checker/gen: fix nested sumtype matching
parent
34a24eaa4e
commit
9d7f1a236a
|
@ -102,22 +102,9 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// sum type
|
// sum type
|
||||||
// TODO: there is a bug when casting sumtype the other way if its pointer
|
if c.table.check_sumtype_compatibility(got, expected) {
|
||||||
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
|
|
||||||
// if got_type_sym.kind == .sum_type {
|
|
||||||
// sum_info := got_type_sym.info as table.SumType
|
|
||||||
// // TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
|
|
||||||
// if expected.set_nr_muls(0) in sum_info.variants {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if exp_type_sym.kind == .sum_type {
|
|
||||||
sum_info := exp_type_sym.info as table.SumType
|
|
||||||
// TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
|
|
||||||
if got.set_nr_muls(0) in sum_info.variants {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// fn type
|
// fn type
|
||||||
if got_type_sym.kind == .function && exp_type_sym.kind == .function {
|
if got_type_sym.kind == .function && exp_type_sym.kind == .function {
|
||||||
return c.check_matching_function_symbols(got_type_sym, exp_type_sym)
|
return c.check_matching_function_symbols(got_type_sym, exp_type_sym)
|
||||||
|
|
|
@ -2462,10 +2462,7 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
if node.is_sum_type || node.is_interface {
|
if node.is_sum_type || node.is_interface {
|
||||||
ok := if cond_type_sym.kind == .sum_type {
|
ok := if cond_type_sym.kind == .sum_type {
|
||||||
// TODO verify sum type
|
c.table.check_sumtype_has_variant(cond_type, typ)
|
||||||
// true // c.check_types(typ, cond_type)
|
|
||||||
info := cond_type_sym.info as table.SumType
|
|
||||||
typ in info.variants
|
|
||||||
} else {
|
} else {
|
||||||
// interface match
|
// interface match
|
||||||
c.type_implements(typ, cond_type, node.pos)
|
c.type_implements(typ, cond_type, node.pos)
|
||||||
|
|
|
@ -949,10 +949,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
|
||||||
fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type) {
|
fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type) {
|
||||||
// cast to sum type
|
// cast to sum type
|
||||||
if expected_type != table.void_type {
|
if expected_type != table.void_type {
|
||||||
exp_sym := g.table.get_type_symbol(expected_type)
|
if g.table.check_sumtype_has_variant(expected_type, got_type) {
|
||||||
if exp_sym.kind == .sum_type {
|
|
||||||
sum_info := exp_sym.info as table.SumType
|
|
||||||
if got_type in sum_info.variants {
|
|
||||||
got_sym := g.table.get_type_symbol(got_type)
|
got_sym := g.table.get_type_symbol(got_type)
|
||||||
got_styp := g.typ(got_type)
|
got_styp := g.typ(got_type)
|
||||||
exp_styp := g.typ(expected_type)
|
exp_styp := g.typ(expected_type)
|
||||||
|
@ -963,7 +960,6 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Generic dereferencing logic
|
// Generic dereferencing logic
|
||||||
expected_sym := g.table.get_type_symbol(expected_type)
|
expected_sym := g.table.get_type_symbol(expected_type)
|
||||||
got_is_ptr := got_type.is_ptr()
|
got_is_ptr := got_type.is_ptr()
|
||||||
|
|
|
@ -491,3 +491,32 @@ pub fn (table &Table) register_fn_gen_type(fn_name string, typ Type) {
|
||||||
// println('registering fn ($fn_name) gen type $sym.name')
|
// println('registering fn ($fn_name) gen type $sym.name')
|
||||||
table.fn_gen_types[fn_name] = a
|
table.fn_gen_types[fn_name] = a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: there is a bug when casting sumtype the other way if its pointer
|
||||||
|
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
|
||||||
|
pub fn (table &Table) check_sumtype_has_variant(parent Type, variant Type) bool {
|
||||||
|
parent_sym := table.get_type_symbol(parent)
|
||||||
|
if parent_sym.kind ==.sum_type {
|
||||||
|
parent_info := parent_sym.info as SumType
|
||||||
|
for v in parent_info.variants {
|
||||||
|
if v.idx() == variant.idx() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if table.check_sumtype_has_variant(v, variant) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (table &Table) check_sumtype_compatibility(a Type, b Type) bool {
|
||||||
|
if table.check_sumtype_has_variant(a, b) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if table.check_sumtype_has_variant(b, a) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
type Expr = IfExpr | IntegerLiteral
|
type Expr = IfExpr | IntegerLiteral
|
||||||
|
type Stmt = FnDecl | StructDecl
|
||||||
|
type Node = Expr | Stmt
|
||||||
|
|
||||||
|
struct FnDecl {
|
||||||
|
pos int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StructDecl {
|
||||||
|
pos int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct IfExpr {
|
struct IfExpr {
|
||||||
pos int
|
pos int
|
||||||
|
@ -94,3 +105,26 @@ fn test_converting_down() {
|
||||||
assert res[1].val == 3
|
assert res[1].val == 3
|
||||||
assert res[1].name == 'three'
|
assert res[1].name == 'three'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_nested_sumtype() {
|
||||||
|
mut a := Node{}
|
||||||
|
mut b := Node{}
|
||||||
|
a = StructDecl{pos: 1}
|
||||||
|
b = IfExpr {pos: 1}
|
||||||
|
match a {
|
||||||
|
StructDecl {
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: not working
|
||||||
|
// assert b is IfExpr
|
||||||
|
if b is IfExpr {
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue