Skip to content

Commit

Permalink
Merge pull request #457 from daejunpark/fix-issue-453
Browse files Browse the repository at this point in the history
fix issue #453
  • Loading branch information
DavidKnott committed Nov 15, 2017
2 parents 974c62e + 52a040f commit 0b9062b
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 6 deletions.
2 changes: 1 addition & 1 deletion docs/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ A signed integer (128 bit) is a type to store positive and negative integers.

Values
------
Signed integer values between -2\ :sup:`127` and (2\ :sup:`127` - 1).
Signed integer values between -2\ :sup:`127` and (2\ :sup:`127` - 1), inclusive.

Operators
---------
Expand Down
2 changes: 1 addition & 1 deletion tests/parser/exceptions/test_invalid_literal_exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def foo():
""",
"""
def foo():
x = -170141183460469231731687303715884105728
x = -170141183460469231731687303715884105729 # -2**127 - 1
""",
"""
def foo():
Expand Down
54 changes: 53 additions & 1 deletion tests/parser/types/numbers/test_num.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from tests.setup_transaction_tests import chain as s, tester as t, ethereum_utils as u, check_gas, \
get_contract_with_gas_estimation, get_contract
get_contract_with_gas_estimation, get_contract, assert_tx_failed

def test_exponents_with_nums():
exp_code = """
Expand All @@ -16,3 +16,55 @@ def _num_exp(x: num, y: num) -> num:
assert c._num_exp(3,3) == 27
assert c._num_exp(72,19) == 72**19

def test_nagative_nums(assert_tx_failed):
negative_nums_code = """
def _negative_num() -> num:
return -1
def _negative_exp() -> num:
return -(1+2)
"""

c = get_contract(negative_nums_code)
t.s = s
assert c._negative_num() == -1
assert c._negative_exp() == -3

def test_num_bound(assert_tx_failed):
num_bound_code = """
def _num(x: num) -> num:
return x
def _num_add(x: num, y: num) -> num:
return x + y
def _num_sub(x: num, y: num) -> num:
return x - y
def _num_add3(x: num, y: num, z: num) -> num:
return x + y + z
def _num_max() -> num:
return 170141183460469231731687303715884105727 # 2**127 - 1
def _num_min() -> num:
return -170141183460469231731687303715884105728 # -2**127
"""

c = get_contract(num_bound_code)

t.s = s
NUM_MAX = 2**127 - 1
NUM_MIN = -2**127
assert c._num_add(NUM_MAX, 0) == NUM_MAX
assert c._num_sub(NUM_MIN, 0) == NUM_MIN
assert c._num_add(NUM_MAX - 1, 1) == NUM_MAX
assert c._num_sub(NUM_MIN + 1, 1) == NUM_MIN
assert_tx_failed(lambda: c._num_add(NUM_MAX, 1))
assert_tx_failed(lambda: c._num_sub(NUM_MIN, 1))
assert_tx_failed(lambda: c._num_add(NUM_MAX - 1, 2))
assert_tx_failed(lambda: c._num_sub(NUM_MIN + 1, 2))
assert c._num_max() == NUM_MAX
assert c._num_min() == NUM_MIN

assert_tx_failed(lambda: c._num_add3(NUM_MAX, 1, -1))
assert c._num_add3(NUM_MAX, -1, 1) == NUM_MAX
2 changes: 0 additions & 2 deletions viper/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,6 @@ def as_num256(expr, args, kwargs, context):
raise InvalidLiteralException("Number out of range: " + str(expr.args[0].n), expr.args[0])
return LLLnode.from_list(args[0], typ=BaseType('num256', None), pos=getpos(expr))
elif isinstance(args[0], LLLnode):
if args[0].value == "sub" and args[0].args[0].value == 0 and args[0].args[1].value > 0:
raise InvalidLiteralException("Negative numbers cannot be num256 literals")
return LLLnode(value=args[0].value, args=args[0].args, typ=BaseType('num256'), pos=getpos(expr))
else:
raise InvalidLiteralException("Invalid input for num256: %r" % args[0], expr)
Expand Down
3 changes: 2 additions & 1 deletion viper/parser/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
)
from viper.utils import (
MemoryPositions,
SizeLimits,
bytes_to_int,
string_to_bytes,
DECIMAL_DIVISOR,
Expand Down Expand Up @@ -78,7 +79,7 @@ def get_expr(self):
def number(self):
orignum = get_original_if_0x_prefixed(self.expr, self.context)
if orignum is None and isinstance(self.expr.n, int):
if not (-2**127 + 1 <= self.expr.n <= 2**127 - 1):
if not (SizeLimits.MINNUM <= self.expr.n <= SizeLimits.MAXNUM):
raise InvalidLiteralException("Number out of range: " + str(self.expr.n), self.expr)
return LLLnode.from_list(self.expr.n, typ=BaseType('num', None), pos=getpos(self.expr))
elif isinstance(self.expr.n, float):
Expand Down
15 changes: 15 additions & 0 deletions viper/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@
def parse(code):
o = ast.parse(code)
decorate_ast_with_source(o, code)
o = resolve_negative_literals(o)
return o.body


# Parser for a single line
def parse_line(code):
o = ast.parse(code).body[0]
decorate_ast_with_source(o, code)
o = resolve_negative_literals(o)
return o


Expand All @@ -82,6 +84,19 @@ def visit(self, node):
MyVisitor().visit(_ast)


def resolve_negative_literals(_ast):

class RewriteUnaryOp(ast.NodeTransformer):
def visit_UnaryOp(self, node):
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Num):
node.operand.n = 0 - node.operand.n
return node.operand
else:
return node

return RewriteUnaryOp().visit(_ast)


# Make a getter for a variable. This function gives an output that
# contains lists of 4-tuples:
# (i) the tail of the function name for the getter
Expand Down

0 comments on commit 0b9062b

Please sign in to comment.