sum types
parent
d2c3c66ba4
commit
7ab993c218
|
@ -21,18 +21,15 @@ fn (p mut Parser) enum_decl(no_name bool) {
|
|||
if !p.builtin_mod && p.mod != 'main' {
|
||||
enum_name = p.prepend_mod(enum_name)
|
||||
}
|
||||
// Skip empty enums
|
||||
if !no_name && !p.first_pass() {
|
||||
p.cgen.typedefs << 'typedef int $enum_name;'
|
||||
}
|
||||
p.fspace()
|
||||
p.check(.lcbr)
|
||||
mut val := 0
|
||||
mut fields := []string
|
||||
mut tuple_variants := []string
|
||||
for p.tok == .name {
|
||||
field := p.check_name()
|
||||
if contains_capital(field) {
|
||||
p.warn('enum values cannot contain uppercase letters, use snake_case instead')
|
||||
if p.pass == .decl && p.tok != .lpar && contains_capital(field) {
|
||||
p.warn('enum values cannot contain uppercase letters, use snake_case instead (`$field`)')
|
||||
}
|
||||
fields << field
|
||||
name := '${mod_gen_name(p.mod)}__${enum_name}_$field'
|
||||
|
@ -59,6 +56,18 @@ fn (p mut Parser) enum_decl(no_name bool) {
|
|||
p.error_with_token_index('only numbers are allowed in enum initializations', enum_assign_tidx)
|
||||
}
|
||||
}
|
||||
// `BoolExpr(bool)`
|
||||
else if p.tok == .lpar {
|
||||
if !field[0].is_capital() {
|
||||
p.error('sum types must be capitalized')
|
||||
}
|
||||
p.check(.lpar)
|
||||
tuple_variants << p.get_type()
|
||||
p.check(.rpar)
|
||||
if p.pass == .main {
|
||||
p.cgen.consts << '#define ${field}_type $val // LOL'
|
||||
}
|
||||
}
|
||||
if p.pass == .main {
|
||||
p.cgen.consts << '#define $name $val'
|
||||
}
|
||||
|
@ -81,10 +90,25 @@ fn (p mut Parser) enum_decl(no_name bool) {
|
|||
is_public: is_pub
|
||||
is_flag: is_flag
|
||||
}
|
||||
p.table.tuple_variants[enum_name] = tuple_variants
|
||||
if is_flag && !p.first_pass() {
|
||||
p.gen_enum_flag_methods(mut T)
|
||||
}
|
||||
p.table.register_type(T)
|
||||
if p.pass == .decl {
|
||||
p.table.register_type(T)
|
||||
}
|
||||
// Register `Expression` enum
|
||||
if tuple_variants.len > 0 && p.pass == .main {
|
||||
p.cgen.typedefs << 'typedef struct {
|
||||
void* obj;
|
||||
int typ;
|
||||
} $enum_name;
|
||||
'
|
||||
}
|
||||
// Skip empty enums
|
||||
else if !no_name && !p.first_pass() {
|
||||
p.cgen.typedefs << 'typedef int $enum_name;'
|
||||
}
|
||||
p.check(.rcbr)
|
||||
p.fgen_nl()
|
||||
p.fgen_nl()
|
||||
|
@ -106,3 +130,23 @@ fn (p mut Parser) check_enum_member_access() {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
enum Expression {
|
||||
Boolean(bool),
|
||||
Integer(i32),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let expr = Expression::Integer(10);
|
||||
let mut val = Expression::Boolean(true);
|
||||
val = expr;
|
||||
match val {
|
||||
Expression::Integer(n) => println!("INT {}", n),
|
||||
Expression::Boolean(b) => println!("BOOL {}", b),
|
||||
}
|
||||
|
||||
//println!("HELLO {}", val);
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
|
@ -343,6 +343,31 @@ fn (p mut Parser) name_expr() string {
|
|||
// no need in `if color == Color.red`
|
||||
p.warn('`${enum_type.name}.$val` is unnecessary, use `.$val`')
|
||||
}
|
||||
// `expr := Expr.BoolExpr(true)` =>
|
||||
// `Expr expr = { .obj = true, .typ = BoolExpr_type };`
|
||||
if val[0].is_capital() {
|
||||
p.next()
|
||||
p.check(.lpar)
|
||||
//println('sum type $val name=$val')
|
||||
// Find a corresponding tuple variant
|
||||
// TODO slow, but this will be re-written anyway
|
||||
mut idx := 0
|
||||
for i, val_ in enum_type.enum_vals {
|
||||
//println('f $field.name')
|
||||
if val_ == val {
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
q := p.table.tuple_variants[enum_type.name]
|
||||
//println(q)
|
||||
//println(q[idx])
|
||||
arg_type := q[idx]
|
||||
p.gen('($enum_type.name) { .obj = ($arg_type[]) { ')
|
||||
p.bool_expression()
|
||||
p.check(.rpar)
|
||||
p.gen('}, .typ = ${val}_type }')
|
||||
return enum_type.name
|
||||
}
|
||||
// println('enum val $val')
|
||||
p.gen(mod_gen_name(enum_type.mod) + '__' + enum_type.name + '_' + val) // `color = main__Color_green`
|
||||
p.next()
|
||||
|
|
|
@ -21,6 +21,7 @@ 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
|
||||
}
|
||||
|
||||
struct VargAccess {
|
||||
|
|
|
@ -54,3 +54,48 @@ fn test_nums() {
|
|||
d := Foo.d
|
||||
assert d == -10
|
||||
}
|
||||
|
||||
|
||||
enum Expr {
|
||||
BoolExpr(bool)
|
||||
IntExpr(int)
|
||||
//FloatExpr(int)
|
||||
}
|
||||
|
||||
fn get_expr() Expr {
|
||||
return Expr.IntExpr(10)
|
||||
|
||||
}
|
||||
|
||||
fn test_typed_enum() {
|
||||
i := Expr.IntExpr(10)
|
||||
expr := Expr.BoolExpr(true)
|
||||
//println(i)
|
||||
//if i == expr {
|
||||
|
||||
//}
|
||||
println('done')
|
||||
// expr = i
|
||||
/*
|
||||
match expr {
|
||||
IntExpr(n) { println('INT $n') }
|
||||
BoolExpr(b) { println('BOOL $b') }
|
||||
}
|
||||
*/
|
||||
}
|
||||
/*
|
||||
|
||||
fn test_typed_enum() {
|
||||
Expr i = { .obj = 10, .typ = IntExpr_type };
|
||||
Expr expr = { .obj = true, .typ = BoolExpr_type };
|
||||
// val = expr;
|
||||
if (expr.typ == IntExpr_type) {
|
||||
int n = (int)expr.obj;
|
||||
println('INT $n');
|
||||
}
|
||||
else if (expr.typ == BoolExpr_type) {
|
||||
int b = (bool)expr.obj;
|
||||
println('BOOL $b');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue