autofree: minor fixes; skip in consts
parent
ad940ff40e
commit
2afb9b30e9
|
@ -57,7 +57,7 @@ pub fn load_from_memory(buf byteptr, bufsize int) ?Image {
|
|||
}
|
||||
|
||||
|
||||
pub fn (img Image) free() {
|
||||
pub fn (img &Image) free() {
|
||||
C.stbi_image_free(img.data)
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ pub mut:
|
|||
mod string // current module name
|
||||
is_builtin_mod bool // are we in `builtin`?
|
||||
inside_unsafe bool
|
||||
inside_const bool
|
||||
skip_flags bool // should `#flag` and `#include` be skipped
|
||||
cur_generic_type table.Type
|
||||
mut:
|
||||
|
@ -1028,7 +1029,7 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type {
|
|||
// autofree: mark args that have to be freed (after saving them in tmp exprs)
|
||||
free_tmp_arg_vars := c.pref.autofree && c.pref.experimental && !c.is_builtin_mod &&
|
||||
call_expr.args.len > 0 && !call_expr.args[0].typ.has_flag(.optional)
|
||||
if free_tmp_arg_vars {
|
||||
if free_tmp_arg_vars && !c.inside_const {
|
||||
for i, arg in call_expr.args {
|
||||
if arg.typ != table.string_type {
|
||||
continue
|
||||
|
@ -1896,6 +1897,48 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) const_decl(mut node ast.ConstDecl) {
|
||||
mut field_names := []string{}
|
||||
mut field_order := []int{}
|
||||
for i, field in node.fields {
|
||||
// TODO Check const name once the syntax is decided
|
||||
if field.name in c.const_names {
|
||||
c.error('duplicate const `$field.name`', field.pos)
|
||||
}
|
||||
c.const_names << field.name
|
||||
field_names << field.name
|
||||
field_order << i
|
||||
}
|
||||
mut needs_order := false
|
||||
mut done_fields := []int{}
|
||||
for i, field in node.fields {
|
||||
c.const_decl = field.name
|
||||
c.const_deps << field.name
|
||||
typ := c.expr(field.expr)
|
||||
node.fields[i].typ = c.table.mktyp(typ)
|
||||
for cd in c.const_deps {
|
||||
for j, f in node.fields {
|
||||
if j != i && cd in field_names && cd == f.name && j !in done_fields {
|
||||
needs_order = true
|
||||
x := field_order[j]
|
||||
field_order[j] = field_order[i]
|
||||
field_order[i] = x
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
done_fields << i
|
||||
c.const_deps = []
|
||||
}
|
||||
if needs_order {
|
||||
mut ordered_fields := []ast.ConstField{}
|
||||
for order in field_order {
|
||||
ordered_fields << node.fields[order]
|
||||
}
|
||||
node.fields = ordered_fields
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
||||
c.check_valid_pascal_case(decl.name, 'enum name', decl.pos)
|
||||
mut seen := []int{}
|
||||
|
@ -2421,45 +2464,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||
c.stmts(node.stmts)
|
||||
}
|
||||
ast.ConstDecl {
|
||||
mut field_names := []string{}
|
||||
mut field_order := []int{}
|
||||
for i, field in node.fields {
|
||||
// TODO Check const name once the syntax is decided
|
||||
if field.name in c.const_names {
|
||||
c.error('duplicate const `$field.name`', field.pos)
|
||||
}
|
||||
c.const_names << field.name
|
||||
field_names << field.name
|
||||
field_order << i
|
||||
}
|
||||
mut needs_order := false
|
||||
mut done_fields := []int{}
|
||||
for i, field in node.fields {
|
||||
c.const_decl = field.name
|
||||
c.const_deps << field.name
|
||||
typ := c.expr(field.expr)
|
||||
node.fields[i].typ = c.table.mktyp(typ)
|
||||
for cd in c.const_deps {
|
||||
for j, f in node.fields {
|
||||
if j != i && cd in field_names && cd == f.name && j !in done_fields {
|
||||
needs_order = true
|
||||
x := field_order[j]
|
||||
field_order[j] = field_order[i]
|
||||
field_order[i] = x
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
done_fields << i
|
||||
c.const_deps = []
|
||||
}
|
||||
if needs_order {
|
||||
mut ordered_fields := []ast.ConstField{}
|
||||
for order in field_order {
|
||||
ordered_fields << node.fields[order]
|
||||
}
|
||||
node.fields = ordered_fields
|
||||
}
|
||||
c.inside_const = true
|
||||
c.const_decl(mut node)
|
||||
c.inside_const = false
|
||||
}
|
||||
ast.DeferStmt {
|
||||
c.stmts(node.stmts)
|
||||
|
|
|
@ -2069,8 +2069,16 @@ fn (mut g Gen) autofree_scope_vars(pos int, line_nr int, free_parent_scopes bool
|
|||
// In `builtin` everything is freed manually.
|
||||
return
|
||||
}
|
||||
if pos == -1 {
|
||||
// TODO why can pos be -1?
|
||||
return
|
||||
}
|
||||
// eprintln('> free_scope_vars($pos)')
|
||||
scope := g.file.scope.innermost(pos)
|
||||
if scope.start_pos == 0 {
|
||||
// TODO why can scope.pos be 0? (only outside fns?)
|
||||
return
|
||||
}
|
||||
g.writeln('// autofree_scope_vars(pos=$pos 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)
|
||||
|
@ -3460,9 +3468,15 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
|||
// For if expressions with multiple statements or another if expression inside, it's much
|
||||
// easier to use a temp var, than do C tricks with commas, introduce special vars etc
|
||||
// (as it used to be done).
|
||||
// Always use this in -autofree, since ?: can have tmp expressions that have to be freed.
|
||||
needs_tmp_var := node.is_expr &&
|
||||
(g.pref.autofree || (g.pref.experimental &&
|
||||
(node.branches[0].stmts.len > 1 || node.branches[0].stmts[0] is ast.IfExpr)))
|
||||
/*
|
||||
needs_tmp_var := node.is_expr &&
|
||||
(g.pref.autofree || g.pref.experimental) &&
|
||||
(node.branches[0].stmts.len > 1 || node.branches[0].stmts[0] is ast.IfExpr)
|
||||
*/
|
||||
tmp := if needs_tmp_var { g.new_tmp_var() } else { '' }
|
||||
mut cur_line := ''
|
||||
if needs_tmp_var {
|
||||
|
|
|
@ -647,6 +647,9 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
|
|||
if g.is_js_call {
|
||||
return
|
||||
}
|
||||
if g.inside_const {
|
||||
return
|
||||
}
|
||||
free_tmp_arg_vars = false // set the flag to true only if we have at least one arg to free
|
||||
g.tmp_count2++
|
||||
mut scope := g.file.scope.innermost(node.pos.pos)
|
||||
|
@ -778,7 +781,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
|
|||
break
|
||||
}
|
||||
use_tmp_var_autofree := g.autofree && g.pref.experimental && arg.typ == table.string_type &&
|
||||
arg.is_tmp_autofree
|
||||
arg.is_tmp_autofree && !g.inside_const
|
||||
// g.write('/* af=$arg.is_tmp_autofree */')
|
||||
mut is_interface := false
|
||||
// some c fn definitions dont have args (cfns.v) or are not updated in checker
|
||||
|
|
Loading…
Reference in New Issue