From b1efc29a2b719ef4812dff660f3c4732922c72bc Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 19 Feb 2019 13:21:01 -0700 Subject: [PATCH 1/8] Fix valency error in if-statements --- vyper/compile_lll.py | 3 +++ vyper/parser/lll_node.py | 6 +----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/vyper/compile_lll.py b/vyper/compile_lll.py index 8a66730561..0ed18b4cd6 100644 --- a/vyper/compile_lll.py +++ b/vyper/compile_lll.py @@ -119,6 +119,7 @@ def compile_to_assembly(code, withargs=None, existing_labels=None, break_dest=No end_symbol = mksymbol() o.extend(['ISZERO', end_symbol, 'JUMPI']) o.extend(compile_to_assembly(code.args[1], withargs, existing_labels, break_dest, height)) + o.extend(['POP'] * code.args[1].valency) o.extend([end_symbol, 'JUMPDEST']) return o # If statements (3 arguments, ie. if x: y, else: z) @@ -129,8 +130,10 @@ def compile_to_assembly(code, withargs=None, existing_labels=None, break_dest=No end_symbol = mksymbol() o.extend(['ISZERO', mid_symbol, 'JUMPI']) o.extend(compile_to_assembly(code.args[1], withargs, existing_labels, break_dest, height)) + o.extend(['POP'] * code.args[1].valency) o.extend([end_symbol, 'JUMP', mid_symbol, 'JUMPDEST']) o.extend(compile_to_assembly(code.args[2], withargs, existing_labels, break_dest, height)) + o.extend(['POP'] * code.args[2].valency) o.extend([end_symbol, 'JUMPDEST']) return o # Repeat statements (compiled from for loops) diff --git a/vyper/parser/lll_node.py b/vyper/parser/lll_node.py index bf96d6308e..4c24845d38 100644 --- a/vyper/parser/lll_node.py +++ b/vyper/parser/lll_node.py @@ -107,17 +107,13 @@ def __init__(self, value, args=None, typ=None, location=None, pos=None, annotati elif self.value == 'if': if len(self.args) == 3: self.gas = self.args[0].gas + max(self.args[1].gas, self.args[2].gas) + 3 - if self.args[1].valency != self.args[2].valency: - raise Exception("Valency mismatch between then and else clause: %r %r" % (self.args[1], self.args[2])) if len(self.args) == 2: self.gas = self.args[0].gas + self.args[1].gas + 17 - if self.args[1].valency: - raise Exception("2-clause if statement must have a zerovalent body: %r" % self.args[1]) if not self.args[0].valency: raise Exception("Can't have a zerovalent argument as a test to an if statement! %r" % self.args[0]) if len(self.args) not in (2, 3): raise Exception("If can only have 2 or 3 arguments") - self.valency = self.args[1].valency + self.valency = 0 # With statements: with elif self.value == 'with': if len(self.args) != 3: From 6a4b90745165b93ff25c2a6967259616826350dc Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 19 Feb 2019 14:09:15 -0700 Subject: [PATCH 2/8] Use seq instead of manual pops --- vyper/compile_lll.py | 3 --- vyper/parser/stmt.py | 6 ++++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/vyper/compile_lll.py b/vyper/compile_lll.py index 0ed18b4cd6..8a66730561 100644 --- a/vyper/compile_lll.py +++ b/vyper/compile_lll.py @@ -119,7 +119,6 @@ def compile_to_assembly(code, withargs=None, existing_labels=None, break_dest=No end_symbol = mksymbol() o.extend(['ISZERO', end_symbol, 'JUMPI']) o.extend(compile_to_assembly(code.args[1], withargs, existing_labels, break_dest, height)) - o.extend(['POP'] * code.args[1].valency) o.extend([end_symbol, 'JUMPDEST']) return o # If statements (3 arguments, ie. if x: y, else: z) @@ -130,10 +129,8 @@ def compile_to_assembly(code, withargs=None, existing_labels=None, break_dest=No end_symbol = mksymbol() o.extend(['ISZERO', mid_symbol, 'JUMPI']) o.extend(compile_to_assembly(code.args[1], withargs, existing_labels, break_dest, height)) - o.extend(['POP'] * code.args[1].valency) o.extend([end_symbol, 'JUMP', mid_symbol, 'JUMPDEST']) o.extend(compile_to_assembly(code.args[2], withargs, existing_labels, break_dest, height)) - o.extend(['POP'] * code.args[2].valency) o.extend([end_symbol, 'JUMPDEST']) return o # Repeat statements (compiled from for loops) diff --git a/vyper/parser/stmt.py b/vyper/parser/stmt.py index fefcc3d294..166d4a0394 100644 --- a/vyper/parser/stmt.py +++ b/vyper/parser/stmt.py @@ -240,7 +240,7 @@ def parse_if(self): if self.stmt.orelse: block_scope_id = id(self.stmt.orelse) self.context.start_blockscope(block_scope_id) - add_on = [parse_body(self.stmt.orelse, self.context)] + add_on = [['seq', parse_body(self.stmt.orelse, self.context)]] self.context.end_blockscope(block_scope_id) else: add_on = [] @@ -251,8 +251,10 @@ def parse_if(self): if not self.is_bool_expr(test_expr): raise TypeMismatchException('Only boolean expressions allowed', self.stmt.test) + body = ['if', test_expr, + parse_body(self.stmt.body, self.context)] + add_on o = LLLnode.from_list( - ['if', test_expr, parse_body(self.stmt.body, self.context)] + add_on, + body, typ=None, pos=getpos(self.stmt) ) self.context.end_blockscope(block_scope_id) From 7b811cd2cc31c985a117e07eb73dd16de278217b Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 19 Feb 2019 14:13:03 -0700 Subject: [PATCH 3/8] Add a missing seq --- vyper/parser/stmt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vyper/parser/stmt.py b/vyper/parser/stmt.py index 166d4a0394..f9d20b9f43 100644 --- a/vyper/parser/stmt.py +++ b/vyper/parser/stmt.py @@ -252,7 +252,8 @@ def parse_if(self): raise TypeMismatchException('Only boolean expressions allowed', self.stmt.test) body = ['if', test_expr, - parse_body(self.stmt.body, self.context)] + add_on + ['seq', parse_body(self.stmt.body, self.context)]] \ + + add_on o = LLLnode.from_list( body, typ=None, pos=getpos(self.stmt) From 8cde6038ada1351c9f3cabea4e78ec09f0f7f155 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 19 Feb 2019 14:45:18 -0700 Subject: [PATCH 4/8] Fix valency calculation --- vyper/parser/lll_node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vyper/parser/lll_node.py b/vyper/parser/lll_node.py index 4c24845d38..cd989f0568 100644 --- a/vyper/parser/lll_node.py +++ b/vyper/parser/lll_node.py @@ -113,7 +113,7 @@ def __init__(self, value, args=None, typ=None, location=None, pos=None, annotati raise Exception("Can't have a zerovalent argument as a test to an if statement! %r" % self.args[0]) if len(self.args) not in (2, 3): raise Exception("If can only have 2 or 3 arguments") - self.valency = 0 + self.valency = self.args[1].valency # With statements: with elif self.value == 'with': if len(self.args) != 3: From 4f69f5333e3ccfcccec6aeec31314765d56213fb Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Thu, 21 Feb 2019 12:21:22 -0800 Subject: [PATCH 5/8] Add tests for valency branches --- tests/parser/syntax/test_conditionals.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/parser/syntax/test_conditionals.py diff --git a/tests/parser/syntax/test_conditionals.py b/tests/parser/syntax/test_conditionals.py new file mode 100644 index 0000000000..8f6e1ca9f8 --- /dev/null +++ b/tests/parser/syntax/test_conditionals.py @@ -0,0 +1,22 @@ +def test_conditional_return_code(get_contract_with_gas_estimation): + conditional_return_code = """ +@private +def mkint() -> int128: + return 1 + +@public +def test_zerovalent(): + if True: + self.mkint() + +@public +def test_valency_mismatch(): + if True: + self.mkint() + else: + pass + """ + + c = get_contract_with_gas_estimation(conditional_return_code) + + print('Passed conditional return tests') From 3cab52791e1cd3f95dd76126acb0ba46582b6cb9 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 22 Feb 2019 12:59:30 -0800 Subject: [PATCH 6/8] Fix lint --- tests/parser/syntax/test_conditionals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/parser/syntax/test_conditionals.py b/tests/parser/syntax/test_conditionals.py index 8f6e1ca9f8..3e625de5ca 100644 --- a/tests/parser/syntax/test_conditionals.py +++ b/tests/parser/syntax/test_conditionals.py @@ -17,6 +17,6 @@ def test_valency_mismatch(): pass """ - c = get_contract_with_gas_estimation(conditional_return_code) + get_contract_with_gas_estimation(conditional_return_code) print('Passed conditional return tests') From c1e5d8d526d2c23f6d57a760766dc7eeeead4289 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Sun, 24 Feb 2019 09:25:43 -0800 Subject: [PATCH 7/8] Compile a different way in tests --- tests/parser/syntax/test_conditionals.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/parser/syntax/test_conditionals.py b/tests/parser/syntax/test_conditionals.py index 3e625de5ca..4e808fa240 100644 --- a/tests/parser/syntax/test_conditionals.py +++ b/tests/parser/syntax/test_conditionals.py @@ -1,5 +1,8 @@ -def test_conditional_return_code(get_contract_with_gas_estimation): - conditional_return_code = """ +import pytest +from vyper import compiler + +valid_list = [ + """ @private def mkint() -> int128: return 1 @@ -16,7 +19,10 @@ def test_valency_mismatch(): else: pass """ +] + +@pytest.mark.parametrize('good_code', valid_list) +def test_conditional_return_code(good_code): + assert compiler.compile_code(good_code) is not None - get_contract_with_gas_estimation(conditional_return_code) - print('Passed conditional return tests') From 09661c261b10378a5099dee2ed888774d1bbae20 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Feb 2019 09:12:19 -0800 Subject: [PATCH 8/8] Fix lint --- tests/parser/syntax/test_conditionals.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/parser/syntax/test_conditionals.py b/tests/parser/syntax/test_conditionals.py index 4e808fa240..10b5172a15 100644 --- a/tests/parser/syntax/test_conditionals.py +++ b/tests/parser/syntax/test_conditionals.py @@ -21,8 +21,7 @@ def test_valency_mismatch(): """ ] + @pytest.mark.parametrize('good_code', valid_list) def test_conditional_return_code(good_code): assert compiler.compile_code(good_code) is not None - -