mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
sum type type Foo = Bar | Baz
This commit is contained in:
parent
9dd05474b0
commit
803ded3dec
@ -4,6 +4,8 @@
|
|||||||
module compiler
|
module compiler
|
||||||
|
|
||||||
fn (p mut Parser) bool_expression() string {
|
fn (p mut Parser) bool_expression() string {
|
||||||
|
start_ph := p.cgen.add_placeholder()
|
||||||
|
expected := p.expected_type
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
typ := p.bterm()
|
typ := p.bterm()
|
||||||
mut got_and := false // to catch `a && b || c` in one expression without ()
|
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())
|
println(tok.str())
|
||||||
p.error('expr() returns empty type')
|
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
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +369,7 @@ fn (p mut Parser) name_expr() string {
|
|||||||
//println(q)
|
//println(q)
|
||||||
//println(q[idx])
|
//println(q[idx])
|
||||||
arg_type := q[idx]
|
arg_type := q[idx]
|
||||||
p.gen('($enum_type.name) { .obj = ($arg_type[]) { ')
|
p.gen('($enum_type.name) { .obj = ($arg_type[]) { ')
|
||||||
p.bool_expression()
|
p.bool_expression()
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
p.gen('}, .typ = ${val}_type }')
|
p.gen('}, .typ = ${val}_type }')
|
||||||
|
@ -160,7 +160,7 @@ fn (v mut V) new_parser_from_file(path string) Parser {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.compile_defines.len > 0 {
|
if v.compile_defines.len > 0 {
|
||||||
for cdefine in v.compile_defines {
|
for cdefine in v.compile_defines {
|
||||||
custom_path_ending := '_d_${cdefine}.v'
|
custom_path_ending := '_d_${cdefine}.v'
|
||||||
@ -171,7 +171,7 @@ fn (v mut V) new_parser_from_file(path string) Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mut p := v.new_parser(new_scanner_file(path))
|
mut p := v.new_parser(new_scanner_file(path))
|
||||||
p = {
|
p = {
|
||||||
p |
|
p |
|
||||||
@ -793,20 +793,79 @@ fn (p mut Parser) type_decl() {
|
|||||||
if p.tok == .key_struct {
|
if p.tok == .key_struct {
|
||||||
p.error('use `struct $name {` instead of `type $name struct {`')
|
p.error('use `struct $name {` instead of `type $name struct {`')
|
||||||
}
|
}
|
||||||
|
if p.tok == .assign {
|
||||||
|
p.next()
|
||||||
|
|
||||||
|
}
|
||||||
parent := p.get_type2()
|
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)
|
nt_pair := p.table.cgen_name_type_pair(name, parent.name)
|
||||||
// TODO dirty C typedef hacks for DOOM
|
// TODO dirty C typedef hacks for DOOM
|
||||||
// Unknown type probably means it's a struct, and it's used before the struct is defined,
|
// Unknown type probably means it's a struct, and it's used before the struct is defined,
|
||||||
// so specify "struct"
|
// so specify "struct"
|
||||||
_struct := if parent.cat != .array && parent.cat != .func && !p.table.known_type(parent.name) { 'struct' } else { '' }
|
_struct := if parent.cat != .array && parent.cat != .func && !p.table.known_type(parent.name) { 'struct' } else { '' }
|
||||||
p.gen_typedef('typedef $_struct $nt_pair; //type alias name="$name" parent=`$parent.name`')
|
if !is_sum {
|
||||||
p.table.register_type(Type{
|
p.gen_typedef('typedef $_struct $nt_pair; //type alias name="$name" parent=`$parent.name`')
|
||||||
name: name
|
p.table.register_type(Type{
|
||||||
parent: parent.name
|
name: name
|
||||||
mod: p.mod
|
parent: parent.name
|
||||||
cat: .alias
|
mod: p.mod
|
||||||
is_public: is_pub
|
cat: .alias
|
||||||
})
|
is_public: is_pub
|
||||||
|
})
|
||||||
|
}
|
||||||
if p.tok != .key_type {
|
if p.tok != .key_type {
|
||||||
p.fspace()
|
p.fspace()
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ pub mut:
|
|||||||
// names []Name
|
// names []Name
|
||||||
max_field_len map[string]int // for vfmt: max_field_len['Parser'] == 12
|
max_field_len map[string]int // for vfmt: max_field_len['Parser'] == 12
|
||||||
generic_struct_params map[string][]string
|
generic_struct_params map[string][]string
|
||||||
tuple_variants map[string][]string
|
tuple_variants map[string][]string // enum( Bool(BoolExpr) )
|
||||||
|
sum_types []string
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VargAccess {
|
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 {
|
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 got := got_
|
||||||
mut expected := expected_
|
mut expected := expected_
|
||||||
// p.log('check types got="$got" exp="$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
|
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 {
|
if !throw {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -17,3 +17,48 @@ fn test_person_str() {
|
|||||||
println(p)
|
println(p)
|
||||||
assert p.str() == 'Person: Bilbo'
|
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
Block a user