autofree: fix exprs N levels deep

pull/6297/head^2
Alexander Medvednikov 2020-09-06 13:02:29 +02:00
parent 047bf02985
commit 9fbea31f47
5 changed files with 19 additions and 13 deletions

View File

@ -307,7 +307,7 @@ pub:
comments []Comment
pub mut:
typ table.Type
is_tmp_autofree bool // for autofree
is_tmp_autofree bool
// tmp_name string // for autofree
}

View File

@ -99,7 +99,7 @@ mut:
sql_side SqlExprSide // left or right, to distinguish idents in `name == name`
inside_vweb_tmpl bool
inside_return bool
strs_to_free string
strs_to_free []string // strings.Builder
inside_call bool
has_main bool
inside_const bool
@ -725,18 +725,21 @@ fn (mut g Gen) write_v_source_line_info(pos token.Position) {
fn (mut g Gen) stmt(node ast.Stmt) {
g.stmt_path_pos << g.out.len
/*
defer {
// If we have temporary string exprs to free after this statement, do it. e.g.:
// `foo('a' + 'b')` => `tmp := 'a' + 'b'; foo(tmp); string_free(&tmp);`
if g.pref.autofree {
if g.strs_to_free != '' {
g.writeln(g.strs_to_free)
g.strs_to_free = ''
if g.strs_to_free.len != 0 {
g.writeln('// strs_to_free:')
for s in g.strs_to_free {
g.writeln(s)
}
g.strs_to_free = []
// s := g.strs_to_free.str()
// g.strs_to_free.free()
}
}
}
*/
// println('cgen.stmt()')
// g.writeln('//// stmt start')
match node {

View File

@ -632,15 +632,16 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
// g.write(cur_line + ' /* cur line*/')
// g.write(tmp)
// Now free the tmp arg vars right after the function call
g.writeln(';')
g.strs_to_free << (';')
for i, arg in node.args {
if arg.is_tmp_autofree {
fn_name := node.name.replace('.', '_')
tmp := '_tt${g.tmp_count2}_arg_expr_${fn_name}_$i'
g.writeln('string_free(&$tmp);')
g.strs_to_free << ('string_free(&$tmp);')
// g.writeln('string_free(&$tmp);')
}
}
g.writeln('')
// g.writeln('')
}
}

View File

@ -194,11 +194,12 @@ fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) {
fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
mut cur_line := ''
mut tmp := ''
free := !g.pref.experimental && g.pref.autofree && g.inside_call && !g.inside_return &&
free := false && !g.pref.experimental && g.pref.autofree && g.inside_call && !g.inside_return &&
g.inside_ternary == 0 && !g.inside_const
// && g.cur_fn != 0 &&
// g.cur_fn.name != ''
if free {
/*
if false && free {
// Save the string expr in a temporary variable, so that it can be removed after the call.
tmp = g.new_tmp_var()
/*
@ -214,6 +215,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
g.write('string $tmp = ')
g.strs_to_free += 'string_free(&$tmp); /*tmp str*/'
}
*/
g.write('_STR("')
// Build the string with %
mut end_string := false

View File

@ -25,7 +25,7 @@ fn handle_int(n int) {
fn str_tmp_expr() {
println('a' + 'b') // tmp expression result must be freed
handle_strings('c' + 'd', 'e' + 'f') // multiple tmp expressions must be freed
// handle_int(handle_strings('x' + 'y', 'f')) // exprs 2 levels deep must bee freed
handle_int(handle_strings('x' + 'y', 'f')) // exprs 2 levels deep must bee freed
}
struct Foo {