parser,cgen: improve `[flag]enum Abc{ a b }`, allow `x := Abc.a | Abc.b`
parent
18cf36a22c
commit
ac27a3ccee
|
@ -829,10 +829,11 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
ast.EnumDecl {
|
ast.EnumDecl {
|
||||||
enum_name := util.no_dots(node.name)
|
enum_name := util.no_dots(node.name)
|
||||||
|
is_flag := node.is_flag
|
||||||
g.enum_typedefs.writeln('typedef enum {')
|
g.enum_typedefs.writeln('typedef enum {')
|
||||||
mut cur_enum_expr := ''
|
mut cur_enum_expr := ''
|
||||||
mut cur_enum_offset := 0
|
mut cur_enum_offset := 0
|
||||||
for field in node.fields {
|
for i, field in node.fields {
|
||||||
g.enum_typedefs.write('\t${enum_name}_$field.name')
|
g.enum_typedefs.write('\t${enum_name}_$field.name')
|
||||||
if field.has_expr {
|
if field.has_expr {
|
||||||
g.enum_typedefs.write(' = ')
|
g.enum_typedefs.write(' = ')
|
||||||
|
@ -843,6 +844,11 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
g.enum_typedefs.write(expr_str)
|
g.enum_typedefs.write(expr_str)
|
||||||
cur_enum_expr = expr_str
|
cur_enum_expr = expr_str
|
||||||
cur_enum_offset = 0
|
cur_enum_offset = 0
|
||||||
|
} else if is_flag {
|
||||||
|
g.enum_typedefs.write(' = ')
|
||||||
|
cur_enum_expr = '1 << $i'
|
||||||
|
g.enum_typedefs.write((1 << i).str())
|
||||||
|
cur_enum_offset = 0
|
||||||
}
|
}
|
||||||
cur_value := if cur_enum_offset > 0 { '$cur_enum_expr+$cur_enum_offset' } else { cur_enum_expr }
|
cur_value := if cur_enum_offset > 0 { '$cur_enum_expr+$cur_enum_offset' } else { cur_enum_expr }
|
||||||
g.enum_typedefs.writeln(', // $cur_value')
|
g.enum_typedefs.writeln(', // $cur_value')
|
||||||
|
|
|
@ -1869,13 +1869,19 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||||
if fields.len > 32 {
|
if fields.len > 32 {
|
||||||
p.error('when an enum is used as bit field, it must have a max of 32 fields')
|
p.error('when an enum is used as bit field, it must have a max of 32 fields')
|
||||||
}
|
}
|
||||||
|
for f in fields {
|
||||||
|
if f.has_expr {
|
||||||
|
p.error_with_pos('when an enum is used as a bit field, you can not assign custom values',
|
||||||
|
f.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
pubfn := if p.mod == 'main' { 'fn' } else { 'pub fn' }
|
pubfn := if p.mod == 'main' { 'fn' } else { 'pub fn' }
|
||||||
p.scanner.codegen('
|
p.scanner.codegen('
|
||||||
//
|
//
|
||||||
$pubfn ( e &$enum_name) has(flag $enum_name) bool { return (int(*e) & (1 << int(flag))) != 0 }
|
$pubfn ( e &$enum_name) has(flag $enum_name) bool { return (int(*e) & (int(flag))) != 0 }
|
||||||
$pubfn (mut e $enum_name) set(flag $enum_name) { unsafe{ *e = int(*e) | (1 << int(flag)) } }
|
$pubfn (mut e $enum_name) set(flag $enum_name) { unsafe{ *e = int(*e) | (int(flag)) } }
|
||||||
$pubfn (mut e $enum_name) clear(flag $enum_name) { unsafe{ *e = int(*e) & ~(1 << int(flag)) } }
|
$pubfn (mut e $enum_name) clear(flag $enum_name) { unsafe{ *e = int(*e) & ~(int(flag)) } }
|
||||||
$pubfn (mut e $enum_name) toggle(flag $enum_name) { unsafe{ *e = int(*e) ^ (1 << int(flag)) } }
|
$pubfn (mut e $enum_name) toggle(flag $enum_name) { unsafe{ *e = int(*e) ^ (int(flag)) } }
|
||||||
//
|
//
|
||||||
')
|
')
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@ mut:
|
||||||
|
|
||||||
fn test_enum_bitfield() {
|
fn test_enum_bitfield() {
|
||||||
mut a := BfFile{}
|
mut a := BfFile{}
|
||||||
|
assert 1 == int(BfPermission.read)
|
||||||
|
assert 2 == int(BfPermission.write)
|
||||||
|
assert 4 == int(BfPermission.execute)
|
||||||
|
assert 8 == int(BfPermission.other)
|
||||||
a.perm.set(.read)
|
a.perm.set(.read)
|
||||||
a.perm.set(.write)
|
a.perm.set(.write)
|
||||||
a.perm.toggle(.execute)
|
a.perm.toggle(.execute)
|
||||||
|
@ -22,11 +26,20 @@ fn test_enum_bitfield() {
|
||||||
assert a.perm.has(.execute)
|
assert a.perm.has(.execute)
|
||||||
assert !a.perm.has(.write)
|
assert !a.perm.has(.write)
|
||||||
assert !a.perm.has(.other)
|
assert !a.perm.has(.other)
|
||||||
mut b := BfPermission.read // TODO: this does nothing currenty just sets the type
|
mut b := BfPermission.read | BfPermission.execute
|
||||||
|
assert int(b) == 1 + 0 + 4 + 0
|
||||||
|
assert b.has(.read)
|
||||||
|
assert b.has(.execute)
|
||||||
b.set(.write)
|
b.set(.write)
|
||||||
|
assert int(b) == 1 + 2 + 4 + 0
|
||||||
b.set(.other)
|
b.set(.other)
|
||||||
|
assert int(b) == 1 + 2 + 4 + 8
|
||||||
assert b.has(.write)
|
assert b.has(.write)
|
||||||
assert b.has(.other)
|
assert b.has(.other)
|
||||||
|
b.toggle(.read)
|
||||||
|
assert int(b) == 0 + 2 + 4 + 8
|
||||||
|
b.toggle(.execute)
|
||||||
|
assert int(b) == 0 + 2 + 0 + 8
|
||||||
assert !b.has(.read)
|
assert !b.has(.read)
|
||||||
assert !b.has(.execute)
|
assert !b.has(.execute)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue