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

refactor: reimplement AST folding #3669

Merged
merged 189 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
189 commits
Select commit Hold shift + click to select a range
50dc8fa
wip
tserg Nov 8, 2023
78d954c
Merge branch 'master' of https://github.com/vyperlang/vyper into refa…
tserg Nov 9, 2023
fafb447
use folded kwargs for fn defaults
tserg Nov 9, 2023
0f6b929
separate expansion steps
tserg Nov 9, 2023
6069f3b
add comment
tserg Nov 9, 2023
1c4bf3d
move remove unused statements after folding
tserg Nov 10, 2023
0aa3b69
fix get_index_value
tserg Nov 10, 2023
f2afc0d
wip
tserg Nov 10, 2023
7f75749
fix lint
tserg Nov 10, 2023
415e123
add compile time and runtime constants attributes
tserg Nov 12, 2023
1557927
fix list tests
tserg Nov 13, 2023
0bebd49
fix tuple exprinfo ctor; fix lint
tserg Nov 13, 2023
0f0ecd1
set folded_value metadata in constant node ctor
tserg Nov 13, 2023
e9be281
fix for loop bound
tserg Nov 13, 2023
94f4f88
wip
tserg Nov 13, 2023
3340cd1
fix folding tests
tserg Nov 13, 2023
763ab84
fix darray from annotation
tserg Nov 13, 2023
56b4149
fix raw call kwargs
tserg Nov 13, 2023
7c4fe7b
fix constant expression visit
tserg Nov 13, 2023
e549ce2
fix unary op
tserg Nov 13, 2023
7409e11
fix exception
tserg Nov 13, 2023
a89b14b
revert folding tests
tserg Nov 13, 2023
6d0f714
remove literal bounds validation
tserg Nov 13, 2023
7b38284
validate folded value with typ
tserg Nov 13, 2023
78de745
revert literal validation in folding
tserg Nov 13, 2023
519ec25
fix some tests
tserg Nov 13, 2023
04ccfa6
fix kwarg handler
tserg Nov 13, 2023
c10095b
fix for semantics
tserg Nov 13, 2023
e14da49
fix iteration tests
tserg Nov 13, 2023
9b94fdd
fix lint
tserg Nov 13, 2023
e74d701
update tests
tserg Nov 14, 2023
bbf0510
fix minmax
tserg Nov 14, 2023
6be94e3
fix lint
tserg Nov 14, 2023
0b0c947
fix infer_arg_types sig
tserg Nov 14, 2023
5fa44d7
fix prefold annotation
tserg Nov 14, 2023
0252268
make prefold a wrapper over evaluate
tserg Nov 14, 2023
e46f528
fix abs test
tserg Nov 14, 2023
f96d25f
fix lint
tserg Nov 14, 2023
d961beb
fix typo
tserg Nov 14, 2023
3c37c52
fix interface tests
tserg Nov 14, 2023
23fe402
fix some builtins wip
tserg Nov 14, 2023
dd8cb8f
fix tests
tserg Nov 14, 2023
93c2e31
fix interface repr
tserg Nov 14, 2023
02af165
add annotated ast output
tserg Nov 14, 2023
3b59708
fix compiler phases
tserg Nov 14, 2023
0bfaf2f
add prefold to builtin fn sig
tserg Nov 14, 2023
78bad6c
clean up prefold
tserg Nov 14, 2023
524fb8f
fix lint
tserg Nov 14, 2023
92a33cf
fix mypy lint
tserg Nov 14, 2023
28e202f
fix ast dict test
tserg Nov 14, 2023
07f2026
fix mypy
tserg Nov 14, 2023
092f71b
add tests
tserg Nov 15, 2023
cd5f6cc
fix builtins wip
tserg Nov 15, 2023
b0b39e4
add raw ast output
tserg Nov 15, 2023
55a125e
remove dead code
tserg Nov 15, 2023
c480521
add type propagation for subscript folding
tserg Nov 15, 2023
6de0e81
rename to always_folded_before_codegen
tserg Nov 15, 2023
6a0ca23
introduce constancy
tserg Nov 15, 2023
d13eabb
fix lint
tserg Nov 15, 2023
16b069c
rename to VariableConstancy
tserg Nov 15, 2023
2705f10
fix lint
tserg Nov 15, 2023
5a51de3
use IntEnum
tserg Nov 15, 2023
3078bcc
fix more builtins
tserg Nov 15, 2023
1683fb8
add test
tserg Nov 15, 2023
28b02e7
rename unannotated ast output option
tserg Nov 15, 2023
7b46c4e
fix method id typo
tserg Nov 15, 2023
fc565d6
fix help test
tserg Nov 15, 2023
7a13db2
refactor user defined const folding
tserg Nov 16, 2023
8785e02
add darray test
tserg Nov 16, 2023
926fef6
combine check_kwargable and check_constant
tserg Nov 16, 2023
19b0102
remove folded_before_codegen attribute
tserg Nov 16, 2023
596958a
fix lint
tserg Nov 16, 2023
19f5c7f
fix methodid
tserg Nov 16, 2023
c7585c6
clean up NameConstant
tserg Nov 16, 2023
12ac785
rewrite shift check
tserg Nov 16, 2023
37681b7
clean up builtins
tserg Nov 17, 2023
d82dbc0
add builtins tests
tserg Nov 17, 2023
eda9ba8
fix call args constancy
tserg Nov 17, 2023
2520b90
fix abs test
tserg Nov 17, 2023
3d7d317
improve error msg for as_wei_value
tserg Nov 17, 2023
c77244c
fix folded builtins for constants
tserg Nov 17, 2023
f39effa
fix constant var decl expr visit
tserg Nov 17, 2023
e55eba6
fix lint
tserg Nov 17, 2023
5816107
add unaryop and compare to constancy check
tserg Nov 18, 2023
5620301
add for bound tests
tserg Nov 18, 2023
6a5e00d
clean up index value getter
tserg Nov 18, 2023
6505a94
fix lint
tserg Nov 18, 2023
6af3191
Merge branch 'master' of https://github.com/vyperlang/vyper into refa…
tserg Dec 21, 2023
0f2302b
fix lint
tserg Dec 21, 2023
4256dca
fix tests; relax type propagation in folding builtins
tserg Dec 21, 2023
ce3f61f
rename evaluate to fold
tserg Dec 21, 2023
83a8b66
add immutable enum to modifiability
tserg Dec 22, 2023
59d2a04
add _is_prefoldable attribute to nodes
tserg Dec 22, 2023
be4be41
Merge branch 'master' of https://github.com/vyperlang/vyper into refa…
tserg Dec 24, 2023
7898efe
remove prefold; add get_folded_value and get_folded_value_maybe
tserg Dec 24, 2023
3b6a566
uncatch vy exc in prefold
tserg Dec 24, 2023
51d9344
fix unary fold node type
tserg Dec 24, 2023
64214ec
fix bool test
tserg Dec 24, 2023
1d3de4b
rename get_folded_value to get_folded_value_throwing
tserg Dec 24, 2023
1d8b5be
use maybe for side efx in prefold
tserg Dec 24, 2023
6e3ad8e
replace get with maybe variant
tserg Dec 24, 2023
5bde191
use get_folded_value_throwing for prefold
tserg Dec 24, 2023
4f4576c
Merge branch 'master' of https://github.com/vyperlang/vyper into refa…
tserg Dec 25, 2023
6daf69f
remove is_immutable; rename constancy to modifiability
tserg Dec 25, 2023
ade20fd
use throwing instead of maybe when folding
tserg Dec 26, 2023
b0a295d
fix as wei value test
tserg Dec 26, 2023
6838aa2
fix lint
tserg Dec 26, 2023
bce87d1
use throwing in prefold
tserg Dec 26, 2023
e4fb5d8
remove folding
tserg Dec 26, 2023
7134cc2
Merge branch 'master' of https://github.com/vyperlang/vyper into refa…
tserg Dec 26, 2023
1f9be95
fix minmax folded node
tserg Dec 27, 2023
81d1bfb
improve tests
tserg Dec 27, 2023
3736bf5
use pytest.raises instead of assert_compile_failed
tserg Dec 27, 2023
dd2522d
Merge branch 'refactor/folding_alt2' into refactor/no_folding
tserg Dec 27, 2023
e1e5576
fix kwarg handling
tserg Dec 27, 2023
3a642fb
fix kwargs and constant structs
tserg Dec 27, 2023
27441ec
fix list codegen
tserg Dec 27, 2023
394c9fb
uncatch vyper exception when prefolding call nodes
tserg Dec 27, 2023
17f01fa
handle const, list and tuples
tserg Dec 28, 2023
4df618f
Merge branch 'master' of https://github.com/vyperlang/vyper into refa…
tserg Dec 28, 2023
93a9b42
fix tuple
tserg Dec 28, 2023
14d1e09
read folded value from metadata
tserg Dec 28, 2023
85de1de
Merge branch 'master' of https://github.com/vyperlang/vyper into refa…
tserg Dec 28, 2023
59f7d36
try reverting const amendment
tserg Dec 28, 2023
1f57495
revert; assert struct
tserg Dec 28, 2023
13b341b
clean up expr codegen ctor
tserg Dec 28, 2023
1709d3a
relax module node for exception str
tserg Dec 28, 2023
fe925d6
fix lint
tserg Dec 28, 2023
8ddd2ca
Merge branch 'refactor/no_folding' into refactor/folding_alt2
tserg Dec 28, 2023
5cffa31
remove folded ast output
tserg Dec 28, 2023
aff2fc1
remove folding
tserg Dec 28, 2023
a37fc0e
update READMEs
tserg Dec 28, 2023
bb066c8
remove outdated comment
tserg Dec 28, 2023
20c773d
fix tests
tserg Dec 28, 2023
9ae1344
fix outdated comments
tserg Dec 28, 2023
d6f79e8
replace _kwargable with modifiability for builtins
tserg Dec 28, 2023
3cf993b
remove maybe variant; add is_literal_value and has_folded_value prope…
tserg Dec 29, 2023
9dbc5db
refactor is_literal_value
tserg Dec 29, 2023
4130dbb
minor touch up
tserg Dec 29, 2023
b3d9f20
remove _is_prefoldable
tserg Dec 29, 2023
6d2addc
minor clean up
tserg Dec 29, 2023
6eca837
fix range
tserg Dec 29, 2023
5432063
clean up has_folded_value branches
tserg Dec 29, 2023
87e6469
add expected_return_typ named kwarg
tserg Dec 29, 2023
9beacb2
fix mypy
tserg Dec 29, 2023
31791b2
fix range test
tserg Dec 29, 2023
37e9a28
try simplifying const structs codegen
tserg Dec 29, 2023
1375c03
move validate_literal_nodes into parse_with_settings
charles-cooper Dec 30, 2023
00dadf7
update some comments
charles-cooper Dec 30, 2023
5012cb6
set parent on folded nodes
charles-cooper Dec 30, 2023
2adda25
fix lint
charles-cooper Dec 30, 2023
ead4f3d
remove dead function: Module.replace_in_tree
charles-cooper Dec 30, 2023
ecabcc5
improve a comment
charles-cooper Dec 30, 2023
730fbc6
refactor pre_typecheck
charles-cooper Dec 30, 2023
0e225d5
fix modification of list while iterating over it
charles-cooper Dec 30, 2023
c947593
update calls to `fold()` in tests
charles-cooper Dec 30, 2023
8f29c77
bugfix
charles-cooper Dec 30, 2023
4095ced
remove an isinstance check
charles-cooper Dec 30, 2023
be04b01
fix mypy
charles-cooper Dec 30, 2023
211a233
fix some exception handling
charles-cooper Dec 30, 2023
f862b2b
fix some more bugs
charles-cooper Dec 30, 2023
9a318d5
rollback change moving validate_literal_nodes
charles-cooper Dec 30, 2023
c2ec198
fix lint
charles-cooper Dec 30, 2023
cc15bf3
clarify a comment
charles-cooper Dec 30, 2023
ce8a192
improve vy_ast.Hex API
charles-cooper Dec 30, 2023
1ea47ad
rewrite some error messages
charles-cooper Dec 30, 2023
c87b156
remove "type-checking" _try_folds
charles-cooper Dec 30, 2023
6437230
fix a bug
charles-cooper Dec 30, 2023
5648335
rewrite a ternary op
charles-cooper Dec 30, 2023
94a562e
simplify the modifiability hierarchy
charles-cooper Dec 31, 2023
853f046
fix lint
charles-cooper Dec 31, 2023
d04fb7c
fix transient variables
charles-cooper Dec 31, 2023
c93ece1
some comments
charles-cooper Dec 31, 2023
2f00b29
add another note
charles-cooper Dec 31, 2023
58f25b6
add back in deepcopy of vyper_module
charles-cooper Dec 31, 2023
580bd89
change unannotated_ast/ast to ast/annotated_ast, respectively
charles-cooper Dec 31, 2023
3fb3bc0
fix lint
charles-cooper Dec 31, 2023
8ac8fe6
fix lint, some tests
charles-cooper Dec 31, 2023
4937876
simplify infer_kwarg_types for method_id
charles-cooper Dec 31, 2023
41e0fa3
use pytest.raises instead of assert_compile_failed for a new test
charles-cooper Dec 31, 2023
2303b37
clarify a branch condition
charles-cooper Dec 31, 2023
a31611e
remove a redundant __init__ implementation
charles-cooper Dec 31, 2023
18a1453
lint, fix an error message
charles-cooper Dec 31, 2023
d826be8
improve an error message
charles-cooper Dec 31, 2023
c4757dd
fix: block None nodes at ast level
charles-cooper Dec 31, 2023
f7edbbd
fix lint
charles-cooper Dec 31, 2023
4296250
fix an error message
charles-cooper Dec 31, 2023
1ada8f1
fix some comments, remove a dead function
charles-cooper Dec 31, 2023
c19f04e
fix comment
charles-cooper Dec 31, 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
38 changes: 17 additions & 21 deletions vyper/ast/folding.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from typing import Optional, Union
from typing import Union

