strings: builder.writeln() optimization
							parent
							
								
									549d7a487d
								
							
						
					
					
						commit
						d94a02ba79
					
				| 
						 | 
				
			
			@ -32,6 +32,7 @@ pub fn (mut b Builder) write_b(data byte) {
 | 
			
		|||
	b.len++
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[inline]
 | 
			
		||||
pub fn (mut b Builder) write(s string) {
 | 
			
		||||
	if s == '' {
 | 
			
		||||
		return
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +78,7 @@ pub fn (mut b Builder) go_back_to(pos int) {
 | 
			
		|||
	b.len = pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[inline]
 | 
			
		||||
pub fn (mut b Builder) writeln(s string) {
 | 
			
		||||
	// for c in s {
 | 
			
		||||
	// b.buf << c
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3599,9 +3599,8 @@ fn (mut g Gen) write_expr_to_string(expr ast.Expr) string {
 | 
			
		|||
	return g.out.cut_last(g.out.buf.len - pos)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g Gen) start_tmp() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fn (mut g Gen) start_tmp() {
 | 
			
		||||
// }
 | 
			
		||||
// If user is accessing the return value eg. in assigment, pass the variable name.
 | 
			
		||||
// If the user is not using the optional return value. We need to pass a temp var
 | 
			
		||||
// to access its fields (`.ok`, `.error` etc)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
 | 
			
		|||
		g.cur_generic_type = 0
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	//g.cur_fn = it
 | 
			
		||||
	// g.cur_fn = it
 | 
			
		||||
	fn_start_pos := g.out.len
 | 
			
		||||
	msvc_attrs := g.write_fn_attrs()
 | 
			
		||||
	// Live
 | 
			
		||||
| 
						 | 
				
			
			@ -270,7 +270,13 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
 | 
			
		|||
		g.write('$styp $tmp_opt = ')
 | 
			
		||||
	}
 | 
			
		||||
	if node.is_method {
 | 
			
		||||
		g.method_call(node)
 | 
			
		||||
		if node.name == 'writeln' && g.pref.show_cc &&
 | 
			
		||||
			node.args.len > 0 && node.args[0].expr is ast.StringInterLiteral &&
 | 
			
		||||
			g.table.get_type_symbol(node.receiver_type).name == 'strings.Builder' {
 | 
			
		||||
			g.string_inter_literal_sb_optimized(node)
 | 
			
		||||
		} else {
 | 
			
		||||
			g.method_call(node)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		g.fn_call(node)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -138,13 +138,61 @@ fn (mut g Gen) string_literal(node ast.StringLiteral) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// optimize string interpolation in string builders:
 | 
			
		||||
// `sb.writeln('a=$a')` =>
 | 
			
		||||
// `sb.writeln('a='); sb.writeln(a.str())`
 | 
			
		||||
fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) {
 | 
			
		||||
	node := call_expr.args[0].expr as ast.StringInterLiteral
 | 
			
		||||
	// sb_name := g.cur_call_expr.left
 | 
			
		||||
	// g.go_before_stmt(0)
 | 
			
		||||
	g.writeln('// sb inter opt')
 | 
			
		||||
	write := 'writeln'
 | 
			
		||||
	/*
 | 
			
		||||
	if node.vals.len != node.exprs.len {
 | 
			
		||||
		println('NOPE')
 | 
			
		||||
		println(node.vals)
 | 
			
		||||
		println('==========')
 | 
			
		||||
		println(node.exprs)
 | 
			
		||||
	}
 | 
			
		||||
	*/
 | 
			
		||||
	for i, val in node.vals {
 | 
			
		||||
		escaped_val := val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', '\\n', '%', '%%'])
 | 
			
		||||
		// if val == '' {
 | 
			
		||||
		// break
 | 
			
		||||
		// continue
 | 
			
		||||
		// }
 | 
			
		||||
		g.write('strings__Builder_${write}(&')
 | 
			
		||||
		g.expr(call_expr.left)
 | 
			
		||||
		g.write(', tos_lit("')
 | 
			
		||||
		g.write(escaped_val)
 | 
			
		||||
		g.writeln('"));')
 | 
			
		||||
		//
 | 
			
		||||
		if i >= node.exprs.len {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		// if node.expr_types.len <= i || node.exprs.len <= i {
 | 
			
		||||
		// continue
 | 
			
		||||
		// }
 | 
			
		||||
		g.write('strings__Builder_${write}(&')
 | 
			
		||||
		g.expr(call_expr.left)
 | 
			
		||||
		g.write(', ')
 | 
			
		||||
		g.write(g.typ(node.expr_types[i]))
 | 
			
		||||
		g.write('_str(')
 | 
			
		||||
		g.expr(node.exprs[i])
 | 
			
		||||
		g.writeln('));')
 | 
			
		||||
	}
 | 
			
		||||
	g.writeln('')
 | 
			
		||||
	// println(node.vals)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
 | 
			
		||||
	mut cur_line := ''
 | 
			
		||||
	mut tmp := ''
 | 
			
		||||
	free := g.pref.autofree && g.inside_call && !g.inside_return &&
 | 
			
		||||
		g.inside_ternary == 0 && !g.inside_const 
 | 
			
		||||
		//&& g.cur_fn != 0 &&
 | 
			
		||||
		//g.cur_fn.name != ''
 | 
			
		||||
		g.inside_ternary == 0 && !g.inside_const
 | 
			
		||||
	// && g.cur_fn != 0 &&
 | 
			
		||||
	// g.cur_fn.name != ''
 | 
			
		||||
	if free {
 | 
			
		||||
		// Save the string expr in a temporary variable, so that it can be removed after the call.
 | 
			
		||||
		tmp = g.new_tmp_var()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue