mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser,cgen: improve [flag]enum Abc{ a b }
, allow x := Abc.a | Abc.b
This commit is contained in:
parent
18cf36a22c
commit
ac27a3ccee
@ -829,10 +829,11 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
}
|
||||
ast.EnumDecl {
|
||||
enum_name := util.no_dots(node.name)
|
||||
is_flag := node.is_flag
|
||||
g.enum_typedefs.writeln('typedef enum {')
|
||||
mut cur_enum_expr := ''
|
||||
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')
|
||||
if field.has_expr {
|
||||
g.enum_typedefs.write(' = ')
|
||||
@ -843,6 +844,11 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
g.enum_typedefs.write(expr_str)
|
||||
cur_enum_expr = expr_str
|
||||
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 }
|
||||
g.enum_typedefs.writeln(', // $cur_value')
|
||||
|
@ -1869,13 +1869,19 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||
if fields.len > 32 {
|
||||
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' }
|
||||
p.scanner.codegen('
|
||||
//
|
||||
$pubfn ( e &$enum_name) has(flag $enum_name) bool { return (int(*e) & (1 << int(flag))) != 0 }
|
||||
$pubfn (mut e $enum_name) set(flag $enum_name) { unsafe{ *e = int(*e) | (1 << int(flag)) } }
|
||||
$pubfn (mut e $enum_name) clear(flag $enum_name) { unsafe{ *e = int(*e) & ~(1 << int(flag)) } }
|
||||
$pubfn (mut e $enum_name) toggle(flag $enum_name) { unsafe{ *e = int(*e) ^ (1 << int(flag)) } }
|
||||
$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) | (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) ^ (int(flag)) } }
|
||||
//
|
||||
')
|
||||
}
|
||||
|
@ -13,6 +13,10 @@ mut:
|
||||
|
||||
fn test_enum_bitfield() {
|
||||
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(.write)
|
||||
a.perm.toggle(.execute)
|
||||
@ -22,11 +26,20 @@ fn test_enum_bitfield() {
|
||||
assert a.perm.has(.execute)
|
||||
assert !a.perm.has(.write)
|
||||
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)
|
||||
assert int(b) == 1 + 2 + 4 + 0
|
||||
b.set(.other)
|
||||
assert int(b) == 1 + 2 + 4 + 8
|
||||
assert b.has(.write)
|
||||
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(.execute)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user