autofree: handle args in optional returns

pull/6616/head
Alexander Medvednikov 2020-10-14 13:23:58 +02:00
parent ea09bd5e45
commit 25947a7b23
3 changed files with 47 additions and 27 deletions

View File

@ -287,7 +287,7 @@ pub mut:
return_type table.Type return_type table.Type
should_be_skipped bool should_be_skipped bool
generic_type table.Type // TODO array, to support multiple types generic_type table.Type // TODO array, to support multiple types
autofree_pregen string // autofree_pregen string
// autofree_vars []AutofreeArgVar // autofree_vars []AutofreeArgVar
// autofree_vars_ids []int // autofree_vars_ids []int
} }
@ -593,20 +593,20 @@ pub:
pub struct ForInStmt { pub struct ForInStmt {
pub: pub:
key_var string key_var string
val_var string val_var string
cond Expr cond Expr
is_range bool is_range bool
high Expr // `10` in `for i in 0..10 {` high Expr // `10` in `for i in 0..10 {`
stmts []Stmt stmts []Stmt
pos token.Position pos token.Position
val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array
// and the array cannot be indexed inside the loop
pub mut: pub mut:
key_type table.Type // and the array cannot be indexed inside the loop
val_type table.Type key_type table.Type
cond_type table.Type val_type table.Type
kind table.Kind // array/map/string cond_type table.Type
kind table.Kind // array/map/string
} }
pub struct ForCStmt { pub struct ForCStmt {
@ -989,11 +989,7 @@ pub fn (expr Expr) position() token.Position {
AnonFn { AnonFn {
return expr.decl.pos return expr.decl.pos
} }
ArrayInit, AsCast, Assoc, BoolLiteral, CallExpr, CastExpr, CharLiteral, ArrayInit, AsCast, Assoc, BoolLiteral, CallExpr, CastExpr, CharLiteral, Comment, EnumVal, FloatLiteral, Ident, IfExpr, IndexExpr, IntegerLiteral, MapInit, MatchExpr, None, PostfixExpr, PrefixExpr, SelectExpr, SelectorExpr, SizeOf, StringLiteral, StringInterLiteral, StructInit, Likely {
Comment, EnumVal, FloatLiteral, Ident, IfExpr, IndexExpr,
IntegerLiteral, MapInit, MatchExpr, None, PostfixExpr, PrefixExpr,
SelectExpr, SelectorExpr, SizeOf, StringLiteral, StringInterLiteral,
StructInit, Likely {
return expr.pos return expr.pos
} }
InfixExpr { InfixExpr {
@ -1042,11 +1038,15 @@ pub fn (expr Expr) is_expr() bool {
} }
// check if stmt can be an expression in C // check if stmt can be an expression in C
pub fn (stmt Stmt) check_c_expr()? { pub fn (stmt Stmt) check_c_expr() ? {
match stmt { match stmt {
AssignStmt {return} AssignStmt {
return
}
ExprStmt { ExprStmt {
if stmt.expr.is_expr() {return} if stmt.expr.is_expr() {
return
}
return error('unsupported statement (`${typeof(stmt.expr)}`)') return error('unsupported statement (`${typeof(stmt.expr)}`)')
} }
else {} else {}
@ -1056,10 +1056,7 @@ pub fn (stmt Stmt) check_c_expr()? {
pub fn (stmt Stmt) position() token.Position { pub fn (stmt Stmt) position() token.Position {
match stmt { match stmt {
AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl, AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl { return stmt.pos }
ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl {
return stmt.pos
}
/* /*
Attr {} Attr {}
BranchStmt {} BranchStmt {}

View File

@ -985,12 +985,16 @@ fn (mut g Gen) stmt(node ast.Stmt) {
} }
ast.Return { ast.Return {
g.write_defer_stmts_when_needed() g.write_defer_stmts_when_needed()
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 {
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)
} }
g.return_statement(node) g.return_statement(node, af)
} }
ast.SqlStmt { ast.SqlStmt {
g.sql_stmt(node) g.sql_stmt(node)
@ -3458,7 +3462,7 @@ fn (g &Gen) expr_is_multi_return_call(expr ast.Expr) bool {
} }
} }
fn (mut g Gen) return_statement(node ast.Return) { fn (mut g Gen) return_statement(node ast.Return, af bool) {
g.write_v_source_line_info(node.pos) g.write_v_source_line_info(node.pos)
if node.exprs.len > 0 { if node.exprs.len > 0 {
// skip `retun $vweb.html()` // skip `retun $vweb.html()`
@ -3496,6 +3500,10 @@ fn (mut g Gen) return_statement(node ast.Return) {
g.write('Option $tmp = ') g.write('Option $tmp = ')
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
g.writeln(';') g.writeln(';')
if af {
// free the tmp arg expr if we have one before the return
g.autofree_call_postgen()
}
styp := g.typ(g.fn_decl.return_type) styp := g.typ(g.fn_decl.return_type)
g.writeln('return *($styp*)&$tmp;') g.writeln('return *($styp*)&$tmp;')
return return

View File

@ -109,6 +109,20 @@ fn optional_str() {
println(pos + 1) println(pos + 1)
} }
fn return_error_with_freed_expr() ?string {
if true {
msg := 'oops'
return error('hm $msg')
}
return 'ok'
}
fn optional_return() {
return_error_with_freed_expr() or {
return
}
}
fn tt() { fn tt() {
// time.parse_rfc2822('1234') // time.parse_rfc2822('1234')
} }
@ -123,6 +137,7 @@ fn main() {
match_expr() match_expr()
reassign_str() reassign_str()
optional_str() optional_str()
optional_return()
// str_replace() // str_replace()
println('end') println('end')
} }