sum type `type Foo = Bar | Baz`
parent
9dd05474b0
commit
803ded3dec
|
@ -4,6 +4,8 @@
|
|||
module compiler
|
||||
|
||||
fn (p mut Parser) bool_expression() string {
|
||||
start_ph := p.cgen.add_placeholder()
|
||||
expected := p.expected_type
|
||||
tok := p.tok
|
||||
typ := p.bterm()
|
||||
mut got_and := false // to catch `a && b || c` in one expression without ()
|
||||
|
@ -44,6 +46,11 @@ fn (p mut Parser) bool_expression() string {
|
|||
println(tok.str())
|
||||
p.error('expr() returns empty type')
|
||||
}
|
||||
if expected != typ && expected in p.table.sum_types { // TODO perf
|
||||
p.cgen.set_placeholder(start_ph, '/*KUK*/($expected) { .obj = ($typ[]) { ')
|
||||
p.gen('}, .typ = 1}')//${val}_type }')
|
||||
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
|
|
|
@ -793,12 +793,70 @@ fn (p mut Parser) type_decl() {
|
|||
if p.tok == .key_struct {
|
||||
p.error('use `struct $name {` instead of `type $name struct {`')
|
||||
}
|
||||
if p.tok == .assign {
|
||||
p.next()
|
||||
|
||||
}
|
||||
parent := p.get_type2()
|
||||
// Sum type
|
||||
is_sum := p.tok == .pipe
|
||||
if is_sum {
|
||||
// Register the first child (name we already parsed)
|
||||
/*
|
||||
p.table.register_type(Type{
|
||||
parent: name
|
||||
name: parent.name // yeah it's not a parent here
|
||||
mod: p.mod
|
||||
is_public: is_pub
|
||||
})
|
||||
*/
|
||||
// Register the rest of them
|
||||
for p.tok == .pipe {
|
||||
p.next()
|
||||
child := p.check_name()
|
||||
if p.pass == .main {
|
||||
// Update the type's parent
|
||||
println('child=$child parent=$name')
|
||||
mut t := p.table.find_type(child)
|
||||
if t.name == '' {
|
||||
p.error('unknown type `$child`')
|
||||
}
|
||||
t.parent = name
|
||||
p.table.rewrite_type(t)
|
||||
/*
|
||||
p.table.register_type(Type{
|
||||
parent: name
|
||||
name: child
|
||||
mod: p.mod
|
||||
is_public: is_pub
|
||||
})
|
||||
*/
|
||||
}
|
||||
}
|
||||
if p.pass == .decl {
|
||||
p.table.sum_types << name
|
||||
println(p.table.sum_types)
|
||||
}
|
||||
// Register the actual sum type
|
||||
println('reging sum $name')
|
||||
p.table.register_type(Type{
|
||||
name: name
|
||||
mod: p.mod
|
||||
cat: .alias
|
||||
is_public: is_pub
|
||||
})
|
||||
p.gen_typedef('typedef struct {
|
||||
void* obj;
|
||||
int typ;
|
||||
} $name;
|
||||
')
|
||||
}
|
||||
nt_pair := p.table.cgen_name_type_pair(name, parent.name)
|
||||
// TODO dirty C typedef hacks for DOOM
|
||||
// Unknown type probably means it's a struct, and it's used before the struct is defined,
|
||||
// so specify "struct"
|
||||
_struct := if parent.cat != .array && parent.cat != .func && !p.table.known_type(parent.name) { 'struct' } else { '' }
|
||||
if !is_sum {
|
||||
p.gen_typedef('typedef $_struct $nt_pair; //type alias name="$name" parent=`$parent.name`')
|
||||
p.table.register_type(Type{
|
||||
name: name
|
||||
|
@ -807,6 +865,7 @@ fn (p mut Parser) type_decl() {
|
|||
cat: .alias
|
||||
is_public: is_pub
|
||||
})
|
||||
}
|
||||
if p.tok != .key_type {
|
||||
p.fspace()
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ pub mut:
|
|||
// names []Name
|
||||
max_field_len map[string]int // for vfmt: max_field_len['Parser'] == 12
|
||||
generic_struct_params map[string][]string
|
||||
tuple_variants map[string][]string
|
||||
tuple_variants map[string][]string // enum( Bool(BoolExpr) )
|
||||
sum_types []string
|
||||
}
|
||||
|
||||
struct VargAccess {
|
||||
|
@ -593,6 +594,9 @@ fn (t &Table) find_type(name_ string) Type {
|
|||
}
|
||||
|
||||
fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
|
||||
if p.fileis('type_test') {
|
||||
println('got=$got_ exp=$expected_')
|
||||
}
|
||||
mut got := got_
|
||||
mut expected := expected_
|
||||
// p.log('check types got="$got" exp="$expected" ')
|
||||
|
@ -725,6 +729,16 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
// Sum type
|
||||
println(expected)
|
||||
if expected in p.table.sum_types {
|
||||
println('checking sum')
|
||||
child := p.table.find_type(got)
|
||||
if child.parent == expected {
|
||||
println('yep $expected')
|
||||
return true
|
||||
}
|
||||
}
|
||||
if !throw {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -17,3 +17,48 @@ fn test_person_str() {
|
|||
println(p)
|
||||
assert p.str() == 'Person: Bilbo'
|
||||
}
|
||||
|
||||
struct Foo {}
|
||||
|
||||
struct WTF {
|
||||
wtf int
|
||||
}
|
||||
|
||||
struct BoolExpr {
|
||||
foo int
|
||||
|
||||
}
|
||||
|
||||
struct BinExpr {
|
||||
|
||||
}
|
||||
|
||||
struct UnaryExpr {
|
||||
|
||||
}
|
||||
|
||||
type Expr = Foo | BoolExpr | BinExpr | UnaryExpr
|
||||
|
||||
fn handle_expr(e Expr) {
|
||||
|
||||
}
|
||||
|
||||
fn parse_bool() BoolExpr {
|
||||
return BoolExpr{}
|
||||
}
|
||||
|
||||
fn test_sum() {
|
||||
b := parse_bool()
|
||||
handle_expr(b)
|
||||
}
|
||||
|
||||
/*
|
||||
#define ExprType_BoolExpr 0
|
||||
#define ExprType_BinExpr 1
|
||||
#define ExprType_UnaryExpr 2
|
||||
|
||||
struct Expr {
|
||||
int typ;
|
||||
void* obj;
|
||||
}
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue