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() | 	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
 | // 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) { | 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) | 	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) { | 		&& !expected_type.has_flag(.optional) { | ||||||
| 		got_styp := g.cc_type(got_type, true) | 		got_styp := g.cc_type(got_type, true) | ||||||
| 		exp_styp := g.cc_type(expected_type, true) | 		exp_styp := g.cc_type(expected_type, true) | ||||||
| 		if expected_is_ptr { | 		fname := 'I_${got_styp}_to_Interface_$exp_styp' | ||||||
| 			g.write('HEAP($exp_styp, ') | 		g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr, | ||||||
| 		} | 			got_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(')') |  | ||||||
| 		} |  | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// cast to sum type
 | 	// 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) | 				g.expr(expr) | ||||||
| 			} else { | 			} else { | ||||||
| 				g.write_sumtype_casting_fn(got_type, expected_type) | 				g.write_sumtype_casting_fn(got_type, expected_type) | ||||||
| 				if expected_is_ptr { | 				fname := '${got_sym.cname}_to_sumtype_$exp_sym.cname' | ||||||
| 					g.write('HEAP($exp_sym.cname, ') | 				g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_sym.cname, | ||||||
| 				} | 					got_is_ptr, got_styp) | ||||||
| 				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(')') |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  | @ -5113,11 +5112,6 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { | ||||||
| 		*/ | 		*/ | ||||||
| 		field_expr := field.expr | 		field_expr := field.expr | ||||||
| 		match 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 { | 			ast.ArrayInit { | ||||||
| 				if field.expr.is_fixed { | 				if field.expr.is_fixed { | ||||||
| 					styp := g.typ(field.expr.typ) | 					styp := g.typ(field.expr.typ) | ||||||
|  | @ -5147,12 +5141,28 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
| 				g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) | 				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) { | fn (mut g Gen) const_decl_simple_define(name string, val string) { | ||||||
| 	// Simple expressions should use a #define
 | 	// Simple expressions should use a #define
 | ||||||
| 	// so that we don't pollute the binary with unnecessary global vars
 | 	// so that we don't pollute the binary with unnecessary global vars
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,10 @@ mut: | ||||||
| 	breed string | 	breed string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn new_cat(breed string) Cat { | ||||||
|  | 	return Cat{breed} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn (c &Cat) name() string { | fn (c &Cat) name() string { | ||||||
| 	if c.breed != '' { | 	if c.breed != '' { | ||||||
| 		assert c.breed == 'Persian' | 		assert c.breed == 'Persian' | ||||||
|  | @ -101,10 +105,12 @@ fn test_perform_speak() { | ||||||
| 	perform_speak(Cat{ | 	perform_speak(Cat{ | ||||||
| 		breed: 'Persian' | 		breed: 'Persian' | ||||||
| 	}) | 	}) | ||||||
|  | 	perform_speak(new_cat('Persian')) | ||||||
| 	perform_speak_on_ptr(cat) | 	perform_speak_on_ptr(cat) | ||||||
| 	perform_speak_on_ptr(Cat{ | 	perform_speak_on_ptr(Cat{ | ||||||
| 		breed: 'Persian' | 		breed: 'Persian' | ||||||
| 	}) | 	}) | ||||||
|  | 	perform_speak_on_ptr(new_cat('Persian')) | ||||||
| 	handle_animals([dog, cat]) | 	handle_animals([dog, cat]) | ||||||
| 	/* | 	/* | ||||||
| 	f := Foo { | 	f := Foo { | ||||||
|  |  | ||||||
|  | @ -56,9 +56,13 @@ fn test_sum_type_cast() { | ||||||
| fn test_sum_types() { | fn test_sum_types() { | ||||||
| 	b := parse_bool() | 	b := parse_bool() | ||||||
| 	handle_expr(b) | 	handle_expr(b) | ||||||
|  | 	handle_expr(parse_bool()) | ||||||
|  | 
 | ||||||
| 	de := DeclExprA{} | 	de := DeclExprA{} | ||||||
| 	handle_expr(de) | 	handle_expr(de) | ||||||
| 	handle_decl_expr(de) | 	handle_decl_expr(de) | ||||||
|  | 	handle_expr(DeclExprA{}) | ||||||
|  | 	handle_decl_expr(DeclExprA{}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue