Skip to content

Commit

Permalink
update codegen and semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
tserg committed Jul 4, 2022
1 parent 94f5883 commit 5e3fbfe
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 6 deletions.
20 changes: 18 additions & 2 deletions vyper/builtin_functions/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
vyper_warn,
)

from .signatures import BuiltinFunction, process_inputs
from .signatures import BuiltinFunction, process_inputs, process_kwarg

SHA256_ADDRESS = 2
SHA256_BASE_GAS = 60
Expand Down Expand Up @@ -2488,11 +2488,27 @@ def build_IR(self, expr, context):
class Pop(BuiltinFunction):
_id = "pop"

def _get_kwarg_settings(self, expr):
call_type = get_exact_type_from_node(expr.func)
expected_kwargs = call_type.kwargs
return expected_kwargs

def build_IR(self, expr, context, return_popped_item):
darray = Expr(expr.func.value, context).ir_node
assert isinstance(darray.typ, DArrayType)
assert len(expr.args) == 0
return pop_dyn_array(darray, return_popped_item=return_popped_item)

kwargs = self._get_kwarg_settings(expr)

if expr.keywords:
assert len(expr.keywords) == 1 and expr.keywords[0].arg == "ix"
kwarg_settings = kwargs[expr.keywords[0].arg]
expected_kwarg_type = kwarg_settings.typ
idx = process_kwarg(expr.keywords[0].value, kwarg_settings, expected_kwarg_type, context)
return pop_dyn_array(darray, return_popped_item=return_popped_item, pop_idx=idx)

else:
return pop_dyn_array(darray, return_popped_item=return_popped_item)


DISPATCH_TABLE = {
Expand Down
13 changes: 10 additions & 3 deletions vyper/codegen/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,20 +290,27 @@ def append_dyn_array(darray_node, elem_node):
return IRnode.from_list(b1.resolve(b2.resolve(ret)))


def pop_dyn_array(darray_node, return_popped_item):
def pop_dyn_array(darray_node, return_popped_item, pop_idx=None):
assert isinstance(darray_node.typ, DArrayType)
assert darray_node.encoding == Encoding.VYPER
ret = ["seq"]
with darray_node.cache_when_complex("darray") as (b1, darray_node):
old_len = clamp("gt", get_dyn_array_count(darray_node), 0)
new_len = IRnode.from_list(["sub", old_len, 1], typ="uint256")

with new_len.cache_when_complex("new_len") as (b2, new_len):
if pop_idx is not None:
# Pop from given index
idx = clamp("gt", get_dyn_array_count(darray_node), pop_idx)
else:
# Else, pop from last index
idx = new_len

with idx.cache_when_complex("idx") as (b2, idx):
ret.append(STORE(darray_node, new_len))

# NOTE skip array bounds check bc we already asserted len two lines up
if return_popped_item:
popped_item = get_element_ptr(darray_node, new_len, array_bounds_check=False)
popped_item = get_element_ptr(darray_node, idx, array_bounds_check=False)
ret.append(popped_item)
typ = popped_item.typ
location = popped_item.location
Expand Down
2 changes: 2 additions & 0 deletions vyper/semantics/types/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,8 @@ def fetch_call_return(self, node: vy_ast.Call) -> Optional[BaseTypeDefinition]:
self._validate_arg_types(node)
return self.return_type

def infer_kwarg_types(self, node: vy_ast.Call) -> Optional[Dict[str, BaseTypeDefinition]]:
return {i.arg: self.kwargs[i.arg].typ for i in node.keywords}

def _generate_method_id(name: str, canonical_abi_types: List[str]) -> Dict[str, int]:
function_sig = f"{name}({','.join(canonical_abi_types)})"
Expand Down
2 changes: 1 addition & 1 deletion vyper/semantics/types/indexable/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def __init__(
[],
self.value_type,
True,
kwargs={"ix": KwargSettings(Uint256Definition(), -1, require_literal=True)},
kwargs={"ix": KwargSettings(Uint256Definition(), -1)},
),
)

Expand Down
3 changes: 3 additions & 0 deletions vyper/semantics/validation/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ def visit_Call(self, node, type_):
assert len(node.args) == len(call_type.arg_types)
for arg, arg_type in zip(node.args, call_type.arg_types):
self.visit(arg, arg_type)
kwarg_types = call_type.infer_kwarg_types(node)
for kwarg in node.keywords:
self.visit(kwarg.value, kwarg_types[kwarg.arg])
else:
# builtin functions
arg_types = call_type.infer_arg_types(node)
Expand Down

0 comments on commit 5e3fbfe

Please sign in to comment.