autofree: free arrays on re-assignment

pull/7005/head
Alexander Medvednikov 2020-11-28 15:21:53 +01:00
parent ed39d151b7
commit 57ad943b92
2 changed files with 29 additions and 15 deletions

View File

@ -1538,25 +1538,32 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
} }
// Free the old value assigned to this string var (only if it's `str = [new value]`) // Free the old value assigned to this string var (only if it's `str = [new value]`)
mut af := g.pref.autofree && !g.is_builtin_mod && assign_stmt.op == .assign && assign_stmt.left_types.len == mut af := g.pref.autofree && !g.is_builtin_mod && assign_stmt.op == .assign && assign_stmt.left_types.len ==
1 && assign_stmt.left_types[0] == table.string_type && assign_stmt.left[0] is ast.Ident 1 && assign_stmt.left[0] is ast.Ident
// assign_stmt.left_types[0] in [table.string_type, table.array_type] &&
mut sref_name := '' mut sref_name := ''
mut type_to_free := ''
if af { if af {
ident := assign_stmt.left[0] as ast.Ident first_left_type := assign_stmt.left_types[0]
if ident.name != '_' { first_left_sym := g.table.get_type_symbol(assign_stmt.left_types[0])
/* if first_left_type == table.string_type || first_left_sym.kind == .array {
g.write('string_free(&') type_to_free = if first_left_type == table.string_type { 'string' } else { 'array' }
ident := assign_stmt.left[0] as ast.Ident
if ident.name != '_' {
/*
g.write('string_free(&')
g.expr(assign_stmt.left[0]) g.expr(assign_stmt.left[0])
g.writeln('); // free str on re-assignment') g.writeln('); // free str on re-assignment')
*/ */
sref_name = '_sref$assign_stmt.pos.pos' sref_name = '_sref$assign_stmt.pos.pos'
g.write('string $sref_name = (') // TODO we are copying the entire string here, optimize g.write('$type_to_free $sref_name = (') // TODO we are copying the entire string here, optimize
// we can't just do `.str` since we need the extra data from the string struct // we can't just do `.str` since we need the extra data from the string struct
// doing `&string` is also not an option since the stack memory with the data will be overwritten // doing `&string` is also not an option since the stack memory with the data will be overwritten
g.expr(assign_stmt.left[0]) g.expr(assign_stmt.left[0])
g.writeln('); // free str on re-assignment2') g.writeln('); // free $type_to_free on re-assignment2')
defer { defer {
if af { if af {
g.writeln('string_free(&$sref_name);') g.writeln('${type_to_free}_free(&$sref_name);')
}
} }
} }
} else { } else {

View File

@ -106,6 +106,12 @@ fn reassign_str() {
s = s + '!' // old s ref must be copied and freed after the assignment, since s is still used in the right expr s = s + '!' // old s ref must be copied and freed after the assignment, since s is still used in the right expr
} }
fn reassign_arr() {
mut x := [1, 2, 3]
// x must be freed before the re-assignment
x = [4, 5, 6]
}
fn match_expr() string { fn match_expr() string {
x := 2 x := 2
res := match x { res := match x {
@ -266,6 +272,7 @@ fn main() {
println('start') println('start')
simple() simple()
reassign_str() reassign_str()
reassign_arr()
str_tmp_expr() str_tmp_expr()
str_tmp_expr_advanced() str_tmp_expr_advanced()
str_tmp_expr_advanced_var_decl() str_tmp_expr_advanced_var_decl()