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