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