Пример #1
0
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
Пример #2
0
def test_labels():
    scope = ScopedName.from_string('my.cool.scope')
    program = preprocess_str("""
const x = 7
a0:
[ap] = x; ap++  # Size: 2.
[ap] = [fp] + 123  # Size: 2.

a1:
[ap] = [fp]  # Size: 1.
jmp rel [fp]  # Size: 1.
a2:
jmp rel x  # Size: 2.
jmp a3  # Size: 2.
jmp a3 if [ap] != 0  # Size: 2.
call a3  # Size: 2.
a3:
""",
                             prime=PRIME,
                             main_scope=scope)
    program_labels = {
        name: identifier_definition.pc
        for name, identifier_definition in program.identifiers.get_scope(
            scope).identifiers.items()
        if isinstance(identifier_definition, LabelDefinition)
    }
    assert program_labels == {'a0': 0, 'a1': 4, 'a2': 6, 'a3': 14}
Пример #3
0
def test_reference_type_deduction():
    program = preprocess_str(code="""
struct T:
    const SIZE = 0
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)

    def get_reference_type(name):
        identifier_definition = program.identifiers.get_by_full_name(
            ScopedName.from_string(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() == 'T***'
    assert get_reference_type('foo.b').format() == 'T**'
    assert get_reference_type('foo.c').format() == 'felt*'
    assert get_reference_type('foo.d').format() == 'T*'
    assert get_reference_type('foo.e').format() == 'felt*'
Пример #4
0
def test_local_variable():
    code = """\
struct Mystruct:
    member a = 0
    member b = 1
    const SIZE = 2
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* = 17
    z = w.b
    ret
end

func no_locals():
    ap += SIZEOF_LOCALS
    ret
end
"""
    program = preprocess_str(code=code, prime=PRIME)
    assert program.format() == """\
Пример #5
0
def test_func_args():
    code = """\
struct T:
    member s = 0
    member t = 1
    const SIZE = 2
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)
    reference_x = program.instructions[
        -1].flow_tracking_data.resolve_reference(
            reference_manager=program.reference_manager,
            name=ScopedName.from_string('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=ScopedName.from_string('f.y'))
    assert reference_y.value.format() == 'cast([fp + (-5)], T)'
    reference_z = program.instructions[
        -1].flow_tracking_data.resolve_reference(
            reference_manager=program.reference_manager,
            name=ScopedName.from_string('f.z'))
    assert reference_z.value.format() == 'cast([fp + (-3)], T*)'
    assert program.format() == """\
Пример #6
0
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')
Пример #7
0
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() == """\
Пример #8
0
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() == """\
Пример #9
0
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)
    }
Пример #10
0
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() == """\
Пример #11
0
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() == """\
Пример #12
0
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() == """\
Пример #13
0
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() == """\
Пример #14
0
def test_hints():
    code = """\
%{ hint0 %}
[fp] = [fp]
%{
    hint1
    hint2
%}
[fp] = [fp]
"""
    program = preprocess_str(code=code, prime=PRIME)
    assert program.format() == code
Пример #15
0
def test_function_call():
    code = """\
func foo(a, b) -> (c):
    return (1)
end
foo(2, 3)
foo(2, b=3)
let res = foo(..., b=3)
res.c = 1
"""
    program = preprocess_str(code=code, prime=PRIME)
    assert program.format() == """\
Пример #16
0
def test_temporary_variable():
    code = """\
struct T:
    member t = 100
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() == """\
Пример #17
0
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() == """\
Пример #18
0
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')
Пример #19
0
def test_return():
    code = """\
func f() -> (a, b, c):
    return (1, [fp], c=[fp + 1] + 2)
    return (..., c=3)
    return (...)
end
func g():
  return ()
end
"""
    program = preprocess_str(code=code, prime=PRIME)
    assert program.format() == """\
Пример #20
0
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]
 ^*^
""")
Пример #21
0
def test_func_by_value_return():
    code = """\
struct T:
    member s = 0
    member t = 1
    const SIZE = 2
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() == """\
Пример #22
0
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')
Пример #23
0
def test_function_call_by_value_args():
    code = """\
struct T:
    member s = 0
    member t = 1
    const SIZE = 2
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() == """\
Пример #24
0
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() == """\
Пример #25
0
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() == """\
Пример #26
0
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() == """\
Пример #27
0
def test_rebind_reference():
    program = preprocess_str(code="""
struct T:
    member t = 100
end
struct S:
    member s = 1000
end
let x : T* = cast(ap + 1, T*)
let y = &x.t
[cast(x, felt)] = x.t
let x : S* = cast(fp - 3, S*)
[cast(x, felt)] = x.s
[y] = [y]
""", prime=PRIME)
    assert program.format() == """\
Пример #28
0
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() == """\
Пример #29
0
def test_label_resolution():
    program = preprocess_str(code="""
[ap] = 7; ap++  # Size: 2.

loop:
[ap] = [ap - 1] + 1  # Size: 2.
jmp future_label  # Size: 2.
jmp future_label if [ap] != 0  # Size: 2.
call future_label  # Size: 2.
[fp] = [fp]  # Size: 1.
future_label:
jmp loop   # Size: 2.
jmp loop if [ap] != 0  # Size: 2.
call loop  # Size 2.
""", prime=PRIME)
    assert program.format() == """\
Пример #30
0
def test_compiler():
    program = preprocess_str(code="""

const x = 5
const y = 2 * x
[ap] = [[fp + 2 * 3] + ((7 - 1 + y))]; ap++
ap += 4 + %[ 2**10 %]

# An empty line with a comment.
[ap] = [fp] # This is a comment.
let z = ap - 3
[ap] = [ap - x]
jmp rel 2 - 3
ret
label:
jmp label if [fp + 3 + 1] != 0
""", prime=PRIME)
    assert program.format() == """\