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