cgen: fix anon_fn redefinition (#8961)
parent
fdc60817d3
commit
c762d150c6
|
@ -300,8 +300,9 @@ pub:
|
||||||
// anonymous function
|
// anonymous function
|
||||||
pub struct AnonFn {
|
pub struct AnonFn {
|
||||||
pub mut:
|
pub mut:
|
||||||
decl FnDecl
|
decl FnDecl
|
||||||
typ table.Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
|
typ table.Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
|
||||||
|
has_gen bool // has been generated
|
||||||
}
|
}
|
||||||
|
|
||||||
// function or method declaration
|
// function or method declaration
|
||||||
|
@ -360,9 +361,8 @@ pub:
|
||||||
// function or method call expr
|
// function or method call expr
|
||||||
pub struct CallExpr {
|
pub struct CallExpr {
|
||||||
pub:
|
pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
left Expr // `user` in `user.register()`
|
mod string
|
||||||
mod string
|
|
||||||
pub mut:
|
pub mut:
|
||||||
name string // left.name()
|
name string // left.name()
|
||||||
is_method bool
|
is_method bool
|
||||||
|
@ -371,6 +371,7 @@ pub mut:
|
||||||
expected_arg_types []table.Type
|
expected_arg_types []table.Type
|
||||||
language table.Language
|
language table.Language
|
||||||
or_block OrExpr
|
or_block OrExpr
|
||||||
|
left Expr // `user` in `user.register()`
|
||||||
left_type table.Type // type of `user`
|
left_type table.Type // type of `user`
|
||||||
receiver_type table.Type // User
|
receiver_type table.Type // User
|
||||||
return_type table.Type
|
return_type table.Type
|
||||||
|
|
|
@ -150,11 +150,11 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
||||||
g.writeln('for (int $i = 0; $i < ${tmp}_len; ++$i) {')
|
g.writeln('for (int $i = 0; $i < ${tmp}_len; ++$i) {')
|
||||||
g.writeln('\t$inp_elem_type it = (($inp_elem_type*) ${tmp}_orig.data)[$i];')
|
g.writeln('\t$inp_elem_type it = (($inp_elem_type*) ${tmp}_orig.data)[$i];')
|
||||||
mut is_embed_map_filter := false
|
mut is_embed_map_filter := false
|
||||||
expr := node.args[0].expr
|
mut expr := node.args[0].expr
|
||||||
match expr {
|
match mut expr {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.write('\t$ret_elem_type ti = ')
|
g.write('\t$ret_elem_type ti = ')
|
||||||
g.gen_anon_fn_decl(expr)
|
g.gen_anon_fn_decl(mut expr)
|
||||||
g.write('${expr.decl.name}(it)')
|
g.write('${expr.decl.name}(it)')
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
|
@ -324,11 +324,11 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
||||||
g.writeln('for (int $i = 0; $i < ${tmp}_len; ++$i) {')
|
g.writeln('for (int $i = 0; $i < ${tmp}_len; ++$i) {')
|
||||||
g.writeln('\t$elem_type_str it = (($elem_type_str*) ${tmp}_orig.data)[$i];')
|
g.writeln('\t$elem_type_str it = (($elem_type_str*) ${tmp}_orig.data)[$i];')
|
||||||
mut is_embed_map_filter := false
|
mut is_embed_map_filter := false
|
||||||
expr := node.args[0].expr
|
mut expr := node.args[0].expr
|
||||||
match expr {
|
match mut expr {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.write('\tif (')
|
g.write('\tif (')
|
||||||
g.gen_anon_fn_decl(expr)
|
g.gen_anon_fn_decl(mut expr)
|
||||||
g.write('${expr.decl.name}(it)')
|
g.write('${expr.decl.name}(it)')
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
|
|
|
@ -2502,12 +2502,15 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_anon_fn_decl(it ast.AnonFn) {
|
fn (mut g Gen) gen_anon_fn_decl(mut node ast.AnonFn) {
|
||||||
pos := g.out.len
|
if !node.has_gen {
|
||||||
g.stmt(it.decl)
|
pos := g.out.len
|
||||||
fn_body := g.out.after(pos)
|
g.stmt(node.decl)
|
||||||
g.out.go_back(fn_body.len)
|
fn_body := g.out.after(pos)
|
||||||
g.anon_fn_definitions << fn_body
|
g.out.go_back(fn_body.len)
|
||||||
|
g.anon_fn_definitions << fn_body
|
||||||
|
node.has_gen = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) map_fn_ptrs(key_typ table.TypeSymbol) (string, string, string, string) {
|
fn (mut g Gen) map_fn_ptrs(key_typ table.TypeSymbol) (string, string, string, string) {
|
||||||
|
@ -2560,10 +2563,10 @@ fn (mut g Gen) map_fn_ptrs(key_typ table.TypeSymbol) (string, string, string, st
|
||||||
fn (mut g Gen) expr(node ast.Expr) {
|
fn (mut g Gen) expr(node ast.Expr) {
|
||||||
// println('cgen expr() line_nr=$node.pos.line_nr')
|
// println('cgen expr() line_nr=$node.pos.line_nr')
|
||||||
// NB: please keep the type names in the match here in alphabetical order:
|
// NB: please keep the type names in the match here in alphabetical order:
|
||||||
match node {
|
match mut node {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
// TODO: dont fiddle with buffers
|
// TODO: dont fiddle with buffers
|
||||||
g.gen_anon_fn_decl(node)
|
g.gen_anon_fn_decl(mut node)
|
||||||
fsym := g.table.get_type_symbol(node.typ)
|
fsym := g.table.get_type_symbol(node.typ)
|
||||||
g.write(fsym.name)
|
g.write(fsym.name)
|
||||||
}
|
}
|
||||||
|
@ -5877,7 +5880,7 @@ fn (mut g Gen) go_expr(node ast.GoExpr) {
|
||||||
fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
|
fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
|
||||||
mut handle := ''
|
mut handle := ''
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
expr := node.call_expr
|
mut expr := node.call_expr
|
||||||
mut name := expr.name // util.no_dots(expr.name)
|
mut name := expr.name // util.no_dots(expr.name)
|
||||||
// TODO: fn call is duplicated. merge with fn_call().
|
// TODO: fn call is duplicated. merge with fn_call().
|
||||||
for i, generic_type in expr.generic_types {
|
for i, generic_type in expr.generic_types {
|
||||||
|
@ -5893,8 +5896,8 @@ fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
|
||||||
if expr.is_method {
|
if expr.is_method {
|
||||||
receiver_sym := g.table.get_type_symbol(expr.receiver_type)
|
receiver_sym := g.table.get_type_symbol(expr.receiver_type)
|
||||||
name = receiver_sym.name + '_' + name
|
name = receiver_sym.name + '_' + name
|
||||||
} else if expr.left is ast.AnonFn {
|
} else if mut expr.left is ast.AnonFn {
|
||||||
g.gen_anon_fn_decl(expr.left)
|
g.gen_anon_fn_decl(mut expr.left)
|
||||||
fsym := g.table.get_type_symbol(expr.left.typ)
|
fsym := g.table.get_type_symbol(expr.left.typ)
|
||||||
name = fsym.name
|
name = fsym.name
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
const default_logger = Example{}
|
||||||
|
|
||||||
|
struct Example {
|
||||||
|
structs []Another = [Another{}]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Another {
|
||||||
|
function fn (string) = fn (value string) {
|
||||||
|
println('$value')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (e Example) useless() string {
|
||||||
|
return 'ok'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_anon_fn_redefinition() {
|
||||||
|
e1 := Example{}
|
||||||
|
assert e1.useless() == 'ok'
|
||||||
|
e2 := Example{}
|
||||||
|
assert e2.useless() == 'ok'
|
||||||
|
e3 := Example{}
|
||||||
|
assert e3.useless() == 'ok'
|
||||||
|
}
|
Loading…
Reference in New Issue