From 8a4cfe39b4f0c682459cc393fca86e2d51f7ca09 Mon Sep 17 00:00:00 2001 From: cyberthirst Date: Mon, 18 Mar 2024 11:38:57 +0100 Subject: [PATCH 1/5] fix import of flag type --- vyper/codegen/expr.py | 11 ++++++----- vyper/semantics/analysis/module.py | 1 + vyper/semantics/types/module.py | 8 ++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/vyper/codegen/expr.py b/vyper/codegen/expr.py index d7afe6c7f6..6bb87e5b54 100644 --- a/vyper/codegen/expr.py +++ b/vyper/codegen/expr.py @@ -206,11 +206,12 @@ def parse_Name(self): def parse_Attribute(self): typ = self.expr._metadata["type"] - # MyFlag.foo - if ( - isinstance(typ, FlagT) - and isinstance(self.expr.value, vy_ast.Name) - and typ.name == self.expr.value.id + # (lib1).MyFlag.foo + if isinstance(typ, FlagT) and ( + (isinstance(self.expr.value, vy_ast.Name) + and typ.name == self.expr.value.id) + or (isinstance(self.expr.value, vy_ast.Attribute) + and typ.name == self.expr.value.attr) ): # 0, 1, 2, .. 255 flag_id = typ._flag_members[self.expr.attr] diff --git a/vyper/semantics/analysis/module.py b/vyper/semantics/analysis/module.py index 90493d643b..f4b7db129f 100644 --- a/vyper/semantics/analysis/module.py +++ b/vyper/semantics/analysis/module.py @@ -657,6 +657,7 @@ def _validate_self_namespace(): def visit_FlagDef(self, node): obj = FlagT.from_FlagDef(node) + node._metadata["flag_type"] = obj self.namespace[node.name] = obj def visit_EventDef(self, node): diff --git a/vyper/semantics/types/module.py b/vyper/semantics/types/module.py index a242bfa1fe..0d2b343e0d 100644 --- a/vyper/semantics/types/module.py +++ b/vyper/semantics/types/module.py @@ -300,6 +300,10 @@ def __init__(self, module: vy_ast.Module, name: Optional[str] = None): # add the type of the event so it can be used in call position self.add_member(e.name, TYPE_T(e._metadata["event_type"])) # type: ignore + for f in self.flag_defs: + self.add_member(f.name, TYPE_T(f._metadata["flag_type"])) + self._helper.add_member(f.name, TYPE_T(f._metadata["flag_type"])) + for s in self.struct_defs: # add the type of the struct so it can be used in call position self.add_member(s.name, TYPE_T(s._metadata["struct_type"])) # type: ignore @@ -347,6 +351,10 @@ def function_defs(self): def event_defs(self): return self._module.get_children(vy_ast.EventDef) + @cached_property + def flag_defs(self): + return self._module.get_children(vy_ast.FlagDef) + @property def struct_defs(self): return self._module.get_children(vy_ast.StructDef) From ba321604c5ff4d1abba2ed056e69022eee3ae81e Mon Sep 17 00:00:00 2001 From: cyberthirst Date: Mon, 18 Mar 2024 11:39:43 +0100 Subject: [PATCH 2/5] add nested import type rule --- vyper/ast/grammar.lark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vyper/ast/grammar.lark b/vyper/ast/grammar.lark index cd7b64e6c3..1c318a76a5 100644 --- a/vyper/ast/grammar.lark +++ b/vyper/ast/grammar.lark @@ -98,7 +98,7 @@ tuple_def: "(" ( NAME | array_def | dyn_array_def | tuple_def ) ( "," ( NAME | a // NOTE: Map takes a basic type and maps to another type (can be non-basic, including maps) _MAP: "HashMap" map_def: _MAP "[" ( NAME | array_def ) "," type "]" -imported_type: NAME "." NAME +imported_type: NAME ("." NAME)+ type: ( NAME | imported_type | array_def | tuple_def | map_def | dyn_array_def ) // Structs can be composed of 1+ basic types or other custom_types From 039e5f496793c511d48e94f39973b756dd4a55bd Mon Sep 17 00:00:00 2001 From: cyberthirst Date: Mon, 18 Mar 2024 11:40:24 +0100 Subject: [PATCH 3/5] add test for flag type imports --- .../codegen/modules/test_flag_imports.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/functional/codegen/modules/test_flag_imports.py diff --git a/tests/functional/codegen/modules/test_flag_imports.py b/tests/functional/codegen/modules/test_flag_imports.py new file mode 100644 index 0000000000..909b2f565e --- /dev/null +++ b/tests/functional/codegen/modules/test_flag_imports.py @@ -0,0 +1,41 @@ +def test_import_flag_types(make_input_bundle, get_contract): + lib1 = """ +import lib2 + +flag Roles: + ADMIN + USER + +enum Roles2: + ADMIN + USER + +role: Roles +role2: Roles2 +role3: lib2.Roles3 + """ + lib2 = """ +flag Roles3: + ADMIN + USER + NOBODY + """ + contract = """ +import lib1 + +initializes: lib1 + +@external +def bar(r: lib1.Roles, r2: lib1.Roles2, r3: lib1.lib2.Roles3) -> bool: + lib1.role = r + lib1.role2 = r2 + lib1.role3 = r3 + assert lib1.role == lib1.Roles.ADMIN + assert lib1.role2 == lib1.Roles2.USER + assert lib1.role3 == lib1.lib2.Roles3.NOBODY + return True + """ + + input_bundle = make_input_bundle({"lib1.vy": lib1, "lib2.vy": lib2}) + c = get_contract(contract, input_bundle=input_bundle) + assert c.bar(1, 2, 4) is True From 6dfd08d57e07b23929706bfa4aae7b466271841b Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 19 Mar 2024 16:52:27 -0400 Subject: [PATCH 4/5] simplify a test --- tests/functional/codegen/modules/test_flag_imports.py | 2 +- vyper/codegen/expr.py | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/functional/codegen/modules/test_flag_imports.py b/tests/functional/codegen/modules/test_flag_imports.py index 909b2f565e..fd954dab02 100644 --- a/tests/functional/codegen/modules/test_flag_imports.py +++ b/tests/functional/codegen/modules/test_flag_imports.py @@ -1,6 +1,6 @@ def test_import_flag_types(make_input_bundle, get_contract): lib1 = """ -import lib2 +import lib2 flag Roles: ADMIN diff --git a/vyper/codegen/expr.py b/vyper/codegen/expr.py index 6bb87e5b54..35b94cce83 100644 --- a/vyper/codegen/expr.py +++ b/vyper/codegen/expr.py @@ -207,12 +207,7 @@ def parse_Attribute(self): typ = self.expr._metadata["type"] # (lib1).MyFlag.foo - if isinstance(typ, FlagT) and ( - (isinstance(self.expr.value, vy_ast.Name) - and typ.name == self.expr.value.id) - or (isinstance(self.expr.value, vy_ast.Attribute) - and typ.name == self.expr.value.attr) - ): + if isinstance(typ, FlagT) and is_type_t(self.expr.value._metadata["type"], FlagT): # 0, 1, 2, .. 255 flag_id = typ._flag_members[self.expr.attr] value = 2**flag_id # 0 => 0001, 1 => 0010, 2 => 0100, etc. From b180e2faba8093ca4b7ac3647c1fc80770986dd4 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 19 Mar 2024 17:19:33 -0400 Subject: [PATCH 5/5] update a comment --- vyper/codegen/expr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vyper/codegen/expr.py b/vyper/codegen/expr.py index 35b94cce83..8ce4288c89 100644 --- a/vyper/codegen/expr.py +++ b/vyper/codegen/expr.py @@ -206,7 +206,8 @@ def parse_Name(self): def parse_Attribute(self): typ = self.expr._metadata["type"] - # (lib1).MyFlag.foo + # check if we have a flag constant, e.g. + # [lib1].MyFlag.FOO if isinstance(typ, FlagT) and is_type_t(self.expr.value._metadata["type"], FlagT): # 0, 1, 2, .. 255 flag_id = typ._flag_members[self.expr.attr]