autofree: handle more statements
parent
acc85be5ae
commit
55536bb364
|
@ -241,6 +241,8 @@ two ',
|
||||||
four!']
|
four!']
|
||||||
s = strings.join(' ')
|
s = strings.join(' ')
|
||||||
assert s.contains('one') && s.contains('two ') && s.contains('four')
|
assert s.contains('one') && s.contains('two ') && s.contains('four')
|
||||||
|
empty := []string{len:0}
|
||||||
|
assert empty.join('A') == ''
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_clone() {
|
fn test_clone() {
|
||||||
|
@ -906,7 +908,7 @@ fn test_sorter() {
|
||||||
i: 102
|
i: 102
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
cmp := fn (a, b &Ka) int {
|
cmp := fn (a &Ka, b &Ka) int {
|
||||||
return compare_strings(a.s, b.s)
|
return compare_strings(a.s, b.s)
|
||||||
}
|
}
|
||||||
arr.sort_with_compare(cmp)
|
arr.sort_with_compare(cmp)
|
||||||
|
|
|
@ -100,8 +100,8 @@ mut:
|
||||||
inside_vweb_tmpl bool
|
inside_vweb_tmpl bool
|
||||||
inside_return bool
|
inside_return bool
|
||||||
inside_or_block bool
|
inside_or_block bool
|
||||||
|
strs_to_free0 []string // strings.Builder
|
||||||
strs_to_free []string // strings.Builder
|
strs_to_free []string // strings.Builder
|
||||||
// strs_to_free0 []string // strings.Builder
|
|
||||||
inside_call bool
|
inside_call bool
|
||||||
has_main bool
|
has_main bool
|
||||||
inside_const bool
|
inside_const bool
|
||||||
|
@ -111,6 +111,7 @@ mut:
|
||||||
match_sumtype_syms []table.TypeSymbol
|
match_sumtype_syms []table.TypeSymbol
|
||||||
// tmp_arg_vars_to_free []string
|
// tmp_arg_vars_to_free []string
|
||||||
// autofree_pregen map[string]string
|
// autofree_pregen map[string]string
|
||||||
|
// autofree_pregen_buf strings.Builder
|
||||||
// autofree_tmp_vars []string // to avoid redefining the same tmp vars in a single function
|
// autofree_tmp_vars []string // to avoid redefining the same tmp vars in a single function
|
||||||
called_fn_name string
|
called_fn_name string
|
||||||
cur_mod string
|
cur_mod string
|
||||||
|
@ -755,6 +756,9 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
defer {
|
defer {
|
||||||
// If we have temporary string exprs to free after this statement, do it. e.g.:
|
// 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);`
|
// `foo('a' + 'b')` => `tmp := 'a' + 'b'; foo(tmp); string_free(&tmp);`
|
||||||
|
if g.pref.autofree {
|
||||||
|
g.autofree_call_postgen()
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
if g.pref.autofree { // && !g.inside_or_block {
|
if g.pref.autofree { // && !g.inside_or_block {
|
||||||
// TODO remove the inside_or_block hack. strings are not freed in or{} atm
|
// TODO remove the inside_or_block hack. strings are not freed in or{} atm
|
||||||
|
@ -835,14 +839,14 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
g.write_v_source_line_info(node.pos)
|
g.write_v_source_line_info(node.pos)
|
||||||
af := g.pref.autofree && node.expr is ast.CallExpr && !g.is_builtin_mod
|
// af := g.pref.autofree && node.expr is ast.CallExpr && !g.is_builtin_mod
|
||||||
if af {
|
// if af {
|
||||||
g.autofree_call_pregen(node.expr as ast.CallExpr)
|
// g.autofree_call_pregen(node.expr as ast.CallExpr)
|
||||||
}
|
// }
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
if af {
|
// if af {
|
||||||
g.autofree_call_postgen()
|
// g.autofree_call_postgen()
|
||||||
}
|
// }
|
||||||
if g.inside_ternary == 0 && !node.is_expr && !(node.expr is ast.IfExpr) {
|
if g.inside_ternary == 0 && !node.is_expr && !(node.expr is ast.IfExpr) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -1011,9 +1015,9 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
af := g.pref.autofree && node.exprs.len > 0 && node.exprs[0] is ast.CallExpr && !g.is_builtin_mod
|
af := g.pref.autofree && node.exprs.len > 0 && node.exprs[0] is ast.CallExpr && !g.is_builtin_mod
|
||||||
if g.pref.autofree {
|
if g.pref.autofree {
|
||||||
g.writeln('// ast.Return free')
|
g.writeln('// ast.Return free')
|
||||||
if af {
|
// if af {
|
||||||
g.autofree_call_pregen(node.exprs[0] as ast.CallExpr)
|
// g.autofree_call_pregen(node.exprs[0] as ast.CallExpr)
|
||||||
}
|
// }
|
||||||
// g.autofree_scope_vars(node.pos.pos)
|
// g.autofree_scope_vars(node.pos.pos)
|
||||||
g.write_autofree_stmts_when_needed(node)
|
g.write_autofree_stmts_when_needed(node)
|
||||||
}
|
}
|
||||||
|
@ -1390,11 +1394,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Autofree tmp arg vars
|
// Autofree tmp arg vars
|
||||||
first_right := assign_stmt.right[0]
|
// first_right := assign_stmt.right[0]
|
||||||
af := g.pref.autofree && first_right is ast.CallExpr && !g.is_builtin_mod
|
// af := g.pref.autofree && first_right is ast.CallExpr && !g.is_builtin_mod
|
||||||
if af {
|
// if af {
|
||||||
g.autofree_call_pregen(first_right as ast.CallExpr)
|
// g.autofree_call_pregen(first_right as ast.CallExpr)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
//
|
//
|
||||||
// Handle optionals. We need to declare a temp variable for them, that's why they are handled
|
// Handle optionals. We need to declare a temp variable for them, that's why they are handled
|
||||||
// here, not in call_expr().
|
// here, not in call_expr().
|
||||||
|
@ -1422,9 +1427,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
gen_or = true
|
gen_or = true
|
||||||
g.or_block(tmp_opt, call_expr.or_block, call_expr.return_type)
|
g.or_block(tmp_opt, call_expr.or_block, call_expr.return_type)
|
||||||
g.writeln('/*=============ret*/')
|
g.writeln('/*=============ret*/')
|
||||||
if af && is_optional {
|
// if af && is_optional {
|
||||||
g.autofree_call_postgen()
|
// g.autofree_call_postgen()
|
||||||
}
|
// }
|
||||||
// return
|
// return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1987,7 +1992,15 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
// if g.fileis('1.strings') {
|
// if g.fileis('1.strings') {
|
||||||
// println('before:' + node.autofree_pregen)
|
// println('before:' + node.autofree_pregen)
|
||||||
// }
|
// }
|
||||||
if g.pref.autofree {
|
if g.pref.autofree && !g.is_builtin_mod && g.strs_to_free0.len == 0 {
|
||||||
|
// if len != 0, that means we are handling call expr inside call expr (arg)
|
||||||
|
// and it'll get messed up here, since it's handled recursively in autofree_call_pregen()
|
||||||
|
// so just skip it
|
||||||
|
g.autofree_call_pregen(node)
|
||||||
|
if g.strs_to_free0.len > 0 {
|
||||||
|
g.insert_before_stmt(g.strs_to_free0.join('\n'))
|
||||||
|
}
|
||||||
|
g.strs_to_free0 = []
|
||||||
// println('pos=$node.pos.pos')
|
// println('pos=$node.pos.pos')
|
||||||
}
|
}
|
||||||
// if g.pref.autofree && node.autofree_pregen != '' { // g.strs_to_free0.len != 0 {
|
// if g.pref.autofree && node.autofree_pregen != '' { // g.strs_to_free0.len != 0 {
|
||||||
|
|
|
@ -620,7 +620,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
|
fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
|
||||||
g.writeln('// autofree_call()')
|
// g.writeln('// autofree_call_pregen()')
|
||||||
// Create a temporary var before fn call for each argument in order to free it (only if it's a complex expression,
|
// Create a temporary var before fn call for each argument in order to free it (only if it's a complex expression,
|
||||||
// like `foo(get_string())` or `foo(a + b)`
|
// like `foo(get_string())` or `foo(a + b)`
|
||||||
mut free_tmp_arg_vars := g.autofree && g.pref.experimental && !g.is_builtin_mod &&
|
mut free_tmp_arg_vars := g.autofree && g.pref.experimental && !g.is_builtin_mod &&
|
||||||
|
@ -648,19 +648,22 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
|
||||||
// g.called_fn_name = name
|
// g.called_fn_name = name
|
||||||
// used := t in g.autofree_tmp_vars
|
// used := t in g.autofree_tmp_vars
|
||||||
used := scope.known_var(t)
|
used := scope.known_var(t)
|
||||||
if used {
|
mut s := if used {
|
||||||
g.write('$t = ')
|
'$t = '
|
||||||
} else {
|
} else {
|
||||||
g.write('string $t = ')
|
|
||||||
scope.register(t, ast.Var{
|
scope.register(t, ast.Var{
|
||||||
name: t
|
name: t
|
||||||
typ: table.string_type
|
typ: table.string_type
|
||||||
is_arg: true // TODO hack so that it's not freed twice when out of scope. it's probably better to use one model
|
is_arg: true // TODO hack so that it's not freed twice when out of scope. it's probably better to use one model
|
||||||
})
|
})
|
||||||
|
'string $t = '
|
||||||
// g.autofree_tmp_vars << t
|
// g.autofree_tmp_vars << t
|
||||||
}
|
}
|
||||||
g.expr(arg.expr)
|
// g.expr(arg.expr)
|
||||||
g.writeln(';// new af pre')
|
s += g.write_expr_to_string(arg.expr)
|
||||||
|
// g.writeln(';// new af pre')
|
||||||
|
s += ';// new af2 pre'
|
||||||
|
g.strs_to_free0 << s
|
||||||
// Now free the tmp arg vars right after the function call
|
// Now free the tmp arg vars right after the function call
|
||||||
g.strs_to_free << t
|
g.strs_to_free << t
|
||||||
// g.strs_to_free << 'string_free(&$t);'
|
// g.strs_to_free << 'string_free(&$t);'
|
||||||
|
|
|
@ -13,14 +13,14 @@ fn foo() {
|
||||||
// nums.free() // this should result in a double free and a CI error
|
// nums.free() // this should result in a double free and a CI error
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_strings(s, p string) int {
|
fn handle_strings(s string, p string) int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_int(n int) {
|
fn handle_int(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_strings(a, b string) string {
|
fn add_strings(a string, b string) string {
|
||||||
return a + b
|
return a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +120,25 @@ fn optional_return() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_string(s string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_cond() {
|
||||||
|
// handle_string('1' + '2')
|
||||||
|
if handle_string('1' + '2') {
|
||||||
|
// if '1' + '2' == '12' {
|
||||||
|
println('yes')
|
||||||
|
} else {
|
||||||
|
println('no')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addition_with_tmp_expr() {
|
||||||
|
x := 1 + handle_strings('a' + 'b', 'c')
|
||||||
|
println(x)
|
||||||
|
}
|
||||||
|
|
||||||
fn tt() {
|
fn tt() {
|
||||||
// time.parse_rfc2822('1234')
|
// time.parse_rfc2822('1234')
|
||||||
}
|
}
|
||||||
|
@ -136,6 +155,8 @@ fn main() {
|
||||||
optional_str()
|
optional_str()
|
||||||
optional_return()
|
optional_return()
|
||||||
// str_replace()
|
// str_replace()
|
||||||
|
if_cond()
|
||||||
|
addition_with_tmp_expr()
|
||||||
println('end')
|
println('end')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue