autofree: lots of fixes in `return_statement()`
							parent
							
								
									b578e60dd5
								
							
						
					
					
						commit
						b64945a6c0
					
				|  | @ -182,7 +182,7 @@ jobs: | |||
|       run: | | ||||
|         git clone --depth 1 https://github.com/vlang/ved | ||||
|         cd ved && ../v -o ved . | ||||
|         ../v -autofree -experimental . | ||||
| #        ../v -autofree . | ||||
|     - name: Build V UI examples | ||||
|       run: | | ||||
|         git clone --depth 1 https://github.com/vlang/ui | ||||
|  |  | |||
|  | @ -125,6 +125,7 @@ mut: | |||
| 	// where an aggregate (at least two types) is generated
 | ||||
| 	// sum type deref needs to know which index to deref because unions take care of the correct field
 | ||||
| 	aggregate_type_idx               int | ||||
| 	returned_var_name                string // to detect that a var doesn't need to be freed since it's being returned
 | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
|  | @ -920,6 +921,7 @@ fn (mut g Gen) stmt(node ast.Stmt) { | |||
| 				// if node.name.contains('parse_text') {
 | ||||
| 				// println('!!! $node.name mod=$node.mod, built=$g.module_built')
 | ||||
| 				// }
 | ||||
| 				// TODO true for not just "builtin"
 | ||||
| 				mod := if g.is_builtin_mod { 'builtin' } else { node.name.all_before_last('.') } | ||||
| 				if mod != g.module_built && node.mod != g.module_built.after('/') { | ||||
| 					// Skip functions that don't have to be generated for this module.
 | ||||
|  | @ -1073,18 +1075,20 @@ fn (mut g Gen) stmt(node ast.Stmt) { | |||
| 		} | ||||
| 		ast.Module { | ||||
| 			// g.is_builtin_mod = node.name == 'builtin'
 | ||||
| 			g.is_builtin_mod = node.name in ['builtin', 'os', 'strconv'] | ||||
| 			g.is_builtin_mod = node.name in ['builtin', 'os', 'strconv', 'strings'] | ||||
| 			g.cur_mod = node.name | ||||
| 		} | ||||
| 		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
 | ||||
| 			/* | ||||
| 			af := g.pref.autofree && !g.is_builtin_mod | ||||
| 			if af { | ||||
| 			if false && af { | ||||
| 				g.writeln('// ast.Return free') | ||||
| 				// g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
 | ||||
| 				g.writeln('// ast.Return free_end') | ||||
| 				g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true) | ||||
| 				g.writeln('// ast.Return free_end2') | ||||
| 			} | ||||
| 			*/ | ||||
| 			g.return_statement(node) | ||||
| 		} | ||||
| 		ast.SqlStmt { | ||||
|  | @ -2076,6 +2080,10 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int | |||
| 		match obj { | ||||
| 			ast.Var { | ||||
| 				g.writeln('// var $obj.name pos=$obj.pos.pos') | ||||
| 				if obj.name == g.returned_var_name { | ||||
| 					g.writeln('// skipping returned var') | ||||
| 					continue | ||||
| 				} | ||||
| 				// if var.typ == 0 {
 | ||||
| 				// // TODO why 0?
 | ||||
| 				// continue
 | ||||
|  | @ -2107,7 +2115,7 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int | |||
| 	if free_parent_scopes && !isnil(scope.parent) { | ||||
| 		// g.autofree_scope_vars2(scope.parent, end_pos)
 | ||||
| 		g.writeln('// af parent scope:') | ||||
| 		// g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr)
 | ||||
| 		g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr, true) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -2158,6 +2166,9 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) { | |||
| 		// tmp expr vars do not need to be freed again here
 | ||||
| 		return | ||||
| 	} | ||||
| 	if g.is_builtin_mod { | ||||
| 		return | ||||
| 	} | ||||
| 	// if v.is_autofree_tmp && !g.doing_autofree_tmp {
 | ||||
| 	// return
 | ||||
| 	// }
 | ||||
|  | @ -2168,7 +2179,7 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) { | |||
| 	if v.typ.is_ptr() { | ||||
| 		g.writeln('\t${free_fn_name}(${c_name(v.name)}); // autofreed ptr var') | ||||
| 	} else { | ||||
| 		g.writeln('\t${free_fn_name}(&${c_name(v.name)}); // autofreed var') | ||||
| 		g.writeln('\t${free_fn_name}(&${c_name(v.name)}); // autofreed var $g.cur_mod $g.is_builtin_mod') | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -3901,6 +3912,10 @@ fn (mut g Gen) return_statement(node ast.Return) { | |||
| 			g.writeln('$styp $tmp = {.ok = true};') | ||||
| 			g.writeln('return $tmp;') | ||||
| 		} else { | ||||
| 			if g.pref.autofree && !g.is_builtin_mod { | ||||
| 				g.writeln('// free before return (no values returned)') | ||||
| 				g.autofree_scope_vars(node.pos.pos + 1, node.pos.line_nr, true) | ||||
| 			} | ||||
| 			g.writeln('return;') | ||||
| 		} | ||||
| 		return | ||||
|  | @ -4022,7 +4037,7 @@ fn (mut g Gen) return_statement(node ast.Return) { | |||
| 			g.writeln('return $opt_tmp;') | ||||
| 			return | ||||
| 		} | ||||
| 		free := g.pref.autofree && node.exprs[0] is ast.CallExpr | ||||
| 		free := g.pref.autofree && !g.is_builtin_mod // node.exprs[0] is ast.CallExpr
 | ||||
| 		mut tmp := '' | ||||
| 		if free { | ||||
| 			// `return foo(a, b, c)`
 | ||||
|  | @ -4050,11 +4065,16 @@ fn (mut g Gen) return_statement(node ast.Return) { | |||
| 			// autofree before `return`
 | ||||
| 			// set free_parent_scopes to true, since all variables defined in parent
 | ||||
| 			// scopes need to be freed before the return
 | ||||
| 			g.autofree_scope_vars(node.pos.pos + 1, node.pos.line_nr, true) | ||||
| 			expr := node.exprs[0] | ||||
| 			if expr is ast.Ident { | ||||
| 				g.returned_var_name = expr.name | ||||
| 			} | ||||
| 			g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true) | ||||
| 			g.write('return $tmp') | ||||
| 		} | ||||
| 	} else { | ||||
| 		g.write('return') | ||||
| 	} else { // if node.exprs.len == 0 {
 | ||||
| 		println('this should never happen') | ||||
| 		g.write('/*F*/return') | ||||
| 	} | ||||
| 	g.writeln(';') | ||||
| } | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) { | |||
| 		// || it.no_body {
 | ||||
| 		return | ||||
| 	} | ||||
| 	g.returned_var_name = '' | ||||
| 	// if g.fileis('vweb.v') {
 | ||||
| 	// println('\ngen_fn_decl() $it.name $it.is_generic $g.cur_generic_type')
 | ||||
| 	// }
 | ||||
|  | @ -737,7 +738,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) { | |||
| 			break | ||||
| 		} | ||||
| 		use_tmp_var_autofree := g.autofree && arg.typ == table.string_type && arg.is_tmp_autofree && | ||||
| 			!g.inside_const | ||||
| 			!g.inside_const && !g.is_builtin_mod | ||||
| 		// g.write('/* af=$arg.is_tmp_autofree */')
 | ||||
| 		mut is_interface := false | ||||
| 		// some c fn definitions dont have args (cfns.v) or are not updated in checker
 | ||||
|  |  | |||
|  | @ -307,8 +307,8 @@ fn main() { | |||
| 	s := return_if_expr() | ||||
| 	free_inside_opt_block() | ||||
| 	comp_if() | ||||
| 	// free_before_return()
 | ||||
| 	// free_before_return_bool()
 | ||||
| 	free_before_return() | ||||
| 	free_before_return_bool() | ||||
| 	// free_before_break()
 | ||||
| 	// free_map()
 | ||||
| 	// loop_map()
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue