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