autofree: handle args in optional returns
parent
ea09bd5e45
commit
25947a7b23
|
@ -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 {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue