예제 #1
0
def test_scope_failures():
    verify_exception("""
func f():
const x = 5
ret
end
func g():
[ap] = x; ap++
ret
end
""", """
file:?:?: Unknown identifier 'x'.
[ap] = x; ap++
       ^
""")
    verify_exception("""
func f():
label:
ret
end
func g():
call label
ret
end
""", """
file:?:?: Unknown identifier 'label'.
call label
     ^***^
""")
예제 #2
0
def test_func_args_failures():
    verify_exception("""
func f(x):
    [ap] = [x] + 1
end
""",
                     """
file:?:?: While expanding the reference 'x' in:
    [ap] = [x] + 1
            ^
file:?:?: Expected a register. Found: [fp + (-3)].
func f(x):
       ^
Preprocessed instruction:
[ap] = [[fp + (-3)]] + 1
""",
                     exc_type=InstructionBuilderError)
    verify_exception(
        """
func f(x):
    g(x=x)
end
func g(x):
    ret
end
""", """
file:?:?: The called function must be defined before the call site.
    g(x=x)
    ^****^
""")
예제 #3
0
def test_error_scope_redefinition():
    verify_exception("""
from a import b
from a.b import c
""", """
Scope 'a.b' collides with a different identifier of type 'const'.
""", files={'a': 'const b = 0', 'a.b': 'const c = 1'})
예제 #4
0
def test_func_by_value_args_failures(test_line, expected_type, actual_type,
                                     arrow):
    verify_exception(
        f"""
struct T:
    member s = 0
    member t = 1
    const SIZE = 2
end
struct S:
    member s = 0
    member t = 1
    const SIZE = 2
end
func f(x, y : {expected_type}):
    local t : {actual_type}
    alloc_locals
    {test_line}
    ret
end
""", f"""
file:?:?: Expected expression of type '{expected_type}', got '{actual_type}'.
    {test_line}
           {arrow}
""")
예제 #5
0
def test_tempvar_modifier_failures():
    verify_exception(
        """
func main():
    tempvar local x = 5
end
""", """
file:?:?: Unexpected modifier 'local'.
    tempvar local x = 5
            ^***^
""")

    verify_exception("""
tempvar x = [ap - 1] + [fp - 3]
[x] = [[ap]]
""",
                     """
file:?:?: While expanding the reference 'x' in:
[x] = [[ap]]
 ^
file:?:?: Expected a register. Found: [ap + (-1)].
tempvar x = [ap - 1] + [fp - 3]
        ^
Preprocessed instruction:
[[ap + (-1)]] = [[ap]]
""",
                     exc_type=InstructionBuilderError)
예제 #6
0
def test_hints_failures():
    verify_exception("""
%{
hint
%}
""", """
file:?:?: Found a hint at the end of a code block. Hints must be followed by an instruction.
%{
^^
""")
    verify_exception("""
func f():
%{
hint
%}
end
[ap] = 1
""", """
file:?:?: Found a hint at the end of a code block. Hints must be followed by an instruction.
%{
^^
""")
    verify_exception("""
%{
hint1
%}
%{
hint2
%}
""", """
file:?:?: Only one hint is allowed per instruction.
%{
^^
""")
    verify_exception("""
[fp] = [fp]
%{
hint
%}
label:
[fp] = [fp]
""", """
file:?:?: Hints before labels are not allowed.
%{
^^
""")
    verify_exception("""
[fp] = [fp]
%{
hint
%}
const x = 5
[fp] = [fp]
""", """
file:?:?: Hints before constant definitions are not allowed.
%{
^^
""")
예제 #7
0
def test_builtins_failures():
    verify_exception("""
%builtins a
%builtins b
""", """
file:?:?: Redefinition of builtins directive.
%builtins b
^*********^
""")
예제 #8
0
def test_directives_failures():
    verify_exception("""
[fp] = [fp]
%builtins ab cd ef
""", """
file:?:?: Directives must appear at the top of the file.
%builtins ab cd ef
^****************^
""")
예제 #9
0
def test_import_errors():
    # Inaccessible import.
    verify_exception("""
from foo import bar
""",
                     """
file:?:?: Could not load module 'foo'.
Error: 'foo'
from foo import bar
     ^*^
""",
                     files={},
                     exc_type=LocationError)

    # Ignoring aliasing.
    verify_exception("""
from foo import bar as notbar
[ap] = bar
""",
                     """
file:?:?: Unknown identifier 'bar'.
[ap] = bar
       ^*^
""",
                     files={'foo': 'const bar = 3'})

    # Identifier redefinition.
    verify_exception("""
const bar = 0
from foo import bar
""",
                     """
file:?:?: Redefinition of 'bar'.
from foo import bar
                ^*^
""",
                     files={'foo': 'const bar=0'})

    verify_exception("""
const lambda = 0
from foo import bar as lambda
""",
                     """
file:?:?: Redefinition of 'lambda'.
from foo import bar as lambda
                       ^****^
""",
                     files={'foo': 'const bar=0'})

    verify_exception('from foo import bar',
                     """ \
file:?:?: Scope 'foo' does not include identifier 'bar'.
from foo import bar
                ^*^
""",
                     files={'foo': ''})
예제 #10
0
def test_ellipsis_failures():
    # Ellipsis in a wrong place.
    verify_exception(
        """
func f() -> (a, b, c):
    return (1, ...)
end
""", """
file:?:?: Ellipsis ("...") can only be used at the beginning of the list.
    return (1, ...)
               ^*^
""")
    # Wrong place, with ellipsis.
    verify_exception(
        """
func f() -> (a, b, c):
    return (..., a=1, c=[fp] + 1)
end
""", """
file:?:?: Expected named arg 'b' found 'a'.
    return (..., a=1, c=[fp] + 1)
                 ^
""")
    # Missing arg, with ellipsis.
    verify_exception(
        """
func f() -> (a, b, c):
    return (..., a=1, b=[fp] + 1)
end
""", """
file:?:?: Expected named arg 'b' found 'a'.
    return (..., a=1, b=[fp] + 1)
                 ^
""")
    # Wrong place, without ellipsis.
    verify_exception(
        """
func f() -> (a, b, c):
    return (a=1, c=[fp] + 1, b=0)
end
""", """
file:?:?: Expected named arg 'b' found 'c'.
    return (a=1, c=[fp] + 1, b=0)
                 ^
""")
    # Compound expressions with ellipsis.
    verify_exception(
        """
func f(x, y) -> (a, b, c, d, e):
    return (..., c=x + y, d=(x + y) * 2, e=x * y)
end
""", """
file:?:?: Compound expressions cannot be used with an ellipsis ("...").
    return (..., c=x + y, d=(x + y) * 2, e=x * y)
                            ^*********^
""")
예제 #11
0
def test_member_def_failure():
    verify_exception("""
struct T:
    member t = ap + 5
end
""", """
file:?:?: Expected a constant expression.
    member t = ap + 5
               ^****^
""")
예제 #12
0
def test_rebind_reference_failures():
    verify_exception("""
let x = cast(ap, felt*)
let x = cast(ap, felt**)
""", """
file:?:?: Reference rebinding must preserve the reference type. Previous type: 'felt*', \
new type: 'felt**'.
let x = cast(ap, felt**)
    ^
""")
예제 #13
0
def test_bad_struct():
    verify_exception("""
struct T:
    return()
end
""", """
file:?:?: Unexpected statement inside a struct definition.
    return()
    ^******^
""")
def test_redefinition_failures():
    verify_exception(
        """
name:
local name = [ap]
""", """
file:?:?: Redefinition of 'test_scope.name'.
local name = [ap]
      ^**^
""")
예제 #15
0
def test_member_def_modifier_failure():
    verify_exception("""
struct T:
    member local t = 17
end
""", """
file:?:?: Unexpected modifier 'local'.
    member local t = 17
           ^***^
""")
예제 #16
0
def test_references_revoked(revoking_instruction):
    verify_exception(f"""
label:
let x = ap
{revoking_instruction}
[x] = 0
""", """
file:?:?: Reference 'x' was revoked.
[x] = 0
 ^
""")
def test_local_variable_modifier_failures():
    verify_exception(
        """
func main():
    local local x
end
""", """
file:?:?: Unexpected modifier 'local'.
    local local x
          ^***^
""")
예제 #18
0
def test_unpacking_modifier_failure():
    verify_exception("""
func foo() -> (a, b):
  ret
end
let (a, local b) = foo()
""", """
file:?:?: Unexpected modifier 'local'.
let (a, local b) = foo()
        ^***^
""")
예제 #19
0
def test_temporary_variable_failures():
    verify_exception("""
struct T:
    member t = 100
end
tempvar x : T = 0
""", """
file:?:?: tempvar type annotation must be 'felt' or a pointer.
tempvar x : T = 0
            ^
""")
def test_local_variable_failures():
    verify_exception(
        """
func main(SIZEOF_LOCALS):
    static_assert SIZEOF_LOCALS == SIZEOF_LOCALS
    local x
end
""", """
file:?:?: The name 'SIZEOF_LOCALS' is reserved and cannot be used as an argument name.
func main(SIZEOF_LOCALS):
          ^***********^
""")
    verify_exception(
        """
func main():
    local x
end
""", """
file:?:?: A function with local variables must use alloc_locals.
    local x
    ^*****^
""")
    verify_exception(
        """
func main():
    alloc_locals
    local x = x + x
end
""", """
file:?:?: Identifier 'x' referenced before definition.
    local x = x + x
              ^
""")
    for inst in ['tempvar a = 0', 'ret', 'ap += [ap]']:
        verify_exception(
            f"""
func main():
    {inst}
    alloc_locals
end
""", """
file:?:?: alloc_locals must be used before any instruction that changes the ap register.
    alloc_locals
    ^**********^
""")
    verify_exception(
        f"""
alloc_locals
""", """
file:?:?: alloc_locals cannot be used outside of a function.
alloc_locals
^**********^
""")
예제 #21
0
def test_func_failures(last_statement):
    verify_exception(f"""
func f(x):
    body:
    ret
    {last_statement}
end
""", """
file:?:?: Function must end with a return instruction or a jump.
func f(x):
     ^
""")
예제 #22
0
def test_compound_expressions_failures():
    verify_exception(
        """\
assert [ap + [ap]] = [ap]
""", """
file:?:?: ap may only be used in an expression of the form [ap + <const>].
assert [ap + [ap]] = [ap]
        ^^
""")
    verify_exception(
        """\
assert [[ap]] = ap
""", """
file:?:?: ap may only be used in an expression of the form [ap + <const>].
assert [[ap]] = ap
                ^^
""")
    verify_exception(
        """\
assert [[fp]] = fp
""", """
file:?:?: Using the value of fp directly, requires defining a variable named __fp__.
assert [[fp]] = fp
                ^^
""")
    verify_exception(
        """\
assert [ap] = [ap + 32768]  # Offset is out of bounds.
""", """
file:?:?: ap may only be used in an expression of the form [ap + <const>].
assert [ap] = [ap + 32768]  # Offset is out of bounds.
               ^^
""")
예제 #23
0
def test_return_failures():
    # Named after positional.
    verify_exception("""
func f() -> (a, b, c):
    return (a=1, b=1, [fp] + 1)
end
""", """
file:?:?: Positional arguments must not appear after named arguments.
    return (a=1, b=1, [fp] + 1)
                      ^******^
""")
    # Wrong num.
    verify_exception("""
func f() -> (a, b, c, d):
    return (1, [fp] + 1)
end
""", """
file:?:?: Expected exactly 4 expressions, got 2.
    return (1, [fp] + 1)
    ^******************^
""")
    # Wrong num.
    verify_exception("""
func f() -> (a, b):
    return ()
end
""", """
file:?:?: Expected exactly 2 expressions, got 0.
    return ()
    ^*******^
""")
    # Unknown name.
    verify_exception("""
func f() -> (a, b, c):
    return (a=1, d=1, [fp] + 1)
end
""", """
file:?:?: Expected named arg 'b' found 'd'.
    return (a=1, d=1, [fp] + 1)
                 ^
""")
    # Not in func.
    verify_exception("""
return (a=1, [fp] + 1)
""", """
file:?:?: return cannot be used outside of a function.
return (a=1, [fp] + 1)
^********************^
""")
예제 #24
0
def test_redefinition_failures():
    verify_exception(
        """
name:
const name = 0
""", """
file:?:?: Redefinition of 'name'.
const name = 0
      ^**^
""")
    verify_exception(
        """
const name = 0
let name = ap
""", """
file:?:?: Redefinition of 'name'.
let name = ap
    ^**^
""")
    verify_exception("""
let name = ap
name:
""", """
file:?:?: Redefinition of 'name'.
name:
^**^
""")
    verify_exception(
        """
func f(name, x, name):
    [ap + name] = 1
    [ap + x] = 2
end
""", """
file:?:?: Redefinition of 'f.Args.name'.
func f(name, x, name):
                ^**^
""")
    verify_exception(
        """
func f() -> (name, x, name):
    [ap + name] = 1
    [ap + x] = 2
end
""", """
file:?:?: Redefinition of 'f.Return.name'.
func f() -> (name, x, name):
                      ^**^
""")
예제 #25
0
def test_func_args_failures():
    verify_exception("""
func f(x):
    [ap] = [x] + 1
end
""", """
file:?:?: While expanding the reference 'x' in:
    [ap] = [x] + 1
            ^
file:?:?: Expected a register. Found: [fp + (-3)].
func f(x):
       ^
Preprocessed instruction:
[ap] = [[fp + (-3)]] + 1
""", exc_type=InstructionBuilderError)
예제 #26
0
def test_func_by_value_discontinuous_struct_failures():
    verify_exception("""
struct T:
    member s = 0
    member t = 2
    const SIZE = 3
end
func f(x, y : T):
    f(1, y=y)
    ret
end
""", """
file:?:?: Discontinuous structs are not supported.
    f(1, y=y)
           ^
""")
예제 #27
0
def test_func_named_args_failures():
    verify_exception("""
func f(x, y, z):
    ret
end

let f_args = cast(ap, f.Args*)
f_args.z = 2; ap++
f_args.x = 0; ap++
static_assert f_args + f.Args.SIZE == ap
call f
""", """
file:?:?: Static assert failed: ap + 1 != ap.
static_assert f_args + f.Args.SIZE == ap
^**************************************^
""")
예제 #28
0
def test_nested_function_failure():
    verify_exception("""
func foo():
    func bar():
        return()
    end
    return()
end
""", """
file:?:?: Nested functions are not supported.
    func bar():
         ^*^
Outer function was defined here: file:?:?
func foo():
     ^*^
""")
예제 #29
0
def test_labels_failures():
    verify_exception("""
jmp x.y.z
""", """
file:?:?: Unknown identifier 'x'.
jmp x.y.z
    ^***^
""")
    verify_exception("""
const x = 0
jmp x
""", """
file:?:?: Expected a label name. Identifier 'x' is of type const.
jmp x
    ^
""")
예제 #30
0
def test_namespace_inside_function_failure():
    verify_exception("""
func foo():
    namespace MyNamespace:
    end
    return()
end


""", """
file:?:?: Cannot define a namespace inside a function.
    namespace MyNamespace:
              ^*********^
Outer function was defined here: file:?:?
func foo():
     ^*^
""")