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
should_be_skipped bool
generic_type table.Type // TODO array, to support multiple types
autofree_pregen string
// autofree_pregen string
// autofree_vars []AutofreeArgVar
// autofree_vars_ids []int
}
@ -593,20 +593,20 @@ pub:
pub struct ForInStmt {
pub:
key_var string
val_var string
cond Expr
is_range bool
high Expr // `10` in `for i in 0..10 {`
stmts []Stmt
pos token.Position
key_var string
val_var string
cond Expr
is_range bool
high Expr // `10` in `for i in 0..10 {`
stmts []Stmt
pos token.Position
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:
key_type table.Type
val_type table.Type
cond_type table.Type
kind table.Kind // array/map/string
// and the array cannot be indexed inside the loop
key_type table.Type
val_type table.Type
cond_type table.Type
kind table.Kind // array/map/string
}
pub struct ForCStmt {
@ -989,11 +989,7 @@ pub fn (expr Expr) position() token.Position {
AnonFn {
return expr.decl.pos
}
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 {
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 {
return expr.pos
}
InfixExpr {
@ -1042,11 +1038,15 @@ pub fn (expr Expr) is_expr() bool {
}
// 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 {
AssignStmt {return}
AssignStmt {
return
}
ExprStmt {
if stmt.expr.is_expr() {return}
if stmt.expr.is_expr() {
return
}
return error('unsupported statement (`${typeof(stmt.expr)}`)')
}
else {}
@ -1056,10 +1056,7 @@ pub fn (stmt Stmt) check_c_expr()? {
pub fn (stmt Stmt) position() token.Position {
match stmt {
AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl,
ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl {
return stmt.pos
}
AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl { return stmt.pos }
/*
Attr {}
BranchStmt {}

View File

@ -985,12 +985,16 @@ fn (mut g Gen) stmt(node ast.Stmt) {
}
ast.Return {
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 {
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.write_autofree_stmts_when_needed(node)
}
g.return_statement(node)
g.return_statement(node, af)
}
ast.SqlStmt {
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)
if node.exprs.len > 0 {
// skip `retun $vweb.html()`
@ -3496,6 +3500,10 @@ fn (mut g Gen) return_statement(node ast.Return) {
g.write('Option $tmp = ')
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
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)
g.writeln('return *($styp*)&$tmp;')
return

View File

@ -109,6 +109,20 @@ fn optional_str() {
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() {
// time.parse_rfc2822('1234')
}
@ -123,6 +137,7 @@ fn main() {
match_expr()
reassign_str()
optional_str()
optional_return()
// str_replace()
println('end')
}