Skip to content

Commit 0747a5c

Browse files
use initialized/used modules instead of analyzing functions
1 parent be087aa commit 0747a5c

File tree

3 files changed

+25
-46
lines changed

3 files changed

+25
-46
lines changed

vyper/semantics/analysis/module.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,14 @@ def validate_module_semantics_r(
7575

7676
with namespace.enter_scope(), import_graph.enter_path(module_ast):
7777
analyzer = ModuleAnalyzer(module_ast, input_bundle, namespace, import_graph, is_interface)
78-
analyzer.analyze()
78+
analyzer.analyze_module_body()
7979

8080
_analyze_call_graph(module_ast)
8181
generate_public_variable_getters(module_ast)
8282

83-
ret = ModuleT(module_ast)
83+
# ModuleT generates the interface; for this we should have
84+
# public variable getters already generated.
85+
ret = ModuleT(module_ast) # note: validates unique method ids
8486
module_ast._metadata["type"] = ret
8587

8688
# if this is an interface, the function is already validated
@@ -145,7 +147,7 @@ def _compute_reachable_set(fn_t: ContractFunctionT, path: list[ContractFunctionT
145147
_compute_reachable_set(g, path=path)
146148

147149
g_reachable = g.reachable_internal_functions
148-
assert fn_t not in g_reachable # sanity check
150+
assert fn_t not in g_reachable # sanity check
149151
fn_t.reachable_internal_functions.update(g_reachable)
150152

151153
fn_t.reachable_internal_functions.add(g)
@@ -184,10 +186,7 @@ def __init__(
184186
if not hasattr(self.input_bundle._cache, "_ast_of"):
185187
self.input_bundle._cache._ast_of: dict[int, vy_ast.Module] = {} # type: ignore
186188

187-
def analyze(self) -> ModuleT:
188-
# generate a `ModuleT` from the top-level node
189-
# note: also validates unique method ids
190-
189+
def analyze_module_body(self):
191190
assert "type" not in self.ast._metadata
192191

193192
self._to_visit = self.ast.body.copy()

vyper/semantics/types/function.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
validate_expected_type,
3131
)
3232
from vyper.semantics.data_locations import DataLocation
33-
from vyper.semantics.types.base import KwargSettings, VyperType, is_type_t
33+
from vyper.semantics.types.base import KwargSettings, VyperType
3434
from vyper.semantics.types.primitives import BoolT
3535
from vyper.semantics.types.shortcuts import UINT256_T
3636
from vyper.semantics.types.subscriptable import TupleT
@@ -462,9 +462,6 @@ def getter_from_VariableDecl(cls, node: vy_ast.VariableDecl) -> "ContractFunctio
462462
ast_def=node,
463463
)
464464

465-
def get_used_events(self): # -> OrderedSet[EventT]:
466-
pass
467-
468465
@property
469466
# convenience property for compare_signature, as it would
470467
# appear in a public interface

vyper/semantics/types/module.py

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,22 @@
99
NamespaceCollision,
1010
StructureException,
1111
UnfoldableNode,
12-
VyperException,
1312
)
1413
from vyper.semantics.analysis.base import Modifiability
1514
from vyper.semantics.analysis.utils import (
1615
check_modifiability,
17-
get_exact_type_from_node,
1816
validate_expected_type,
1917
validate_unique_method_ids,
2018
)
21-
from vyper.utils import OrderedSet
2219
from vyper.semantics.data_locations import DataLocation
23-
from vyper.semantics.types.base import TYPE_T, VyperType, is_type_t
20+
from vyper.semantics.types.base import TYPE_T, VyperType
2421
from vyper.semantics.types.function import ContractFunctionT
2522
from vyper.semantics.types.primitives import AddressT
2623
from vyper.semantics.types.user import EventT, StructT, _UserType
24+
from vyper.utils import OrderedSet
2725

2826
if TYPE_CHECKING:
29-
from vyper.semantics.analysis.base import ModuleInfo
27+
from vyper.semantics.analysis.base import InitializesInfo, ModuleInfo
3028

3129

3230
class InterfaceT(_UserType):
@@ -222,7 +220,7 @@ def from_ModuleT(cls, module_t: "ModuleT") -> "InterfaceT":
222220
if (fn_t := module_t.init_function) is not None:
223221
funcs.append((fn_t.name, fn_t))
224222

225-
events = [(event_t.name, event_t) for event_t in module_t.used_events]
223+
events = [(event_t.name, event_t) for event_t in module_t.exported_events]
226224

227225
# these are accessible via import, but they do not show up
228226
# in the ABI json
@@ -282,16 +280,16 @@ def __init__(self, module: vy_ast.Module, name: Optional[str] = None):
282280

283281
for e in self.event_defs:
284282
# add the type of the event so it can be used in call position
285-
self.add_member(e.name, TYPE_T(e._metadata["event_type"])) # type: ignore
283+
self.add_member(e.name, TYPE_T(e._metadata["event_type"]))
286284

287285
for s in self.struct_defs:
288286
# add the type of the struct so it can be used in call position
289-
self.add_member(s.name, TYPE_T(s._metadata["struct_type"])) # type: ignore
290-
self._helper.add_member(s.name, TYPE_T(s._metadata["struct_type"])) # type: ignore
287+
self.add_member(s.name, TYPE_T(s._metadata["struct_type"]))
288+
self._helper.add_member(s.name, TYPE_T(s._metadata["struct_type"]))
291289

292290
for i in self.interface_defs:
293291
# add the type of the interface so it can be used in call position
294-
self.add_member(i.name, TYPE_T(i._metadata["interface_type"])) # type: ignore
292+
self.add_member(i.name, TYPE_T(i._metadata["interface_type"]))
295293

296294
for v in self.variable_decls:
297295
self.add_member(v.target.id, v.target._metadata["varinfo"])
@@ -389,7 +387,7 @@ def exports_decls(self):
389387
return self._module.get_children(vy_ast.ExportsDecl)
390388

391389
@cached_property
392-
def used_modules(self):
390+
def used_modules(self) -> list["ModuleInfo"]:
393391
# modules which are written to
394392
ret = []
395393
for node in self.uses_decls:
@@ -398,7 +396,7 @@ def used_modules(self):
398396
return ret
399397

400398
@property
401-
def initialized_modules(self):
399+
def initialized_modules(self) -> list["InitializesInfo"]:
402400
# modules which are initialized to
403401
ret = []
404402
for node in self.initializes_decls:
@@ -440,31 +438,16 @@ def functions(self):
440438
return {f.name: f._metadata["func_type"] for f in self.function_defs}
441439

442440
@cached_property
443-
# it would be nice to rely on the function analyzer to do this analysis,
444-
# but we don't have the result of function analysis at the time we need to
445-
# construct `self.interface`.
446-
def used_events(self) -> OrderedSet[EventT]:
441+
def exported_events(self) -> OrderedSet[EventT]:
447442
ret: OrderedSet[EventT] = OrderedSet()
448443

449-
reachable = OrderedSet()
450-
if self.init_function is not None:
451-
reachable.add(self.init_function)
452-
reachable.update(self.init_function.reachable_internal_functions)
453-
for fn_t in self.exposed_functions:
454-
reachable.add(fn_t)
455-
reachable.update(fn_t.reachable_internal_functions)
456-
457-
for fn_t in reachable:
458-
fn_ast = fn_t.decl_node
459-
assert isinstance(fn_ast, vy_ast.FunctionDef)
460-
461-
for node in fn_ast.get_descendants(vy_ast.Log):
462-
call_t = get_exact_type_from_node(node.value.func)
463-
if not is_type_t(call_t, EventT):
464-
# this is an error, but it will be handled later
465-
continue
466-
467-
ret.add(call_t.typedef)
444+
for module_info in self.used_modules:
445+
ret.update(module_info.module_t.exported_events)
446+
447+
for info in self.initialized_modules:
448+
ret.update(info.module_info.module_t.exported_events)
449+
450+
ret.update([n._metadata["event_type"] for n in self.event_defs])
468451

469452
return ret
470453

0 commit comments

Comments
 (0)