cgen: fix anon_fn redefinition (#8961)
							parent
							
								
									fdc60817d3
								
							
						
					
					
						commit
						c762d150c6
					
				| 
						 | 
				
			
			@ -302,6 +302,7 @@ pub struct AnonFn {
 | 
			
		|||
pub mut:
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +362,6 @@ pub:
 | 
			
		|||
pub struct CallExpr {
 | 
			
		||||
pub:
 | 
			
		||||
	pos token.Position
 | 
			
		||||
	left Expr // `user` in `user.register()`
 | 
			
		||||
	mod string
 | 
			
		||||
pub mut:
 | 
			
		||||
	name               string // left.name()
 | 
			
		||||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
fn (mut g Gen) gen_anon_fn_decl(mut node ast.AnonFn) {
 | 
			
		||||
	if !node.has_gen {
 | 
			
		||||
		pos := g.out.len
 | 
			
		||||
	g.stmt(it.decl)
 | 
			
		||||
		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