Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat[lang]: support flags from imported interfaces #4253

Merged
merged 20 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions vyper/semantics/analysis/constant_folding.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from vyper.semantics.analysis.base import VarInfo
from vyper.semantics.analysis.common import VyperNodeVisitorBase
from vyper.semantics.namespace import get_namespace
from vyper.semantics.types.module import InterfaceT


def constant_fold(module_ast: vy_ast.Module):
Expand Down Expand Up @@ -105,12 +106,15 @@
# not super type-safe but we don't care. just catch AttributeErrors
# and move on
try:
module_t = namespace[value.id].module_t

ns_member = namespace[value.id]
module_t = ns_member if isinstance(ns_member, InterfaceT) else ns_member.module_t
for module_name in path:
module_t = module_t.members[module_name].module_t

varinfo = module_t.get_member(node.attr, node)
varinfo = (

Check warning on line 113 in vyper/semantics/analysis/constant_folding.py

View check run for this annotation

Codecov / codecov/patch

vyper/semantics/analysis/constant_folding.py#L113

Added line #L113 was not covered by tests
module_t.get_type_member(node.attr, node)
if isinstance(module_t, InterfaceT)
else module_t.get_member(node.attr, node)
)

return varinfo.decl_node.value.get_folded_value()
except (VyperException, AttributeError, KeyError):
Expand Down
36 changes: 27 additions & 9 deletions vyper/semantics/types/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
StructureException,
UnfoldableNode,
)
from vyper.semantics.analysis.base import Modifiability
from vyper.semantics.analysis.base import Modifiability, VarInfo
Fixed Show fixed Hide fixed
from vyper.semantics.analysis.utils import (
check_modifiability,
get_exact_type_from_node,
Expand Down Expand Up @@ -45,28 +45,35 @@
functions: dict,
events: dict,
structs: dict,
constants: Optional[dict] = None,
) -> None:
validate_unique_method_ids(list(functions.values()))

members = functions | events | structs
constants = constants if constants else {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constants or {}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh we should do this for all the other things too, since in most cases we end up passing an empty dict for most of these parameters

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you mean to set the default for these params to None? should I do it in this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and yes!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking that since _from_lists is already passing a dictionary (either empty or with values) for all the params, and it is the only caller of the ctor for InterfaceT, maybe we can require a dict instead for all the same params in the ctor for InterfaceT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the changes in 69e5b3e to show what I meant in the previous comment.


members = functions | events | structs | constants

# sanity check: by construction, there should be no duplicates.
assert len(members) == len(functions) + len(events) + len(structs)
assert len(members) == len(functions) + len(events) + len(structs) + len(constants)

super().__init__(functions)

self._helper = VyperType(events | structs)
self._helper = VyperType(events | structs | constants)
self._id = _id
self._helper._id = _id
self.functions = functions
self.events = events
self.structs = structs
self.constants = constants

self.decl_node = decl_node

def get_type_member(self, attr, node):
# get an event or struct from this interface
return TYPE_T(self._helper.get_member(attr, node))
# get an event, struct or constant from this interface
type_member = self._helper.get_member(attr, node)

Check warning on line 73 in vyper/semantics/types/module.py

View check run for this annotation

Codecov / codecov/patch

vyper/semantics/types/module.py#L73

Added line #L73 was not covered by tests
if isinstance(type_member, (EventT, StructT)):
return TYPE_T(type_member)
return type_member

Check warning on line 76 in vyper/semantics/types/module.py

View check run for this annotation

Codecov / codecov/patch

vyper/semantics/types/module.py#L75-L76

Added lines #L75 - L76 were not covered by tests

@property
def getter_signature(self):
Expand Down Expand Up @@ -161,10 +168,12 @@
function_list: list[tuple[str, ContractFunctionT]],
event_list: list[tuple[str, EventT]],
struct_list: list[tuple[str, StructT]],
constant_list: Optional[list[tuple[str, VarInfo]]] = None,
) -> "InterfaceT":
functions = {}
events = {}
structs = {}
constants = {}

seen_items: dict = {}

Expand All @@ -187,7 +196,12 @@
_mark_seen(name, struct)
structs[name] = struct

return cls(interface_name, decl_node, functions, events, structs)
if constant_list:
for name, constant in constant_list:
_mark_seen(name, constant)
constants[name] = constant

Check warning on line 202 in vyper/semantics/types/module.py

View check run for this annotation

Codecov / codecov/patch

vyper/semantics/types/module.py#L201-L202

Added lines #L201 - L202 were not covered by tests

return cls(interface_name, decl_node, functions, events, structs, constants)

@classmethod
def from_json_abi(cls, name: str, abi: dict) -> "InterfaceT":
Expand Down Expand Up @@ -247,8 +261,12 @@
# these are accessible via import, but they do not show up
# in the ABI json
structs = [(node.name, node._metadata["struct_type"]) for node in module_t.struct_defs]

return cls._from_lists(module_t._id, module_t.decl_node, funcs, events, structs)
constants = [
(node.target.id, node.target._metadata["varinfo"])
for node in module_t.variable_decls
if node.target._metadata["varinfo"].modifiability is Modifiability.CONSTANT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can just check node.is_constant

]
return cls._from_lists(module_t._id, module_t.decl_node, funcs, events, structs, constants)

@classmethod
def from_InterfaceDef(cls, node: vy_ast.InterfaceDef) -> "InterfaceT":
Expand Down
Loading