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: implement "stateless" modules #3663

Merged
merged 140 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
8a56425
feat: implement pure libraries
charles-cooper Nov 7, 2023
0625bbb
fix topsort
charles-cooper Nov 7, 2023
684a83d
fix a typo
charles-cooper Nov 7, 2023
3ef38c4
introduce ModuleInfo
charles-cooper Nov 8, 2023
e3edb7e
fix a circular import
charles-cooper Nov 8, 2023
eca6379
change a docstring
charles-cooper Nov 8, 2023
bb37ee2
`at()` to convert ModuleT to InterfaceT
charles-cooper Nov 8, 2023
2038549
fix a bug
charles-cooper Nov 8, 2023
3f38b43
feat: module.at(<address>)
charles-cooper Nov 8, 2023
2caaf9d
Merge branch 'master' into feat/libraries
charles-cooper Nov 9, 2023
aba6558
fix some bugs
charles-cooper Nov 9, 2023
febaa96
fix some tests
charles-cooper Nov 9, 2023
19404e9
detect import cycles
charles-cooper Nov 10, 2023
21a04c3
remove `.name` from module ast
charles-cooper Nov 11, 2023
52943e1
abstract out a common exception rewriting pattern
charles-cooper Nov 11, 2023
4a8cc12
remove a note
charles-cooper Nov 17, 2023
0a786f7
rollback `module.at()` method
charles-cooper Nov 20, 2023
b61176e
fix some tests
charles-cooper Nov 21, 2023
6c7f795
refactor builtin interfaces to `.vyi` files
charles-cooper Nov 23, 2023
c923714
wip: .vyi files
charles-cooper Nov 23, 2023
924980a
implement ellipsis in interfaces
charles-cooper Nov 28, 2023
e9da1f2
whitespace
charles-cooper Dec 6, 2023
4a3cfd2
fix getter generation in ABI
charles-cooper Dec 6, 2023
6a7e603
rename "type" metadata to "func_type" on function declaration objects
charles-cooper Dec 7, 2023
9171934
Merge branch 'master' into feat/libraries
charles-cooper Dec 7, 2023
6c81142
fix some interface tests
charles-cooper Dec 7, 2023
e7e37b8
fix some more tests
charles-cooper Dec 7, 2023
1b7162b
revert change enabling `Bytes[...]`
charles-cooper Dec 10, 2023
26fb9e0
fix old usage of reachable_internal_functions
charles-cooper Dec 10, 2023
1e2a235
fix another type error
charles-cooper Dec 10, 2023
c58bfa0
fix sqrt
charles-cooper Dec 10, 2023
467720b
ensure _ir_info is populated whether or not functions are reachable
charles-cooper Dec 10, 2023
c6eba5e
fix a bad test
charles-cooper Dec 10, 2023
9c537cc
fix some interfaces in tests
charles-cooper Dec 10, 2023
25563f6
fix a bad type dispatch
charles-cooper Dec 10, 2023
9838ad6
fix call to validate_semantics
charles-cooper Dec 10, 2023
90731a2
fix InterfaceT.from_Module
charles-cooper Dec 10, 2023
a86cc02
set search path correctly in nested imports
charles-cooper Dec 10, 2023
82cb5bd
fix some tests
charles-cooper Dec 10, 2023
0a3d618
fix another small test
charles-cooper Dec 10, 2023
c6d8892
fix lint
charles-cooper Dec 10, 2023
88843e9
fix some calls to validate_semantics
charles-cooper Dec 10, 2023
2f739d0
fix mypy
charles-cooper Dec 10, 2023
0ce2a58
add a todo
charles-cooper Dec 10, 2023
ba50a83
fix an old key
charles-cooper Dec 10, 2023
dc506a8
move test_interfaces.py to codegen/ tests
charles-cooper Dec 10, 2023
ecb3841
remove dead code
charles-cooper Dec 10, 2023
5bb66b5
remove dead package pytest-rerunfailures
charles-cooper Dec 10, 2023
3d5e3b1
add a note
charles-cooper Dec 10, 2023
ad78f07
remove dead function
charles-cooper Dec 10, 2023
7ebd09c
refactor: move `parse_*` functions, remove vyper.ast.annotation
charles-cooper Dec 10, 2023
a0ff2b8
refactor: CompilerInput.from_string
charles-cooper Dec 10, 2023
84a33db
implement eq/hash on ModuleT
charles-cooper Dec 10, 2023
84f2298
remove dead comment
charles-cooper Dec 10, 2023
21abfb6
fix some bad imports
charles-cooper Dec 10, 2023
2a9db07
fix lint
charles-cooper Dec 10, 2023
0b78923
remove `remove_unused_statements()`
charles-cooper Dec 10, 2023
269a9cf
refactor cycle detection
charles-cooper Dec 10, 2023
b0ac484
remove expand_annotated_ast
charles-cooper Dec 10, 2023
a95000d
fix analysis on imported modules
charles-cooper Dec 10, 2023
50f388e
small fixes
charles-cooper Dec 10, 2023
9b5bff2
factor out parse_and_fold_ast
charles-cooper Dec 10, 2023
a43beff
fix mypy
charles-cooper Dec 10, 2023
487e29b
fix global namespace
charles-cooper Dec 10, 2023
abbe697
fix generate_inline_function
charles-cooper Dec 10, 2023
9509dc9
Merge branch 'master' into feat/libraries
charles-cooper Dec 10, 2023
fa4a30f
fix tokenization of comments in lark grammar
charles-cooper Dec 10, 2023
292d085
rename storage layout test directory
charles-cooper Dec 10, 2023
5b8847e
relax import restrictions
charles-cooper Dec 10, 2023
b26c00a
improve ModuleNotFound error
charles-cooper Dec 10, 2023
e4693a0
fix name/alias resolution
charles-cooper Dec 10, 2023
93401f3
add library test to test_compile_files
charles-cooper Dec 10, 2023
4295dcc
missing import
charles-cooper Dec 10, 2023
373abd6
update interfaces output
charles-cooper Dec 10, 2023
663dc1e
change function labels in IR
charles-cooper Dec 10, 2023
7ac2f62
add a note
charles-cooper Dec 10, 2023
d297418
fix: use codegen.core._freshname to generate self call labels
charles-cooper Dec 10, 2023
34b45c8
make compilation targets adhere to outputSelection
charles-cooper Dec 10, 2023
5c0d3a7
use orderedset for json inputs
charles-cooper Dec 10, 2023
9902baf
add library to json tests
charles-cooper Dec 10, 2023
9bdf12c
remove dead code
charles-cooper Dec 10, 2023
64f6840
fix lint
charles-cooper Dec 10, 2023
42dfd2b
fix lint
charles-cooper Dec 10, 2023
ba11cff
fix a signature
charles-cooper Dec 11, 2023
c7ea5c9
disambiguate types with same name across different modules
charles-cooper Dec 11, 2023
418eb97
fix some small bugs
charles-cooper Dec 11, 2023
e64b52c
update some hardcoded asm
charles-cooper Dec 11, 2023
f5ff470
fix unassigned variable
charles-cooper Dec 11, 2023
c86d267
fix lint
charles-cooper Dec 11, 2023
0ac1043
make module argument optional for structs
charles-cooper Dec 11, 2023
5ebb252
fix some updates to json cli api
charles-cooper Dec 11, 2023
d880e58
add libraries test file
charles-cooper Dec 11, 2023
34052b0
roll back changes require threading around the module ast
charles-cooper Dec 11, 2023
15ad3cc
fix lint
charles-cooper Dec 11, 2023
91642f0
add InputBundle._normalize_path
charles-cooper Dec 11, 2023
4db4928
rename ModuleInfo.module to ModuleInfo.module_t
charles-cooper Dec 11, 2023
028d96c
fix source_id threading
charles-cooper Dec 11, 2023
8d7a5dd
enrich CompilerInput
charles-cooper Dec 11, 2023
0a37e1c
change compile_code api from contract_name= to contract_path=
charles-cooper Dec 11, 2023
8b477eb
introduce source_id= back into compile_code
charles-cooper Dec 11, 2023
64a5379
add compile_from_file_input
charles-cooper Dec 11, 2023
39575e8
fix bunch of bugs in path resolution of imports
charles-cooper Dec 11, 2023
9ef6ea7
fix compile for regular files
charles-cooper Dec 11, 2023
b64035d
add support for attribute access on modules/interfaces: structs and e…
charles-cooper Dec 11, 2023
58940a0
allow string input to CompilerData
charles-cooper Dec 11, 2023
f34d7d1
remove ability to `implements: ModuleT`
charles-cooper Dec 11, 2023
be07dfd
fix small type bug
charles-cooper Dec 11, 2023
88250cc
fix a bad function call
charles-cooper Dec 11, 2023
183aada
fix a bug in _normalize_path
charles-cooper Dec 11, 2023
0a84ef2
fix another bad function call
charles-cooper Dec 11, 2023
3d2c95f
handle self calls in statements
charles-cooper Dec 12, 2023
2e32ba8
fix transitive imports
charles-cooper Dec 12, 2023
5476076
trap calls to external functions in libraries
charles-cooper Dec 12, 2023
bfde0cb
add more tests for libraries
charles-cooper Dec 12, 2023
7aa80e3
new scheme for IR identifiers -- use function ID
charles-cooper Dec 12, 2023
91c16e5
update selector table stability tests
charles-cooper Dec 12, 2023
5a9eea7
fix asm tests
charles-cooper Dec 12, 2023
59922f3
fix lint, mypy
charles-cooper Dec 12, 2023
a734b09
hygiene: raise proper exception
charles-cooper Dec 12, 2023
dd1ea14
test imported structs
charles-cooper Dec 12, 2023
c7584bd
add a couple more tests for libraries
charles-cooper Dec 12, 2023
76f3abb
fix a regression
charles-cooper Dec 12, 2023
48a76b4
handle some errors better
charles-cooper Dec 12, 2023
1fafca6
fix mypy
charles-cooper Dec 12, 2023
a441e2f
remove a dead variable
charles-cooper Dec 12, 2023
6e1a05e
update a test name
charles-cooper Dec 12, 2023
94ff82b
change an argument name
charles-cooper Dec 12, 2023
6edcbdd
reject duplicate imports
charles-cooper Dec 12, 2023
d9b9f3b
fix some tests
charles-cooper Dec 13, 2023
0b64abe
rename test file
charles-cooper Dec 13, 2023
255a93a
refactor: move InterfaceT into vyper/semantics/types/module.py
charles-cooper Dec 13, 2023
9ec83d4
address review comments
charles-cooper Dec 13, 2023
74c630e
remove unneeded F401
charles-cooper Dec 13, 2023
132fde0
add library code eliminator test
charles-cooper Dec 14, 2023
64bc3a5
make nested libraries work
charles-cooper Dec 15, 2023
dcb55b4
refactor a side effect
charles-cooper Dec 15, 2023
d26f401
fix missing import
charles-cooper Dec 15, 2023
bea05ca
add test for imported slice
charles-cooper Dec 15, 2023
7066688
remove stray print
charles-cooper Dec 16, 2023
b0c6684
add a note on Module.__eq__
charles-cooper Dec 16, 2023
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
6 changes: 2 additions & 4 deletions vyper/builtins/_utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from vyper.ast import parse_to_ast
from vyper.codegen.context import Context
from vyper.codegen.global_context import GlobalContext
from vyper.codegen.stmt import parse_body
from vyper.semantics.analysis.local import FunctionNodeVisitor
from vyper.semantics.namespace import Namespace, override_global_namespace
from vyper.semantics.types.function import ContractFunctionT, FunctionVisibility, StateMutability
from vyper.semantics.types.module import ModuleT
Dismissed Show dismissed Hide dismissed


