cgen: fix anon_fn redefinition (#8961)
parent
fdc60817d3
commit
c762d150c6
|
@ -300,8 +300,9 @@ pub:
|
|||
// anonymous function
|
||||
pub struct AnonFn {
|
||||
pub mut:
|
||||
decl FnDecl
|
||||
typ table.Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
|
||||
decl FnDecl
|
||||
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
|
||||
|
@ -360,9 +361,8 @@ pub:
|
|||
// function or method call expr
|
||||
pub struct CallExpr {
|
||||
pub:
|
||||
pos token.Position
|
||||
left Expr // `user` in `user.register()`
|
||||
mod string
|
||||
pos token.Position
|
||||
mod string
|
||||
pub mut:
|
||||
name string // left.name()
|
||||
is_method bool
|
||||
|
@ -371,6 +371,7 @@ pub mut:
|
|||
expected_arg_types []table.Type
|
||||
language table.Language
|
||||
or_block OrExpr
|
||||
left Expr // `user` in `user.register()`
|
||||
left_type table.Type // type of `user`
|
||||
receiver_type table.Type // User
|
||||
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('\t$inp_elem_type it = (($inp_elem_type*) ${tmp}_orig.data)[$i];')
|
||||
mut is_embed_map_filter := false
|
||||
expr := node.args[0].expr
|
||||
match expr {
|
||||
mut expr := node.args[0].expr
|
||||
match mut expr {
|
||||
ast.AnonFn {
|
||||
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)')
|
||||
}
|
||||
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('\t$elem_type_str it = (($elem_type_str*) ${tmp}_orig.data)[$i];')
|
||||
mut is_embed_map_filter := false
|
||||
expr := node.args[0].expr
|
||||
match expr {
|
||||
mut expr := node.args[0].expr
|
||||
match mut expr {
|
||||
ast.AnonFn {
|
||||
g.write('\tif (')
|
||||
g.gen_anon_fn_decl(expr)
|
||||
g.gen_anon_fn_decl(mut expr)
|
||||
g.write('${expr.decl.name}(it)')
|
||||
}
|
||||
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) {
|
||||
pos := g.out.len
|
||||
g.stmt(it.decl)
|
||||
fn_body := g.out.after(pos)
|
||||
g.out.go_back(fn_body.len)
|
||||
g.anon_fn_definitions << fn_body
|
||||
fn (mut g Gen) gen_anon_fn_decl(mut node ast.AnonFn) {
|
||||
if !node.has_gen {
|
||||
pos := g.out.len
|
||||
g.stmt(node.decl)
|
||||
fn_body := g.out.after(pos)
|
||||
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) {
|
||||
|
@ -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) {
|
||||
// println('cgen expr() line_nr=$node.pos.line_nr')
|
||||
// NB: please keep the type names in the match here in alphabetical order:
|
||||
match node {
|
||||
match mut node {
|
||||
ast.AnonFn {
|
||||
// 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)
|
||||
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 {
|
||||
mut handle := ''
|
||||
tmp := g.new_tmp_var()
|
||||
expr := node.call_expr
|
||||
mut expr := node.call_expr
|
||||
mut name := expr.name // util.no_dots(expr.name)
|
||||
// TODO: fn call is duplicated. merge with fn_call().
|
||||
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 {
|
||||
receiver_sym := g.table.get_type_symbol(expr.receiver_type)
|
||||
name = receiver_sym.name + '_' + name
|
||||
} else if expr.left is ast.AnonFn {
|
||||
g.gen_anon_fn_decl(expr.left)
|
||||
} else if mut expr.left is ast.AnonFn {
|
||||
g.gen_anon_fn_decl(mut expr.left)
|
||||
fsym := g.table.get_type_symbol(expr.left.typ)
|
||||
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