From 6a2ef733de6bccc19413ccadf22d92ccca678880 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 26 Sep 2021 21:24:35 +0300 Subject: [PATCH] v.parser: add a generated `.all(.flag1|.flag2)` method to `[flag]` enums Unlike `.has(.flag1|.flag2)`, which is true, for any of `.flag1` or `.flag2`, the new method `.all()` tests whether *all flags* are set at the same time. --- doc/docs.md | 13 ++++++++++++- vlib/v/parser/parser.v | 1 + vlib/v/tests/enum_bitfield_test.v | 31 +++++++++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index 744a99aa75..88bad0e761 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -5344,14 +5344,23 @@ enum BitField { other } -fn example_enum_as_bitfield_use() { +fn main() { assert 1 == int(BitField.read) assert 2 == int(BitField.write) mut bf := BitField.read + assert bf.has(.read | .other) // test if *at least one* of the flags is set + assert !bf.all(.read | .other) // test if *all* of the flags is set bf.set(.write | .other) assert bf.has(.read | .write | .other) + assert bf.all(.read | .write | .other) + bf.toggle(.other) + assert bf == BitField.read | .write + assert bf.all(.read | .write) + assert !bf.has(.other) } +``` +```v // Calling this function will result in a deprecation warning [deprecated] fn old_function() { @@ -5372,7 +5381,9 @@ fn legacy_function() {} [deprecated: 'use new_function2() instead'] [deprecated_after: '2021-05-27'] fn legacy_function2() {} +``` +```v nofmt // This function's calls will be inlined. [inline] fn inlined_function() { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 9193e87380..76feddb99b 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -3146,6 +3146,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl { // [inline] $pubfn ( e &$enum_name) is_empty() bool { return int(*e) == 0 } [inline] $pubfn ( e &$enum_name) has(flag $enum_name) bool { return (int(*e) & (int(flag))) != 0 } +[inline] $pubfn ( e &$enum_name) all(flag $enum_name) bool { return (int(*e) & (int(flag))) == int(flag) } [inline] $pubfn (mut e $enum_name) set(flag $enum_name) { unsafe{ *e = ${enum_name}(int(*e) | (int(flag))) } } [inline] $pubfn (mut e $enum_name) clear(flag $enum_name) { unsafe{ *e = ${enum_name}(int(*e) & ~(int(flag))) } } [inline] $pubfn (mut e $enum_name) toggle(flag $enum_name) { unsafe{ *e = ${enum_name}(int(*e) ^ (int(flag))) } } diff --git a/vlib/v/tests/enum_bitfield_test.v b/vlib/v/tests/enum_bitfield_test.v index f6d274eca5..8c8f37c78a 100644 --- a/vlib/v/tests/enum_bitfield_test.v +++ b/vlib/v/tests/enum_bitfield_test.v @@ -26,6 +26,9 @@ fn test_enum_bitfield() { assert a.perm.has(.execute) assert !a.perm.has(.write) assert !a.perm.has(.other) +} + +fn test_enum_bitfield_operators() { mut b := BfPermission.read | BfPermission.execute assert int(b) == 1 + 0 + 4 + 0 assert b.has(.read) @@ -42,11 +45,35 @@ fn test_enum_bitfield() { assert int(b) == 0 + 2 + 0 + 8 assert !b.has(.read) assert !b.has(.execute) +} +fn test_enum_bitfield_has_vs_all_methods_with_combined_flags() { mut c := BfPermission.read c.set(.write | .execute) assert c.has(.read | .write | .execute) assert !c.has(.other) - c.toggle(.write | .other) - assert '$c' == 'BfPermission{.read | .execute | .other}' + assert c.has(.read | .write | .execute | .other) + // .all() tests if *ALL* of the given flags are set, i.e. not just any one of them. + // .has() tests if *ANY* of the given flags is set, even though some of the others may not be. + assert c.all(.read | .write | .execute) + assert !c.all(.read | .write | .execute | .other) +} + +fn test_enum_bitfield_has_vs_all_methods_with_combined_flags_2() { + mut c := BfPermission.read | .execute | .other + // + assert c.has(.read | .execute | .other | .write) + assert c.has(.read | .write) + assert !c.all(.read | .execute | .other | .write) + assert !c.all(.read | .write) + // + assert c.all(.read | .execute | .other) + assert c.all(.read | .execute) + assert c.all(.execute | .other) + assert c.all(.read | .other) + // + assert c.has(.read | .execute | .other) + assert c.has(.read | .execute) + assert c.has(.execute | .other) + assert c.has(.read | .other) }