from vyper.ast import nodes as vy_ast
from vyper.builtins.functions import DISPATCH_TABLE
from vyper.exceptions import UnfoldableNode, UnknownType
from vyper.exceptions import UnfoldableNode
from vyper.semantics.types.base import VyperType
from vyper.semantics.types.utils import type_from_annotation


def fold(vyper_module: vy_ast.Module) -> None:
Expand Down Expand Up @@ -49,6 +48,12 @@ def replace_literal_ops(vyper_module: vy_ast.Module) -> int:
except UnfoldableNode:
continue

# type may not be available if it is within a type's annotation
# e.g. DynArray[uint256, 2 ** 8]
typ = node._metadata.get("type")
if typ:
new_node._metadata["type"] = node._metadata["type"]

changed_nodes += 1
vyper_module.replace_in_tree(node, new_node)

Expand Down Expand Up @@ -111,6 +116,7 @@ def replace_builtin_functions(vyper_module: vy_ast.Module) -> int:
continue
try:
new_node = func.evaluate(node) # type: ignore
new_node._metadata["type"] = node._metadata["type"]
except UnfoldableNode:
continue

Expand Down Expand Up @@ -146,37 +152,26 @@ def replace_user_defined_constants(vyper_module: vy_ast.Module) -> int:
continue

# Extract type definition from propagated annotation
type_ = None
try:
type_ = type_from_annotation(node.annotation)
except UnknownType:
# handle user-defined types e.g. structs - it's OK to not
# propagate the type annotation here because user-defined
# types can be unambiguously inferred at typechecking time
pass

changed_nodes += replace_constant(
vyper_module, node.target.id, node.value, False, type_=type_
)
type_ = node._metadata["type"]

changed_nodes += replace_constant(vyper_module, node.target.id, node.value, type_, False)

return changed_nodes


# TODO constant folding on log events


def _replace(old_node, new_node, type_=None):
def _replace(old_node, new_node, type_):
if isinstance(new_node, vy_ast.Constant):
new_node = new_node.from_node(old_node, value=new_node.value)
if type_:
new_node._metadata["type"] = type_
new_node._metadata["type"] = type_
return new_node
elif isinstance(new_node, vy_ast.List):
base_type = type_.value_type if type_ else None
list_values = [_replace(old_node, i, type_=base_type) for i in new_node.elements]
new_node = new_node.from_node(old_node, elements=list_values)
if type_:
new_node._metadata["type"] = type_
new_node._metadata["type"] = type_
return new_node
elif isinstance(new_node, vy_ast.Call):
# Replace `Name` node with `Call` node
Expand All @@ -188,6 +183,7 @@ def _replace(old_node, new_node, type_=None):
new_node = new_node.from_node(
old_node, func=new_node.func, args=new_node.args, keyword=keyword, keywords=keywords
)
new_node._metadata["type"] = type_
return new_node
else:
raise UnfoldableNode
Expand All @@ -197,8 +193,8 @@ def replace_constant(
vyper_module: vy_ast.Module,
id_: str,
replacement_node: Union[vy_ast.Constant, vy_ast.List, vy_ast.Call],
type_: VyperType,
raise_on_error: bool,
type_: Optional[VyperType] = None,
) -> int:
"""
Replace references to a variable name with a literal value.
Expand Down
42 changes: 42 additions & 0 deletions vyper/ast/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,14 @@
class UnaryOp(ExprNode):
__slots__ = ("op", "operand")

def prefold(self) -> ExprNode:
Fixed Show fixed Hide fixed
operand = self.operand._metadata.get("folded_value")
if operand is None:
return

value = self.op._op(operand.value)
return type(self.operand).from_node(self, value=value)

def evaluate(self) -> ExprNode:
"""
Attempt to evaluate the unary operation.
Expand Down Expand Up @@ -960,6 +968,22 @@
class BinOp(ExprNode):
__slots__ = ("left", "op", "right")

def prefold(self) -> ExprNode:
Fixed Show fixed Hide fixed
left = self.left._metadata.get("folded_value")
right = self.right._metadata.get("folded_value")

if None in (left, right):
return

# this validation is performed to prevent the compiler from hanging
# on very large shifts and improve the error message for negative
# values.
if isinstance(self.op, (LShift, RShift)) and not (0 <= right.value <= 256):
raise InvalidLiteral("Shift bits must be between 0 and 256", right)

value = self.op._op(left.value, right.value)
return type(left).from_node(self, value=value)

def evaluate(self) -> ExprNode:
"""
Attempt to evaluate the arithmetic operation.
Expand Down Expand Up @@ -1110,6 +1134,14 @@
class BoolOp(ExprNode):
__slots__ = ("op", "values")

def prefold(self) -> ExprNode:
Fixed Show fixed Hide fixed
values = [i._metadata.get("folded_value") for i in self.values]
if None in values:
return

value = self.op._op(values)
return NameConstant.from_node(self, value=value)

def evaluate(self) -> ExprNode:
"""
Attempt to evaluate the boolean operation.
Expand Down Expand Up @@ -1166,6 +1198,16 @@
kwargs["right"] = kwargs.pop("comparators")[0]
super().__init__(*args, **kwargs)

