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