1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: autofree - know where to stop freeing parent scops on continue/break

This commit is contained in:
joe-conigliaro 2020-12-06 02:36:27 +11:00
parent fafe30b6aa
commit 83f651c29a
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
5 changed files with 34 additions and 15 deletions

View File

@ -286,9 +286,10 @@ pub mut:
// break, continue // break, continue
pub struct BranchStmt { pub struct BranchStmt {
pub: pub:
kind token.Kind kind token.Kind
label string label string
pos token.Position pos token.Position
parent_pos int
} }
pub struct CallExpr { pub struct CallExpr {

View File

@ -858,7 +858,8 @@ fn (mut g Gen) stmt(node ast.Stmt) {
// continue or break // continue or break
if g.pref.autofree && !g.is_builtin_mod { if g.pref.autofree && !g.is_builtin_mod {
g.writeln('// free before continue/break') 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;') 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 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) { 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 { if g.is_builtin_mod {
// In `builtin` everything is freed manually. // In `builtin` everything is freed manually.
return return
@ -2078,12 +2082,12 @@ fn (mut g Gen) autofree_scope_vars(pos int, line_nr int, free_parent_scopes bool
return return
} }
g.writeln('// autofree_scope_vars(pos=$pos line_nr=$line_nr scope.pos=$scope.start_pos scope.end_pos=$scope.end_pos)') 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, 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) { if isnil(scope) {
return 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 !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.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)
} }
} }

View File

@ -9,6 +9,7 @@ import v.table
fn (mut p Parser) for_stmt() ast.Stmt { fn (mut p Parser) for_stmt() ast.Stmt {
p.check(.key_for) p.check(.key_for)
pos := p.tok.position() pos := p.tok.position()
p.branch_parent_pos = pos.pos
p.open_scope() p.open_scope()
p.inside_for = true p.inside_for = true
if p.tok.kind == .key_match { if p.tok.kind == .key_match {

View File

@ -60,6 +60,7 @@ mut:
vet_errors []string vet_errors []string
cur_fn_name string cur_fn_name string
in_generic_params bool // indicates if parsing between `<` and `>` of a method/function 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 // for tests
@ -690,6 +691,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
kind: tok.kind kind: tok.kind
label: label label: label
pos: tok.position() pos: tok.position()
parent_pos: p.branch_parent_pos
} }
} }
.key_unsafe { .key_unsafe {

View File

@ -258,17 +258,28 @@ fn free_before_break() {
q := [1, 2, 3] q := [1, 2, 3]
break break
} }
/*
for { for {
qq := [1, 2, 3] aa := [1, 2, 3]
if true { if true {
// breaking should free only vars in the closest for loop's scope // breaking should free only vars in the closest for loop's scope
// `qq`, not `s` // `qq`, not `s`
break break
} }
// nested 1
for {
bb := [4, 5, 6]
if true {
break
}
// nested 2
for {
cc := [7, 8, 9]
if true {
break
}
}
}
} }
*/
/*
mut i := 0 mut i := 0
for { for {
i++ i++
@ -280,7 +291,6 @@ fn free_before_break() {
continue continue
} }
} }
*/
} }
struct User { struct User {