def _strip_source_pos(ir_node):
Expand All @@ -29,9 +29,7 @@
# annotate the AST as side effects.
FunctionNodeVisitor(ast_code, ast_code.body[0], namespace)

new_context = Context(
vars_=variables, global_ctx=GlobalContext(), memory_allocator=memory_allocator
)
new_context = Context(vars_=variables, global_ctx=ModuleT(), memory_allocator=memory_allocator)
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
generated_ir = parse_body(ast_code.body[0].body, new_context)
# strip source position info from the generated_ir since
# it doesn't make any sense (e.g. the line numbers will start from 0
Expand Down
8 changes: 4 additions & 4 deletions vyper/codegen/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __repr__(self):
class Context:
def __init__(
self,
global_ctx,
module_ctx,
memory_allocator,
vars_=None,
forvars=None,
Expand All @@ -60,7 +60,7 @@ def __init__(
self.vars = vars_ or {}

# Global variables, in the form (name, storage location, type)
self.globals = global_ctx.variables
self.globals = module_ctx.variables

# Variables defined in for loops, e.g. for i in range(6): ...
self.forvars = forvars or {}
Expand All @@ -75,8 +75,8 @@ def __init__(
# Whether we are currently parsing a range expression
self.in_range_expr = False

# store global context
self.global_ctx = global_ctx
# store module context
self.module_ctx = module_ctx

# full function type
self.func_t = func_t
Expand Down
2 changes: 1 addition & 1 deletion vyper/codegen/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ def parse_Call(self):
# type annotations are consistently available
isinstance(self.expr.func, vy_ast.Attribute)
and isinstance(self.expr.func.value, vy_ast.Name)
and self.expr.func.value.id == "self"
and self.expr.func._metadata["type"].is_internal
):
return self_call.ir_for_self_call(self.expr, self.context)
else:
Expand Down
6 changes: 3 additions & 3 deletions vyper/codegen/function_definitions/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
from vyper.codegen.core import check_single_exit
from vyper.codegen.function_definitions.external_function import generate_ir_for_external_function
from vyper.codegen.function_definitions.internal_function import generate_ir_for_internal_function
from vyper.codegen.global_context import GlobalContext
from vyper.codegen.ir_node import IRnode
from vyper.codegen.memory_allocator import MemoryAllocator
from vyper.exceptions import CompilerPanic
from vyper.semantics.types import VyperType
from vyper.semantics.types.function import ContractFunctionT
from vyper.semantics.types.module import ModuleT
from vyper.utils import MemoryPositions, calc_mem_gas, mkalphanum


Expand Down Expand Up @@ -94,7 +94,7 @@ class InternalFuncIR(FuncIR):

# TODO: should split this into external and internal ir generation?
def generate_ir_for_function(
code: vy_ast.FunctionDef, global_ctx: GlobalContext, is_ctor_context: bool = False
code: vy_ast.FunctionDef, module_ctx: ModuleT, is_ctor_context: bool = False
) -> FuncIR:
"""
Parse a function and produce IR code for the function, includes:
Expand Down Expand Up @@ -126,7 +126,7 @@ def generate_ir_for_function(

context = Context(
vars_=None,
global_ctx=global_ctx,
module_ctx=module_ctx,
memory_allocator=memory_allocator,
constancy=Constancy.Mutable if func_t.is_mutable else Constancy.Constant,
func_t=func_t,
Expand Down
32 changes: 0 additions & 32 deletions vyper/codegen/global_context.py

This file was deleted.

66 changes: 32 additions & 34 deletions vyper/codegen/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,31 @@
from vyper.codegen import core, jumptable_utils
from vyper.codegen.core import shr
from vyper.codegen.function_definitions import generate_ir_for_function
from vyper.codegen.global_context import GlobalContext
from vyper.codegen.ir_node import IRnode
from vyper.compiler.settings import _is_debug_mode
from vyper.exceptions import CompilerPanic
from vyper.utils import method_id_int
from vyper.semantics.types.module import ModuleT
from vyper.utils import OrderedSet, method_id_int


def _topsort_helper(functions, lookup):
def _topsort(functions):
# single pass to get a global topological sort of functions (so that each
# function comes after each of its callees). may have duplicates, which get
# filtered out in _topsort()
# filtered out at the end

ret = []
for f in functions:
# called_functions is a list of ContractFunctions, need to map
# back to FunctionDefs.
callees = [lookup[t.name] for t in f._metadata["type"].called_functions]
ret.extend(_topsort_helper(callees, lookup))
ret.append(f)
fn_t = f._metadata["type"]
if not fn_t.is_external:
continue

return ret
for internal_fn in fn_t.reachable_internal_functions:
assert internal_fn.ast_def is not None
ret.append(internal_fn.ast_def)

ret.append(f)

def _topsort(functions):
lookup = {f.name: f for f in functions}
# strip duplicates
return list(dict.fromkeys(_topsort_helper(functions, lookup)))
return list(OrderedSet.fromkeys(ret))


def _is_constructor(func_ast):
Expand Down Expand Up @@ -86,12 +84,12 @@ def _ir_for_internal_function(func_ast, *args, **kwargs):
return generate_ir_for_function(func_ast, *args, **kwargs).func_ir


def _generate_external_entry_points(external_functions, global_ctx):
def _generate_external_entry_points(external_functions, module_ctx):
entry_points = {} # map from ABI sigs to ir code
sig_of = {} # reverse map from method ids to abi sig

for code in external_functions:
func_ir = generate_ir_for_function(code, global_ctx)
func_ir = generate_ir_for_function(code, module_ctx)
for abi_sig, entry_point in func_ir.entry_points.items():
method_id = method_id_int(abi_sig)
assert abi_sig not in entry_points
Expand All @@ -113,13 +111,13 @@ def _generate_external_entry_points(external_functions, global_ctx):
# into a bucket (of about 8-10 items), and then uses perfect hash
# to select the final function.
# costs about 212 gas for typical function and 8 bytes of code (+ ~87 bytes of global overhead)
def _selector_section_dense(external_functions, global_ctx):
def _selector_section_dense(external_functions, module_ctx):
function_irs = []

if len(external_functions) == 0:
return IRnode.from_list(["seq"])

entry_points, sig_of = _generate_external_entry_points(external_functions, global_ctx)
entry_points, sig_of = _generate_external_entry_points(external_functions, module_ctx)

# generate the label so the jumptable works
for abi_sig, entry_point in entry_points.items():
Expand Down Expand Up @@ -264,13 +262,13 @@ def _selector_section_dense(external_functions, global_ctx):
# a bucket, and then descends into linear search from there.
# costs about 126 gas for typical (nonpayable, >0 args, avg bucket size 1.5)
# function and 24 bytes of code (+ ~23 bytes of global overhead)
def _selector_section_sparse(external_functions, global_ctx):
def _selector_section_sparse(external_functions, module_ctx):
ret = ["seq"]

if len(external_functions) == 0:
return ret

entry_points, sig_of = _generate_external_entry_points(external_functions, global_ctx)
entry_points, sig_of = _generate_external_entry_points(external_functions, module_ctx)

n_buckets, buckets = jumptable_utils.generate_sparse_jumptable_buckets(entry_points.keys())

Expand Down Expand Up @@ -367,14 +365,14 @@ def _selector_section_sparse(external_functions, global_ctx):
# O(n) linear search for the method id
# mainly keep this in for backends which cannot handle the indirect jump
# in selector_section_dense and selector_section_sparse
def _selector_section_linear(external_functions, global_ctx):
def _selector_section_linear(external_functions, module_ctx):
ret = ["seq"]
if len(external_functions) == 0:
return ret

ret.append(["if", ["lt", "calldatasize", 4], ["goto", "fallback"]])

entry_points, sig_of = _generate_external_entry_points(external_functions, global_ctx)
entry_points, sig_of = _generate_external_entry_points(external_functions, module_ctx)

dispatcher = ["seq"]

Expand Down Expand Up @@ -402,10 +400,10 @@ def _selector_section_linear(external_functions, global_ctx):
return ret


# take a GlobalContext, and generate the runtime and deploy IR
def generate_ir_for_module(global_ctx: GlobalContext) -> tuple[IRnode, IRnode]:
# take a ModuleT, and generate the runtime and deploy IR
def generate_ir_for_module(module_ctx: ModuleT) -> tuple[IRnode, IRnode]:
# order functions so that each function comes after all of its callees
function_defs = _topsort(global_ctx.functions)
function_defs = _topsort(module_ctx.functions)

runtime_functions = [f for f in function_defs if not _is_constructor(f)]
init_function = next((f for f in function_defs if _is_constructor(f)), None)
Expand All @@ -421,20 +419,20 @@ def generate_ir_for_module(global_ctx: GlobalContext) -> tuple[IRnode, IRnode]:

# compile internal functions first so we have the function info
for func_ast in internal_functions:
func_ir = _ir_for_internal_function(func_ast, global_ctx, False)
func_ir = _ir_for_internal_function(func_ast, module_ctx, False)
internal_functions_ir.append(IRnode.from_list(func_ir))

if core._opt_none():
selector_section = _selector_section_linear(external_functions, global_ctx)
selector_section = _selector_section_linear(external_functions, module_ctx)
# dense vs sparse global overhead is amortized after about 4 methods.
# (--debug will force dense selector table anyway if _opt_codesize is selected.)
elif core._opt_codesize() and (len(external_functions) > 4 or _is_debug_mode()):
selector_section = _selector_section_dense(external_functions, global_ctx)
selector_section = _selector_section_dense(external_functions, module_ctx)
else:
selector_section = _selector_section_sparse(external_functions, global_ctx)
selector_section = _selector_section_sparse(external_functions, module_ctx)

if default_function:
fallback_ir = _ir_for_fallback_or_ctor(default_function, global_ctx)
fallback_ir = _ir_for_fallback_or_ctor(default_function, module_ctx)
else:
fallback_ir = IRnode.from_list(
["revert", 0, 0], annotation="Default function", error_msg="fallback function"
Expand All @@ -447,24 +445,24 @@ def generate_ir_for_module(global_ctx: GlobalContext) -> tuple[IRnode, IRnode]:
runtime.extend(internal_functions_ir)

deploy_code: List[Any] = ["seq"]
immutables_len = global_ctx.immutable_section_bytes
immutables_len = module_ctx.immutable_section_bytes
if init_function:
# cleanly rerun codegen for internal functions with `is_ctor_ctx=True`
ctor_internal_func_irs = []
internal_functions = [f for f in runtime_functions if _is_internal(f)]
for f in internal_functions:
init_func_t = init_function._metadata["type"]
if f.name not in init_func_t.recursive_calls:
if f.name not in init_func_t.reachable_internal_functions:
# unreachable code, delete it
continue

func_ir = _ir_for_internal_function(f, global_ctx, is_ctor_context=True)
func_ir = _ir_for_internal_function(f, module_ctx, is_ctor_context=True)
ctor_internal_func_irs.append(func_ir)

# generate init_func_ir after callees to ensure they have analyzed
# memory usage.
# TODO might be cleaner to separate this into an _init_ir helper func
init_func_ir = _ir_for_fallback_or_ctor(init_function, global_ctx, is_ctor_context=True)
init_func_ir = _ir_for_fallback_or_ctor(init_function, module_ctx, is_ctor_context=True)

# pass the amount of memory allocated for the init function
# so that deployment does not clobber while preparing immutables
Expand Down
14 changes: 6 additions & 8 deletions vyper/compiler/phases.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
from vyper import ast as vy_ast
from vyper.codegen import module
from vyper.codegen.core import anchor_opt_level
from vyper.codegen.global_context import GlobalContext
from vyper.codegen.ir_node import IRnode
from vyper.compiler.input_bundle import FilesystemInputBundle, InputBundle
from vyper.compiler.settings import OptimizationLevel, Settings
from vyper.exceptions import StructureException
from vyper.ir import compile_ir, optimizer
from vyper.semantics import set_data_positions, validate_semantics
from vyper.semantics.types.function import ContractFunctionT
from vyper.semantics.types.module import ModuleT
from vyper.typing import StorageLayout

DEFAULT_CONTRACT_NAME = PurePath("VyperContract.vy")
Expand All @@ -34,7 +34,7 @@ class CompilerData:
Top-level Vyper AST node
vyper_module_folded : vy_ast.Module
Folded Vyper AST
global_ctx : GlobalContext
global_ctx : ModuleT
Sorted, contextualized representation of the Vyper AST
ir_nodes : IRnode
IR used to generate deployment bytecode
Expand Down Expand Up @@ -154,8 +154,8 @@ def storage_layout(self) -> StorageLayout:
return storage_layout

@property
def global_ctx(self) -> GlobalContext:
return GlobalContext(self.vyper_module_folded)
def global_ctx(self) -> ModuleT:
return ModuleT(self.vyper_module_folded)

@cached_property
def _ir_output(self):
Expand Down Expand Up @@ -282,9 +282,7 @@ def generate_folded_ast(
return vyper_module_folded, symbol_tables


def generate_ir_nodes(
global_ctx: GlobalContext, optimize: OptimizationLevel
) -> tuple[IRnode, IRnode]:
def generate_ir_nodes(global_ctx: ModuleT, optimize: OptimizationLevel) -> tuple[IRnode, IRnode]:
"""
Generate the intermediate representation (IR) from the contextualized AST.

Expand All @@ -295,7 +293,7 @@ def generate_ir_nodes(

Arguments
---------
global_ctx : GlobalContext
global_ctx: ModuleT
Contextualized Vyper AST

Returns
Expand Down
4 changes: 3 additions & 1 deletion vyper/semantics/analysis/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,9 @@ def visit_For(self, node):
call_node,
)

for name in self.namespace["self"].typ.members[fn_name].recursive_calls:
for name in (
self.namespace["self"].typ.members[fn_name].reachable_internal_functions
):
# check for indirect modification
fn_node = self.vyper_module.get_children(vy_ast.FunctionDef, {"name": name})[0]
if _check_iterator_modification(node.iter, fn_node):
Expand Down
Loading
Loading