autofree: fix `or {}`; ci: bring back gitly -autofree

pull/7119/head
Alexander Medvednikov 2020-12-04 18:06:53 +01:00
parent 3f2133c65e
commit 0ea2fa228f
5 changed files with 29 additions and 16 deletions

View File

@ -170,7 +170,7 @@ jobs:
run: ./v -silent build-examples run: ./v -silent build-examples
- name: Build examples with -autofree - name: Build examples with -autofree
run: | run: |
./v -autofree -experimental -o tetris examples/tetris/tetris.v ./v -autofree -o tetris examples/tetris/tetris.v
- name: v doctor - name: v doctor
run: | run: |
./v doctor ./v doctor
@ -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 . ../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
@ -538,6 +538,7 @@ jobs:
git clone --depth 1 https://github.com/vlang/gitly git clone --depth 1 https://github.com/vlang/gitly
cd gitly cd gitly
../v . ../v .
../v -autofree .
cd .. cd ..
websocket_autobahn: websocket_autobahn:

View File

@ -311,9 +311,6 @@ pub mut:
generic_type table.Type // TODO array, to support multiple types generic_type table.Type // TODO array, to support multiple types
generic_list_pos token.Position generic_list_pos token.Position
free_receiver bool // true if the receiver expression needs to be freed free_receiver bool // true if the receiver expression needs to be freed
// autofree_pregen string
// autofree_vars []AutofreeArgVar
// autofree_vars_ids []int
} }
/* /*
@ -371,6 +368,8 @@ pub mut:
pos token.Position pos token.Position
is_used bool is_used bool
is_changed bool // to detect mutable vars that are never changed is_changed bool // to detect mutable vars that are never changed
is_or bool // `x := foo() or { ... }`
// (for setting the position after the or block for autofree)
} }
// used for smartcasting only // used for smartcasting only

View File

@ -1079,7 +1079,7 @@ 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', 'strings'] g.is_builtin_mod = node.name in ['builtin', 'os', 'strconv', 'strings', 'gg']
g.cur_mod = node.name g.cur_mod = node.name
} }
ast.Return { ast.Return {
@ -2070,7 +2070,7 @@ fn (mut g Gen) autofree_scope_vars(pos int, line_nr int, free_parent_scopes bool
// TODO why can scope.pos be 0? (only outside fns?) // TODO why can scope.pos be 0? (only outside fns?)
return return
} }
g.writeln('// autofree_scope_vars(pos=$pos 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.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)
} }
@ -2083,11 +2083,16 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
for _, obj in scope.objects { for _, obj in scope.objects {
match obj { match obj {
ast.Var { ast.Var {
g.writeln('// var $obj.name pos=$obj.pos.pos') g.writeln('// var "$obj.name" var.pos=$obj.pos.pos var.line_nr=$obj.pos.line_nr')
if obj.name == g.returned_var_name { if obj.name == g.returned_var_name {
g.writeln('// skipping returned var') g.writeln('// skipping returned var')
continue continue
} }
if obj.is_or {
// Skip vars inited with the `or {}`, since they are generated
// after the or block in C.
continue
}
// if var.typ == 0 { // if var.typ == 0 {
// // TODO why 0? // // TODO why 0?
// continue // continue
@ -2117,7 +2122,6 @@ 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) {
// 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, true) g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr, true)
} }
@ -3918,7 +3922,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
} else { } else {
if g.pref.autofree && !g.is_builtin_mod { if g.pref.autofree && !g.is_builtin_mod {
g.writeln('// free before return (no values returned)') g.writeln('// free before return (no values returned)')
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('return;') g.writeln('return;')
} }

View File

@ -423,7 +423,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
} else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name != 'str' { } else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name != 'str' {
g.write('/*rec*/*') g.write('/*rec*/*')
} }
if node.free_receiver && !g.inside_lambda { if node.free_receiver && !g.inside_lambda && !g.is_builtin_mod {
// The receiver expression needs to be freed, use the temp var. // The receiver expression needs to be freed, use the temp var.
fn_name := node.name.replace('.', '_') fn_name := node.name.replace('.', '_')
arg_name := '_arg_expr_${fn_name}_0_$node.pos.pos' arg_name := '_arg_expr_${fn_name}_0_$node.pos.pos'
@ -652,7 +652,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
} else { } else {
scope.register(ast.Var{ scope.register(ast.Var{
name: t name: t
typ: table.string_type // is_arg: true // TODO hack so that it's not freed twice when out of scope. it's probably better to use one model typ: table.string_type
is_autofree_tmp: true is_autofree_tmp: true
}) })
s = 'string $t = ' s = 'string $t = '
@ -662,10 +662,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
// g.writeln(';// new af pre') // g.writeln(';// new af pre')
s += ';// new af2 pre' s += ';// new af2 pre'
g.strs_to_free0 << s g.strs_to_free0 << s
// Now free the tmp arg vars right after the function call // This tmp arg var will be freed with the rest of the vars at the end of the scope.
// g.strs_to_free << t
// g.nr_vars_to_free++
// g.strs_to_free << 'string_free(&$t);'
} }
} }

View File

@ -131,6 +131,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
is_static = true is_static = true
} }
} }
r0 := right[0]
mut v := ast.Var{ mut v := ast.Var{
name: lx.name name: lx.name
expr: if left.len == right.len { right[i] } else { ast.Expr{} } expr: if left.len == right.len { right[i] } else { ast.Expr{} }
@ -138,6 +139,17 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
is_mut: lx.is_mut || p.inside_for is_mut: lx.is_mut || p.inside_for
pos: lx.pos pos: lx.pos
} }
if p.pref.autofree {
if r0 is ast.CallExpr {
// Set correct variable position (after the or block)
// so that autofree doesn't free it in cgen before
// it's declared. (`Or` variables are declared after the or block).
if r0.or_block.pos.pos > 0 {
v.is_or = true
// v.pos = r0.or_block.pos.
}
}
}
obj := ast.ScopeObject(v) obj := ast.ScopeObject(v)
lx.obj = obj lx.obj = obj
p.scope.register(obj) p.scope.register(obj)