def test_func_args(): scope = TEST_SCOPE code = """\ struct T: member s : felt member t : felt end func f(x, y : T, z : T*): x = 1; ap++ y.s = 2; ap++ z.t = y.t; ap++ ret end """ program = preprocess_str(code=code, prime=PRIME, main_scope=scope) reference_x = program.instructions[-1].flow_tracking_data.resolve_reference( reference_manager=program.reference_manager, name=scope + 'f.x') assert reference_x.value.format() == 'cast([fp + (-6)], felt)' reference_y = program.instructions[-1].flow_tracking_data.resolve_reference( reference_manager=program.reference_manager, name=scope + 'f.y') assert reference_y.value.format() == f'cast([fp + (-5)], {scope}.T)' reference_z = program.instructions[-1].flow_tracking_data.resolve_reference( reference_manager=program.reference_manager, name=scope + 'f.z') assert reference_z.value.format() == f'cast([fp + (-3)], {scope}.T*)' assert program.format() == """\
def test_references(): program = preprocess_str(code=""" call label1 label1: ret let x = ap + 1 label2: [x] = 1; ap++ [x + 3] = 2; ap++ [x - 2] = 3; ap++ [x - 2] = 3; ap++ jmp label1 if [x] != 0; ap++ jmp label3 if [x] != 0 [x - 2] = 4 [x - 4] = 5 [x - 6] = 6; ap++ [ap] = [ap]; ap++ ap += 4 [x] = 7 call label3 label3: ret let y = ap [y] = 0; ap++ [y] = 0; ap++ """, prime=PRIME) assert program.format() == """\
def test_reference_type_deduction(): scope = TEST_SCOPE program = preprocess_str(code=""" struct T: member t : felt end func foo(): let a = cast(0, T***) tempvar b = [a] tempvar c : felt* = [a] let d = [b] let e : felt* = [b] return () end """, prime=PRIME, main_scope=scope) def get_reference_type(name): identifier_definition = program.identifiers.get_by_full_name(scope + name) assert isinstance(identifier_definition, ReferenceDefinition) assert len(identifier_definition.references) == 1 _, expr_type = simplify_type_system(identifier_definition.references[0].value) return expr_type assert get_reference_type('foo.a').format() == f'{scope}.T***' assert get_reference_type('foo.b').format() == f'{scope}.T**' assert get_reference_type('foo.c').format() == 'felt*' assert get_reference_type('foo.d').format() == f'{scope}.T*' assert get_reference_type('foo.e').format() == 'felt*'
def test_hints_unindent(): before = """\ %{ hint1 hint2 %} [fp] = [fp] func f(): %{ if a: b %} [fp] = [fp] ret end """ after = """\ %{ hint1 hint2 %} [fp] = [fp] %{ if a: b %} [fp] = [fp] ret """ program = preprocess_str(code=before, prime=PRIME) assert program.format() == after
def test_compound_expressions_args(): code = """\ func foo(a, b, c, d) -> (x, y): return (a + b, c * c + d) end tempvar x = 5 foo(x + x, x + x * x, x, 3 * x + x * x) """ program = preprocess_str(code=code, prime=PRIME) expected_result = """\ [ap] = [fp + (-4)] * [fp + (-4)]; ap++ # Compute c * c. [ap] = [fp + (-6)] + [fp + (-5)]; ap++ # Push a + b. [ap] = [ap + (-2)] + [fp + (-3)]; ap++ # Push c * c + d. ret [ap] = 5; ap++ [ap] = [ap + (-1)] * [ap + (-1)]; ap++ # Compute x * x. [ap] = 3; ap++ [ap] = [ap + (-1)] * [ap + (-3)]; ap++ # Compute 3 * x. [ap] = [ap + (-4)] * [ap + (-4)]; ap++ # Compute x * x. [ap] = [ap + (-5)] + [ap + (-5)]; ap++ # Push x + x. [ap] = [ap + (-6)] + [ap + (-5)]; ap++ # Push x + x * x. [ap] = [ap + (-7)]; ap++ # Push x. [ap] = [ap + (-5)] + [ap + (-4)]; ap++ # Push 3 * x + x * x. call rel -15 """ assert program.format() == re.sub(r'\s*#.*\n', '\n', expected_result).replace('\n\n', '\n')
def test_local_variable(): code = """\ struct MyStruct: member a : felt member b : felt end func main(): ap += 5 + SIZEOF_LOCALS local x local y : MyStruct local z = x * y.a x = y.a y.b = z local w : MyStruct* = cast(17, MyStruct*) # Check implicit cast from MyStruct* to felt*. local w_as_felt_ptr : felt* = w z = w.b ret end func no_locals(): ap += SIZEOF_LOCALS ret end """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_unique_label_creator(): program = preprocess_str(code=""" namespace B: func foo(x, y) -> (res): if x == 0: if y == 0: return (res=0) else: return (res=1) end else: if y == 0: return (res=2) else: return (res=3) end end end end func main(): B.foo(1, 2) ret end """, prime=PRIME) assert program.format() == """\
def test_static_assert(): code = """\ static_assert 3 + fp + 10 == 0 + fp + 13 let x = ap ap += 3 static_assert x + 7 == ap + 4 """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_process_file_scope(): # Verify the good scenario. valid_scope = ScopedName.from_string('some.valid.scope') program = preprocess_str('const x = 4', prime=PRIME, main_scope=valid_scope) module = CairoModule(cairo_file=program, module_name=valid_scope) assert program.identifiers.as_dict() == { valid_scope + 'x': ConstDefinition(4) }
def test_n_locals_used_in_static_assert(): code = """\ func main(): static_assert 3 == SIZEOF_LOCALS + 2 local x ret end """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_assign_future_label(): code = """\ [ap] = future_label2 - future_label1; ap++ [ap] = future_label1; ap++ future_label1: [ap] = future_label2; ap++ future_label2: [ap] = 8; ap++ """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_directives(): program = preprocess_str(code="""\ # This is a comment. %builtins ab cd ef [fp] = [fp] """, prime=PRIME) assert program.builtins == ['ab', 'cd', 'ef'] assert program.format() == """\
def test_reference_flow_converge(): program = preprocess_str(""" if [ap] != 0: tempvar a = 1 else: tempvar a = 2 end assert a = a """, prime=PRIME) assert program.format() == """\
def test_hints(): code = """\ %{ hint0 %} [fp] = [fp] %{ hint1 hint2 %} [fp] = [fp] """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == code
def test_tail_call(): code = """\ func f(a) -> (a): return f(a) end func g(a, b) -> (a): return f(a) end """ program = preprocess_str( code=code, prime=PRIME, main_scope=ScopedName.from_string('test_scope')) assert program.format() == """\
def test_func_by_value_return(): code = """\ struct T: member s : felt member t : felt end func f(s : T) -> (x : T, y : T): let t : T = cast([ap - 100], T) return(x=s, y=t) end """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_compound_expressions_tempvars(): code = """\ tempvar x = [ap - 1] * [ap - 1] + [ap - 1] * [ap - 2] tempvar y = x + x """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\ [ap] = [ap + (-1)] * [ap + (-1)]; ap++ [ap] = [ap + (-2)] * [ap + (-3)]; ap++ [ap] = [ap + (-2)] + [ap + (-1)]; ap++ [ap] = [ap + (-1)] + [ap + (-1)]; ap++ """.replace('\n\n', '\n')
def test_implcit_argument_bindings(): code = """\ func f{x, y}(): ret end func g{x, y, z}(): f{y=z}() return () end """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_local_rebinding(): code = """\ func main(): alloc_locals local x = 5 local x = x * x local x = x + x local x = x * x ret end """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_function_call_by_value_args(): code = """\ struct T: member s : felt member t : felt end func f(x, y : T, z : T): let t : T = cast([ap], T) let res = f(x=2, y=z, z=t) return() end """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_reference_flow_revokes(valid, has0, has1, has2): def0 = 'let ref = [fp]' if has0 else '' def1 = 'let ref = [fp + 1]' if has1 else '' def2 = 'let ref = [fp + 2]' if has2 else '' code = f""" {def0} jmp b if [ap] != 0 a: {def1} jmp c b: {def2} c: [ref] = [fp + 3] """ if valid: preprocess_str(code, prime=PRIME) else: verify_exception(code, """ file:?:?: Reference 'ref' was revoked. [ref] = [fp + 3] ^*^ """)
def test_with_statement(): code = """ let x = 1000 [ap] = 0 with x: [ap] = 1 [ap] = 2 [ap] = x let x = 1001 end [ap] = x """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_temporary_variable(): code = """\ struct T: member pad0 : felt member t : felt end tempvar x = [ap - 1] + [fp - 3] ap += 3 tempvar y : T* = cast(x, T*) ap += 4 [fp] = y.t """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_compound_expressions(): code = """\ assert [ap] = [ap + 1] * [ap + 2] assert 5 = [[ap - 1]] assert [[ap - 1]] = 5 assert [ap - 2] = [[ap - 1] - 5] assert [ap - 2] = [[ap - 1] + 999999] assert [[ap + 5 + 5]] = [ap - 1] assert [ap - 1] = [[[ap + 5 + 5]]] assert [[ap - 1]] = [[ap - 2]] tempvar __fp__ = 100 assert [fp] = fp + [fp + [fp]] let __fp__ = [ap - 1] + [ap - 1] assert [fp] = fp + fp """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\ [ap] = [ap + 1] * [ap + 2] [ap] = [[ap + (-1)]]; ap++ 5 = [ap + (-1)] [ap] = 5; ap++ [[ap + (-2)]] = [ap + (-1)] [ap + (-2)] = [[ap + (-1)] + (-5)] [ap] = [ap + (-1)] + 999999; ap++ [ap + (-3)] = [[ap + (-1)]] [[ap + 10]] = [ap + (-1)] [ap] = [[ap + 10]]; ap++ [ap + (-2)] = [[ap + (-1)]] [ap] = [[ap + (-2)]]; ap++ [[ap + (-2)]] = [ap + (-1)] [ap] = 100; ap++ [ap] = [ap + (-1)] + [fp]; ap++ [ap] = [[ap + (-1)]]; ap++ [fp] = [ap + (-3)] + [ap + (-1)] [ap] = [ap + (-1)] + [ap + (-1)]; ap++ [ap] = [ap + (-2)] + [ap + (-2)]; ap++ [fp] = [ap + (-2)] + [ap + (-1)] """.replace('\n\n', '\n')
def test_scope_const(): code = """\ const x = 5 [ap] = x; ap++ func f(): const x = 1234 [ap + 1] = x; ap++ [ap + 2] = f.x; ap++ ret end [ap + 3] = x; ap++ [ap + 4] = f.x; ap++ """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_func_args_scope(): code = """\ const x = 1234 [ap] = x; ap++ func f(x, y, z): x = 1; ap++ y = 2; ap++ z = 3; ap++ ret end [ap + 4] = x; ap++ [ap + 5] = f.Args.z; ap++ """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_func_named_args(): code = """\ func f(x, y, z): ret end let f_args = cast(ap, f.Args*) f_args.z = 2; ap++ f_args.x = 0; ap++ f_args.y = 1; ap++ static_assert f_args + f.Args.SIZE == ap call f """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_rebind_reference(): program = preprocess_str(code=""" struct T: member pad0 : felt member pad1 : felt member t : felt end let x : T* = cast(ap + 1, T*) let y = &x.t [cast(x, felt)] = x.t let x : T* = cast(fp - 3, T*) [cast(x, felt)] = x.t [y] = [y] """, prime=PRIME) assert program.format() == """\
def test_function_call(): code = """\ func foo(a, b) -> (c): bar(a=a) return (1) end func bar(a): return () end foo(2, 3) foo(2, b=3) let res = foo(a=2, b=3) res.c = 1 """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\
def test_func_args_and_rets_scope(): code = """\ const x = 1234 [ap] = x; ap++ func f(x, y, z) -> (a, b, x): x = 1; ap++ y = 2; ap++ [ap] = Return.b; ap++ ret end [ap + 4] = x; ap++ [ap + 5] = f.Args.x; ap++ [ap + 6] = f.Return.x; ap++ """ program = preprocess_str(code=code, prime=PRIME) assert program.format() == """\