cgen: fix `cannot take rvalue` error of interface (#10040)
							parent
							
								
									e0a3c5384f
								
							
						
					
					
						commit
						a9435f3c25
					
				|  | @ -1768,6 +1768,26 @@ fn (mut g Gen) write_sumtype_casting_fn(got_ ast.Type, exp_ ast.Type) { | |||
| 	g.auto_fn_definitions << sb.str() | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) call_cfn_for_casting_expr(fname string, expr ast.Expr, exp_is_ptr bool, exp_styp string, got_is_ptr bool, got_styp string) { | ||||
| 	mut rparen_n := 1 | ||||
| 	if exp_is_ptr { | ||||
| 		g.write('HEAP($exp_styp, ') | ||||
| 		rparen_n++ | ||||
| 	} | ||||
| 	g.write('${fname}(') | ||||
| 	if !got_is_ptr { | ||||
| 		if !expr.is_lvalue() | ||||
| 			|| (expr is ast.Ident && is_simple_define_const((expr as ast.Ident).obj)) { | ||||
| 			g.write('ADDR($got_styp, (') | ||||
| 			rparen_n += 2 | ||||
| 		} else { | ||||
| 			g.write('&') | ||||
| 		} | ||||
| 	} | ||||
| 	g.expr(expr) | ||||
| 	g.write(')'.repeat(rparen_n)) | ||||
| } | ||||
| 
 | ||||
| // use instead of expr() when you need to cast to a different type
 | ||||
| fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_type ast.Type) { | ||||
| 	got_type := g.table.mktyp(got_type_raw) | ||||
|  | @ -1787,18 +1807,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ | |||
| 		&& !expected_type.has_flag(.optional) { | ||||
| 		got_styp := g.cc_type(got_type, true) | ||||
| 		exp_styp := g.cc_type(expected_type, true) | ||||
| 		if expected_is_ptr { | ||||
| 			g.write('HEAP($exp_styp, ') | ||||
| 		} | ||||
| 		g.write('I_${got_styp}_to_Interface_${exp_styp}(') | ||||
| 		if !got_is_ptr { | ||||
| 			g.write('&') | ||||
| 		} | ||||
| 		g.expr(expr) | ||||
| 		g.write(')') | ||||
| 		if expected_is_ptr { | ||||
| 			g.write(')') | ||||
| 		} | ||||
| 		fname := 'I_${got_styp}_to_Interface_$exp_styp' | ||||
| 		g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr, | ||||
| 			got_styp) | ||||
| 		return | ||||
| 	} | ||||
| 	// cast to sum type
 | ||||
|  | @ -1827,21 +1838,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ | |||
| 				g.expr(expr) | ||||
| 			} else { | ||||
| 				g.write_sumtype_casting_fn(got_type, expected_type) | ||||
| 				if expected_is_ptr { | ||||
| 					g.write('HEAP($exp_sym.cname, ') | ||||
| 				} | ||||
| 				g.write('${got_sym.cname}_to_sumtype_${exp_sym.cname}(') | ||||
| 				if !got_is_ptr { | ||||
| 					g.write('ADDR($got_styp, (') | ||||
| 					g.expr(expr) | ||||
| 					g.write(')))') | ||||
| 				} else { | ||||
| 					g.expr(expr) | ||||
| 					g.write(')') | ||||
| 				} | ||||
| 				if expected_is_ptr { | ||||
| 					g.write(')') | ||||
| 				} | ||||
| 				fname := '${got_sym.cname}_to_sumtype_$exp_sym.cname' | ||||
| 				g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_sym.cname, | ||||
| 					got_is_ptr, got_styp) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
|  | @ -5113,11 +5112,6 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { | |||
| 		*/ | ||||
| 		field_expr := field.expr | ||||
| 		match field.expr { | ||||
| 			ast.CharLiteral, ast.FloatLiteral, ast.IntegerLiteral { | ||||
| 				// "Simple" expressions are not going to need multiple statements,
 | ||||
| 				// only the ones which are inited later, so it's safe to use expr_string
 | ||||
| 				g.const_decl_simple_define(name, g.expr_string(field_expr)) | ||||
| 			} | ||||
| 			ast.ArrayInit { | ||||
| 				if field.expr.is_fixed { | ||||
| 					styp := g.typ(field.expr.typ) | ||||
|  | @ -5147,10 +5141,26 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { | |||
| 				} | ||||
| 			} | ||||
| 			else { | ||||
| 				if is_simple_define_const(field) { | ||||
| 					// "Simple" expressions are not going to need multiple statements,
 | ||||
| 					// only the ones which are inited later, so it's safe to use expr_string
 | ||||
| 					g.const_decl_simple_define(name, g.expr_string(field_expr)) | ||||
| 				} else { | ||||
| 					g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn is_simple_define_const(obj ast.ScopeObject) bool { | ||||
| 	if obj is ast.ConstField { | ||||
| 		return match obj.expr { | ||||
| 			ast.CharLiteral, ast.FloatLiteral, ast.IntegerLiteral { true } | ||||
| 			else { false } | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) const_decl_simple_define(name string, val string) { | ||||
|  |  | |||
|  | @ -7,6 +7,10 @@ mut: | |||
| 	breed string | ||||
| } | ||||
| 
 | ||||
| fn new_cat(breed string) Cat { | ||||
| 	return Cat{breed} | ||||
| } | ||||
| 
 | ||||
| fn (c &Cat) name() string { | ||||
| 	if c.breed != '' { | ||||
| 		assert c.breed == 'Persian' | ||||
|  | @ -101,10 +105,12 @@ fn test_perform_speak() { | |||
| 	perform_speak(Cat{ | ||||
| 		breed: 'Persian' | ||||
| 	}) | ||||
| 	perform_speak(new_cat('Persian')) | ||||
| 	perform_speak_on_ptr(cat) | ||||
| 	perform_speak_on_ptr(Cat{ | ||||
| 		breed: 'Persian' | ||||
| 	}) | ||||
| 	perform_speak_on_ptr(new_cat('Persian')) | ||||
| 	handle_animals([dog, cat]) | ||||
| 	/* | ||||
| 	f := Foo { | ||||
|  |  | |||
|  | @ -56,9 +56,13 @@ fn test_sum_type_cast() { | |||
| fn test_sum_types() { | ||||
| 	b := parse_bool() | ||||
| 	handle_expr(b) | ||||
| 	handle_expr(parse_bool()) | ||||
| 
 | ||||
| 	de := DeclExprA{} | ||||
| 	handle_expr(de) | ||||
| 	handle_decl_expr(de) | ||||
| 	handle_expr(DeclExprA{}) | ||||
| 	handle_decl_expr(DeclExprA{}) | ||||
| } | ||||
| 
 | ||||
| /* | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue