Skip to content

Commit

Permalink
fix folded builtins for constants
Browse files Browse the repository at this point in the history
  • Loading branch information
tserg committed Nov 17, 2023
1 parent 3d7d317 commit c77244c
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 11 deletions.
18 changes: 18 additions & 0 deletions tests/functional/syntax/test_as_wei_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ def foo():
""",
InvalidLiteral,
),
(
"""
FOO: constant(uint256) = as_wei_value(5, szabo)
""",
ArgumentException,
),
(
"""
FOO: constant(uint256) = as_wei_value(5, "szaboo")
""",
ArgumentException,
),
(
"""
FOO: constant(uint256) = as_wei_value(-1, "szabo")
""",
InvalidLiteral,
),
]


Expand Down
14 changes: 14 additions & 0 deletions tests/functional/syntax/test_epsilon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest

from vyper.exceptions import InvalidType

fail_list = [
"""
FOO: constant(address) = epsilon(address)
"""
]


@pytest.mark.parametrize("bad_code", fail_list)
def test_block_fail(assert_compile_failed, get_contract_with_gas_estimation, bad_code):
assert_compile_failed(lambda: get_contract_with_gas_estimation(bad_code), InvalidType)
16 changes: 14 additions & 2 deletions tests/functional/syntax/test_method_id.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest

from vyper import compiler
from vyper.exceptions import InvalidLiteral
from vyper.exceptions import InvalidLiteral, InvalidType

fail_list = [
(
Expand All @@ -11,7 +11,19 @@ def foo():
a: Bytes[4] = method_id("bar ()")
""",
InvalidLiteral,
)
),
(
"""
FOO: constant(Bytes[4]) = method_id(1)
""",
InvalidType,
),
(
"""
FOO: constant(Bytes[4]) = method_id("bar ()")
""",
InvalidLiteral,
),
]


Expand Down
3 changes: 3 additions & 0 deletions tests/functional/syntax/test_minmax_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ def foo():
def foo():
a: address = max_value(address)
""",
"""
FOO: constant(address) = min_value(address)
""",
]


Expand Down
26 changes: 18 additions & 8 deletions vyper/builtins/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,11 @@ def fetch_call_return(self, node):
type_ = self.infer_kwarg_types(node)["output_type"].typedef
return type_

def infer_arg_types(self, node, expected_return_typ=None):
# call `evaluate` for its typechecking side effects
self.evaluate(node)
return [self._inputs[0][1]]

def infer_kwarg_types(self, node):
# If `output_type` is not given, default to `Bytes[4]`
output_typedef = TYPE_T(BytesT(4))
Expand Down Expand Up @@ -977,16 +982,12 @@ class AsWeiValue(BuiltinFunction):
("kether", "grand"): 10**21,
}

def _get_denomination_node(self, node):
def get_denomination(self, node):
value = node.args[1]._metadata.get("folded_value")
if not isinstance(value, vy_ast.Str):
raise ArgumentException(
"Wei denomination must be given as a literal string", node.args[1]
)
return value

def get_denomination(self, node):
value = self._get_denomination_node(node)
try:
denom = next(v for k, v in self.wei_denoms.items() if value.value in k)
except StopIteration:
Expand All @@ -1013,9 +1014,12 @@ def fetch_call_return(self, node):
return self._return_type

def infer_arg_types(self, node, expected_return_typ=None):
# raise a better error message by first calling this function
# for its side effects of checking the denom
self._get_denomination_node(node)
# call `evaluate` for its typechecking side effects`
try:
self.evaluate(node)
except UnfoldableNode:
pass

self._validate_arg_types(node)
# return a concrete type instead of abstract type
value_type = get_possible_types_from_node(node.args[0]).pop()
Expand Down Expand Up @@ -2585,6 +2589,12 @@ def evaluate(self, node):
ret._metadata["type"] = input_type
return ret

def infer_arg_types(self, node, expected_return_typ=None):
# call `evaluate` for its typechecking side effects
self.evaluate(node)
input_typedef = TYPE_T(type_from_annotation(node.args[0]))
return [input_typedef]


class MinValue(_MinMaxValue):
_id = "min_value"
Expand Down
2 changes: 1 addition & 1 deletion vyper/semantics/analysis/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,13 @@ def _validate_self_namespace():
raise exc.with_annotation(node) from None

if node.is_constant:
ExprVisitor().visit(node.value, type_)
if not node.value:
raise VariableDeclarationException("Constant must be declared with a value", node)
if not check_variable_constancy(node.value, VariableConstancy.COMPILE_TIME_CONSTANT):
raise StateAccessViolation("Value must be a literal", node.value)

validate_expected_type(node.value, type_)
ExprVisitor().visit(node.value, type_)
_validate_self_namespace()

return _finalize()
Expand Down

0 comments on commit c77244c

Please sign in to comment.