cgen: autofree - know where to stop freeing parent scops on continue/break
							parent
							
								
									fafe30b6aa
								
							
						
					
					
						commit
						83f651c29a
					
				| 
						 | 
				
			
			@ -289,6 +289,7 @@ pub:
 | 
			
		|||
	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