cgen: autofree - know where to stop freeing parent scops on continue/break
							parent
							
								
									fafe30b6aa
								
							
						
					
					
						commit
						83f651c29a
					
				|  | @ -286,9 +286,10 @@ pub mut: | |||
| // break, continue
 | ||||
| pub struct BranchStmt { | ||||
| pub: | ||||
| 	kind  token.Kind | ||||
| 	label string | ||||
| 	pos   token.Position | ||||
| 	kind       token.Kind | ||||
| 	label      string | ||||
| 	pos        token.Position | ||||
| 	parent_pos int | ||||
| } | ||||
| 
 | ||||
| pub struct CallExpr { | ||||
|  |  | |||
|  | @ -858,7 +858,8 @@ fn (mut g Gen) stmt(node ast.Stmt) { | |||
| 				// continue or break
 | ||||
| 				if g.pref.autofree && !g.is_builtin_mod { | ||||
| 					g.writeln('// free before continue/break') | ||||
| 					g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, false) | ||||
| 					g.autofree_scope_vars_stop(node.pos.pos - 1, node.pos.line_nr, true, | ||||
| 						node.parent_pos) | ||||
| 				} | ||||
| 				g.writeln('$node.kind;') | ||||
| 			} | ||||
|  | @ -2061,8 +2062,11 @@ fn (mut g Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, ad | |||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // fn (mut g Gen) autofree_scope_vars(pos int, line_nr int) {
 | ||||
| fn (mut g Gen) autofree_scope_vars(pos int, line_nr int, free_parent_scopes bool) { | ||||
| 	g.autofree_scope_vars_stop(pos, line_nr, free_parent_scopes, -1) | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) autofree_scope_vars_stop(pos int, line_nr int, free_parent_scopes bool, stop_pos int) { | ||||
| 	if g.is_builtin_mod { | ||||
| 		// In `builtin` everything is freed manually.
 | ||||
| 		return | ||||
|  | @ -2078,12 +2082,12 @@ fn (mut g Gen) autofree_scope_vars(pos int, line_nr int, free_parent_scopes bool | |||
| 		return | ||||
| 	} | ||||
| 	g.writeln('// autofree_scope_vars(pos=$pos line_nr=$line_nr scope.pos=$scope.start_pos scope.end_pos=$scope.end_pos)') | ||||
| 	// g.autofree_scope_vars2(scope, scope.end_pos)
 | ||||
| 	g.autofree_scope_vars2(scope, scope.start_pos, scope.end_pos, line_nr, free_parent_scopes) | ||||
| 	g.autofree_scope_vars2(scope, scope.start_pos, scope.end_pos, line_nr, free_parent_scopes, | ||||
| 		stop_pos) | ||||
| } | ||||
| 
 | ||||
| // fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, end_pos int) {
 | ||||
| fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int, line_nr int, free_parent_scopes bool) { | ||||
| fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int, line_nr int, free_parent_scopes bool, stop_pos int) { | ||||
| 	if isnil(scope) { | ||||
| 		return | ||||
| 	} | ||||
|  | @ -2129,9 +2133,10 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int | |||
| 	// }
 | ||||
| 	// ```
 | ||||
| 	// if !isnil(scope.parent) && line_nr > 0 {
 | ||||
| 	if free_parent_scopes && !isnil(scope.parent) { | ||||
| 	if free_parent_scopes && !isnil(scope.parent) && | ||||
| 		(stop_pos == -1 || scope.parent.start_pos >= stop_pos) { | ||||
| 		g.writeln('// af parent scope:') | ||||
| 		g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr, true) | ||||
| 		g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr, true, stop_pos) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import v.table | |||
| fn (mut p Parser) for_stmt() ast.Stmt { | ||||
| 	p.check(.key_for) | ||||
| 	pos := p.tok.position() | ||||
| 	p.branch_parent_pos = pos.pos | ||||
| 	p.open_scope() | ||||
| 	p.inside_for = true | ||||
| 	if p.tok.kind == .key_match { | ||||
|  |  | |||
|  | @ -60,6 +60,7 @@ mut: | |||
| 	vet_errors        []string | ||||
| 	cur_fn_name       string | ||||
| 	in_generic_params bool // indicates if parsing between `<` and `>` of a method/function
 | ||||
| 	branch_parent_pos int  // used in BranchStmt (continue/break) autofree stop position
 | ||||
| } | ||||
| 
 | ||||
| // for tests
 | ||||
|  | @ -690,6 +691,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { | |||
| 				kind: tok.kind | ||||
| 				label: label | ||||
| 				pos: tok.position() | ||||
| 				parent_pos: p.branch_parent_pos | ||||
| 			} | ||||
| 		} | ||||
| 		.key_unsafe { | ||||
|  |  | |||
|  | @ -258,17 +258,28 @@ fn free_before_break() { | |||
| 		q := [1, 2, 3] | ||||
| 		break | ||||
| 	} | ||||
| 	/* | ||||
| 	for { | ||||
| 		qq := [1, 2, 3] | ||||
| 		aa := [1, 2, 3] | ||||
| 		if true { | ||||
| 			// breaking should free only vars in the closest for loop's scope
 | ||||
| 			// `qq`, not `s`
 | ||||
| 			break | ||||
| 		} | ||||
| 		// nested 1
 | ||||
| 		for { | ||||
| 			bb := [4, 5, 6] | ||||
| 			if true { | ||||
| 				break | ||||
| 			} | ||||
| 			// nested 2
 | ||||
| 			for { | ||||
| 				cc := [7, 8, 9] | ||||
| 				if true { | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	*/ | ||||
| 	/* | ||||
| 	mut i := 0 | ||||
| 	for { | ||||
| 		i++ | ||||
|  | @ -280,7 +291,6 @@ fn free_before_break() { | |||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 	*/ | ||||
| } | ||||
| 
 | ||||
| struct User { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue