cgen: fix typeof union sum type (#6794)

pull/6804/head
Daniel Däschle 2020-11-12 12:27:54 +01:00 committed by GitHub
parent 24f743ee12
commit 9c569246ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 5 deletions

View File

@ -381,6 +381,22 @@ pub fn (mut g Gen) write_typeof_functions() {
g.writeln('}')
}
}
for typ in g.table.types {
if typ.kind == .union_sum_type {
sum_info := typ.info as table.UnionSumType
tidx := g.table.find_type_idx(typ.name)
g.writeln('char * v_typeof_unionsumtype_${tidx}(int sidx) { /* $typ.name */ ')
g.writeln(' switch(sidx) {')
g.writeln(' case $tidx: return "${util.strip_main_name(typ.name)}";')
for v in sum_info.variants {
subtype := g.table.get_type_symbol(v)
g.writeln(' case $v: return "${util.strip_main_name(subtype.name)}";')
}
g.writeln(' default: return "unknown ${util.strip_main_name(typ.name)}";')
g.writeln(' }')
g.writeln('}')
}
}
g.writeln('// << typeof() support for sum types')
g.writeln('')
}
@ -2566,6 +2582,13 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) {
g.write('tos3( /* $sym.name */ v_typeof_sumtype_${sum_type_idx}( (')
g.expr(node.expr)
g.write(').typ ))')
} else if sym.kind == .union_sum_type {
// When encountering a .sum_type, typeof() should be done at runtime,
// because the subtype of the expression may change:
sum_type_idx := node.expr_type.idx()
g.write('tos3( /* $sym.name */ v_typeof_unionsumtype_${sum_type_idx}( (')
g.expr(node.expr)
g.write(').typ ))')
} else if sym.kind == .array_fixed {
fixed_info := sym.info as table.ArrayFixed
typ_name := g.table.get_type_name(fixed_info.elem_type)

View File

@ -24,7 +24,7 @@ fn handle(e Expr) string {
assert is_literal
assert !(e !is IntegerLiteral)
if e is IntegerLiteral {
println('int')
assert typeof(e.val) == 'string'
}
match union e {
IntegerLiteral {
@ -294,7 +294,7 @@ fn test_nested_if_is() {
mut b := Outer(InnerStruct{Inner(0)})
if b is InnerStruct {
if b.x is int {
println(b.x)
assert b.x == 0
}
}
}
@ -303,20 +303,30 @@ fn test_casted_sum_type_selector_reassign() {
mut b := InnerStruct{Inner(0)}
if b.x is int {
assert typeof(b.x) == 'int'
// this check works only if x is castet
assert b.x == 0
b.x = 'test'
// this check works only if x is castet
assert b.x[0] == `t`
assert typeof(b.x) == 'string'
}
assert typeof(b.x) == 'Inner'
// this check works only if x is not castet
assert b.x is string
}
fn test_casted_sum_type_ident_reassign() {
mut x := Inner(0)
if x is int {
// this check works only if x is castet
assert x == 0
assert typeof(x) == 'int'
x = 'test'
// this check works only if x is castet
assert x[0] == `t`
assert typeof(x) == 'string'
}
assert typeof(x) == 'Inner'
// this check works only if x is not castet
assert x is string
}
__type Expr2 = int | string
@ -427,11 +437,17 @@ fn test_match_multi_branch() {
mut y := ''
match union f {
CallExpr2, CTempVarExpr {
assert typeof(f) == 'Expr4'
// this check works only if f is not castet
assert f is CTempVarExpr
}
}
}
fn test_typeof() {
x := Expr4(CTempVarExpr{})
assert typeof(x) == 'CTempVarExpr'
}
struct Outer2 {
e Expr4
}