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

Added types to iterator variables #1054

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
12 changes: 12 additions & 0 deletions tests/parser/syntax/test_for_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ def foo():
x: int128 = 5
for i in range(x, x + 10):
pass
""",
"""
@public
def foo():
for i in range(10, type=int128):
pass
""",
"""
@public
def foo():
for i in range(10, 20, type=uint256):
pass
"""
]

Expand Down
24 changes: 20 additions & 4 deletions vyper/parser/stmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
get_size_of_type,
is_base_type,
parse_type,
canonicalize_type,
NodeType
)
from vyper.types import (
Expand Down Expand Up @@ -277,16 +278,31 @@ def parse_for(self):

block_scope_id = id(self.stmt.orelse)
self.context.start_blockscope(block_scope_id)

# type defaults to int128
typ_str = 'int128'
# goes through all keywords in iterator variable
# this loop can be used if new keyword arguments are added too
if len(self.stmt.iter.keywords) > 0:
for keyword in self.stmt.iter.keywords:
# set type equal to the value of the type keyword
if keyword.arg == 'type':
typ_str = keyword.value.id

# handle invalid types
# this function raises an error for unsupported types
typ = canonicalize_type(BaseType(typ_str))

# Type 1 for, e.g. for i in range(10): ...
if len(self.stmt.iter.args) == 1:
if not isinstance(self.stmt.iter.args[0], ast.Num):
raise StructureException("Range only accepts literal values", self.stmt.iter)
start = LLLnode.from_list(0, typ='int128', pos=getpos(self.stmt))
start = LLLnode.from_list(0, typ=typ, pos=getpos(self.stmt))
rounds = self.stmt.iter.args[0].n
elif isinstance(self.stmt.iter.args[0], ast.Num) and isinstance(self.stmt.iter.args[1], ast.Num):
# Type 2 for, e.g. for i in range(100, 110): ...
start = LLLnode.from_list(self.stmt.iter.args[0].n, typ='int128', pos=getpos(self.stmt))
rounds = LLLnode.from_list(self.stmt.iter.args[1].n - self.stmt.iter.args[0].n, typ='int128', pos=getpos(self.stmt))
start = LLLnode.from_list(self.stmt.iter.args[0].n, typ=typ, pos=getpos(self.stmt))
rounds = LLLnode.from_list(self.stmt.iter.args[1].n - self.stmt.iter.args[0].n, typ=typ, pos=getpos(self.stmt))
else:
# Type 3 for, e.g. for i in range(x, x + 10): ...
if not isinstance(self.stmt.iter.args[1], ast.BinOp) or not isinstance(self.stmt.iter.args[1].op, ast.Add):
Expand All @@ -299,7 +315,7 @@ def parse_for(self):
start = Expr.parse_value_expr(self.stmt.iter.args[0], self.context)
rounds = self.stmt.iter.args[1].right.n
varname = self.stmt.target.id
pos = self.context.new_variable(varname, BaseType('int128'))
pos = self.context.new_variable(varname, BaseType(typ))
self.context.forvars[varname] = True
o = LLLnode.from_list(['repeat', pos, start, rounds, parse_body(self.stmt.body, self.context)], typ=None, pos=getpos(self.stmt))
del self.context.vars[varname]
Expand Down