def prefold(self) -> ExprNode:
Fixed Show fixed Hide fixed
left = self.left._metadata.get("folded_value")
right = self.right._metadata.get("folded_value")

if None in (left, right):
return

value = self.op._op(left.value, right.value)
return NameConstant.from_node(self, value=value)

def evaluate(self) -> ExprNode:
"""
Attempt to evaluate the comparison.
Expand Down
12 changes: 8 additions & 4 deletions vyper/builtins/_signatures.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import functools
from typing import Dict

from vyper.ast import nodes as vy_ast

from vyper.ast.validation import validate_call_args
from vyper.codegen.expr import Expr
from vyper.codegen.ir_node import IRnode
from vyper.exceptions import CompilerPanic, TypeMismatch
from vyper.semantics.analysis.utils import get_exact_type_from_node, validate_expected_type
from vyper.semantics.analysis.utils import (
check_kwargable,
get_exact_type_from_node,
validate_expected_type,
)
Fixed Show fixed Hide fixed
from vyper.semantics.types import TYPE_T, KwargSettings, VyperType
from vyper.semantics.types.utils import type_from_annotation

Expand Down Expand Up @@ -97,14 +101,14 @@
# note special meaning for -1 in validate_call_args API
expect_num_args = (num_args, -1)

validate_call_args(node, expect_num_args, self._kwargs)
validate_call_args(node, expect_num_args, self._kwargs.keys())

for arg, (_, expected) in zip(node.args, self._inputs):
self._validate_single(arg, expected)

for kwarg in node.keywords:
kwarg_settings = self._kwargs[kwarg.arg]
if kwarg_settings.require_literal and not isinstance(kwarg.value, vy_ast.Constant):
if kwarg_settings.require_literal and not check_kwargable(kwarg.value):
raise TypeMismatch("Value for kwarg must be a literal", kwarg.value)
self._validate_single(kwarg.value, kwarg_settings.typ)

Expand Down
5 changes: 5 additions & 0 deletions vyper/builtins/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ class FoldedFunction(BuiltinFunction):
# Since foldable builtin functions are not folded before semantics validation,
# this flag is used for `check_kwargable` in semantics validation.
_kwargable = True
# Skip annotation of builtins if it will be folded before codegen
_is_folded_before_codegen = True


class TypenameFoldedFunction(FoldedFunction):
Expand Down Expand Up @@ -2260,6 +2262,9 @@ def build_IR(self, expr, args, kwargs, context):

class Empty(TypenameFoldedFunction):
_id = "empty"
# Since `empty` is not folded in the AST, `is_folded` is set to False
# so that it will be properly annotated.
_is_folded_before_codegen = False

def fetch_call_return(self, node):
type_ = self.infer_arg_types(node)[0].typedef
Expand Down
29 changes: 18 additions & 11 deletions vyper/codegen/function_definitions/external_function.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from vyper import ast as vy_ast
from vyper.codegen.abi_encoder import abi_encoding_matches_vyper
from vyper.codegen.context import Context, VariableRecord
from vyper.codegen.core import get_element_ptr, getpos, make_setter, needs_clamp
Expand Down Expand Up @@ -50,7 +51,7 @@ def _register_function_args(func_t: ContractFunctionT, context: Context) -> list


def _generate_kwarg_handlers(
func_t: ContractFunctionT, context: Context
func_t: ContractFunctionT, context: Context, code: vy_ast.FunctionDef
) -> dict[str, tuple[int, IRnode]]:
# generate kwarg handlers.
# since they might come in thru calldata or be default,
Expand All @@ -62,7 +63,7 @@ def _generate_kwarg_handlers(
# write default args to memory
# goto external_function_common_ir

def handler_for(calldata_kwargs, default_kwargs):
def handler_for(calldata_kwargs, folded_default_kwargs, original_default_kwargs):
calldata_args = func_t.positional_args + calldata_kwargs
# create a fake type so that get_element_ptr works
calldata_args_t = TupleT(list(arg.typ for arg in calldata_args))
Expand All @@ -81,7 +82,7 @@ def handler_for(calldata_kwargs, default_kwargs):
calldata_min_size = args_abi_t.min_size() + 4

# TODO optimize make_setter by using
# TupleT(list(arg.typ for arg in calldata_kwargs + default_kwargs))
# TupleT(list(arg.typ for arg in calldata_kwargs + folded_default_kwargs))
# (must ensure memory area is contiguous)

for i, arg_meta in enumerate(calldata_kwargs):
Expand All @@ -97,15 +98,15 @@ def handler_for(calldata_kwargs, default_kwargs):
copy_arg.source_pos = getpos(arg_meta.ast_source)
ret.append(copy_arg)

for x in default_kwargs:
for x, y in zip(original_default_kwargs, folded_default_kwargs):
dst = context.lookup_var(x.name).pos
lhs = IRnode(dst, location=MEMORY, typ=x.typ)
lhs.source_pos = getpos(x.ast_source)
kw_ast_val = func_t.default_values[x.name] # e.g. `3` in x: int = 3
lhs.source_pos = getpos(y)
kw_ast_val = y
rhs = Expr(kw_ast_val, context).ir_node

copy_arg = make_setter(lhs, rhs)
copy_arg.source_pos = getpos(x.ast_source)
copy_arg.source_pos = getpos(y)
ret.append(copy_arg)

ret.append(["goto", func_t._ir_info.external_function_base_entry_label])
Expand All @@ -116,19 +117,25 @@ def handler_for(calldata_kwargs, default_kwargs):
ret = {}

keyword_args = func_t.keyword_args
folded_keyword_args = code.args.defaults

# allocate variable slots in memory
for arg in keyword_args:
context.new_variable(arg.name, arg.typ, is_mutable=False)

for i, _ in enumerate(keyword_args):
calldata_kwargs = keyword_args[:i]
default_kwargs = keyword_args[i:]
# folded ast
original_default_kwargs = keyword_args[i:]
# unfolded ast
folded_default_kwargs = folded_keyword_args[1:]

sig, calldata_min_size, ir_node = handler_for(calldata_kwargs, default_kwargs)
sig, calldata_min_size, ir_node = handler_for(
calldata_kwargs, folded_default_kwargs, original_default_kwargs
)
ret[sig] = calldata_min_size, ir_node

sig, calldata_min_size, ir_node = handler_for(keyword_args, [])
sig, calldata_min_size, ir_node = handler_for(keyword_args, [], [])

ret[sig] = calldata_min_size, ir_node

Expand All @@ -153,7 +160,7 @@ def generate_ir_for_external_function(code, func_t, context):
handle_base_args = _register_function_args(func_t, context)

# generate handlers for kwargs and register the variable records
kwarg_handlers = _generate_kwarg_handlers(func_t, context)
kwarg_handlers = _generate_kwarg_handlers(func_t, context, code)

body = ["seq"]
# once optional args have been handled,
Expand Down
10 changes: 6 additions & 4 deletions vyper/compiler/phases.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,15 @@ def generate_folded_ast(

vy_ast.validation.validate_literal_nodes(vyper_module)

with input_bundle.search_path(contract_path.parent):
validate_semantics(vyper_module, input_bundle)

symbol_tables = set_data_positions(vyper_module, storage_layout_overrides)

vyper_module_folded = copy.deepcopy(vyper_module)
vy_ast.folding.fold(vyper_module_folded)

with input_bundle.search_path(contract_path.parent):
validate_semantics(vyper_module_folded, input_bundle)

symbol_tables = set_data_positions(vyper_module_folded, storage_layout_overrides)
vy_ast.expansion.remove_unused_statements(vyper_module_folded)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Constant variable declarations can only be removed after folding.


return vyper_module_folded, symbol_tables

Expand Down
4 changes: 3 additions & 1 deletion vyper/semantics/analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from ..namespace import get_namespace
from .local import validate_functions
from .module import add_module_namespace
from .pre_typecheck import pre_typecheck
from .utils import _ExprAnalyser


Expand All @@ -12,6 +13,7 @@ def validate_semantics(vyper_ast, input_bundle):
namespace = get_namespace()

with namespace.enter_scope():
pre_typecheck(vyper_ast)
add_module_namespace(vyper_ast, input_bundle)
vy_ast.expansion.expand_annotated_ast(vyper_ast)
vy_ast.expansion.generate_public_variable_getters(vyper_ast)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Getter functions are added before semantics validation so they can be annotated.

validate_functions(vyper_ast)
Loading
Loading