예제 #1
0
def function_definitions_in_statement_lists_can_be_defined_out_of_order():
    f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(nodes.ref("g"), []))
    ])
    g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[])
    
    _updated_bindings(nodes.module([f, g]))
예제 #2
0
def attributes_assigned_in_init_can_be_used_in_methods_when_init_method_is_defined_after_other_method():
    init_func = nodes.func(
        name="__init__",
        args=nodes.args([nodes.arg("self_init")]),
        body=[
            nodes.assign(
                [nodes.attr(nodes.ref("self_init"), "message")],
                nodes.str_literal("Hello"),
                type=nodes.ref("str"),
            )
        ],
        type=nodes.signature(
            args=[nodes.signature_arg(nodes.ref("Self"))],
            returns=nodes.ref("none")
        ),
    )
    node = nodes.class_("User", [
        nodes.func(
            name="g",
            args=nodes.args([nodes.arg("self_g")]),
            body=[nodes.ret(nodes.attr(nodes.ref("self_g"), "message"))],
            type=nodes.signature(
                args=[nodes.signature_arg(nodes.ref("Self"))],
                returns=nodes.ref("str")
            ),
        ),
        init_func,
    ])
    _infer_class_type(node, ["__init__", "g"], [(init_func, ["self_init"])])
예제 #3
0
def init_method_cannot_call_other_methods():
    node = nodes.class_("User", [
        nodes.func(
            name="__init__",
            args=nodes.args([nodes.arg("self_init")]),
            body=[
                nodes.assign([nodes.ref("x")], nodes.call(nodes.attr(nodes.ref("self_init"), "g"), []))
            ],
            type=nodes.signature(
                args=[nodes.signature_arg(nodes.ref("Self"))],
                returns=nodes.ref("none")
            ),
        ),
        nodes.func(
            name="g",
            args=nodes.args([nodes.arg("self_g")]),
            body=[],
            type=nodes.signature(
                args=[nodes.signature_arg(nodes.ref("Self"))],
                returns=nodes.ref("none")
            ),
        ),
    ])
    try:
        _infer_class_type(node, ["__init__", "g"])
        assert False, "Expected error"
    except errors.InitMethodCannotGetSelfAttributes as error:
        assert_equal("__init__ methods cannot get attributes of self", str(error))
예제 #4
0
def method_can_call_method_on_same_instance_defined_later_in_body():
    node = nodes.class_("User", [
        nodes.func(
            name="f",
            args=nodes.args([nodes.arg("self_f")]),
            body=[
                nodes.ret(nodes.call(nodes.attr(nodes.ref("self_f"), "g"), []))
            ],
            type=nodes.signature(
                args=[nodes.signature_arg(nodes.ref("Self"))],
                returns=nodes.ref("none")
            ),
        ),
        nodes.func(
            name="g",
            args=nodes.args([nodes.arg("self_g")]),
            body=[
                nodes.ret(nodes.call(nodes.attr(nodes.ref("self_g"), "f"), []))
            ],
            type=nodes.signature(
                args=[nodes.signature_arg(nodes.ref("Self"))],
                returns=nodes.ref("none")
            ),
        )
    ])
    _infer_class_type(node, ["f", "g"])
예제 #5
0
def function_definitions_in_statement_lists_can_be_mutually_recursive():
    f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(nodes.ref("g"), []))
    ])
    g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(nodes.ref("f"), []))
    ])
    _update_context([f, g])
예제 #6
0
def function_definitions_can_be_mutually_recursive():
    f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(nodes.ref("g"), []))
    ])
    g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(nodes.ref("f"), []))
    ])
    
    _updated_bindings(nodes.module([f, g]))
예제 #7
0
def method_can_reference_later_function_if_class_is_not_used_in_the_interim():
    g_ref = nodes.ref("g")
    f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(g_ref, []))
    ])
    g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[])
    
    _updated_bindings(nodes.module([
        nodes.class_("a", [f]),
        g,
    ]))
예제 #8
0
def names_in_function_are_not_declared_in_outer_scope():
    node = nodes.func("f", nodes.arguments([]), [
        nodes.assign([nodes.ref("x")], nodes.none())
    ], type=None)
    
    declarations = find_declarations(node)
    assert not declarations.is_declared("x")
예제 #9
0
def exception_handler_targets_cannot_be_accessed_from_nested_function():
    target_node = nodes.ref("error")
    ref_node = nodes.ref("error")
    body = [nodes.ret(ref_node)]
    func_node = nodes.func("f", nodes.arguments([]), body, type=None)
    try_node = nodes.try_(
        [],
        handlers=[
            nodes.except_(nodes.none(), target_node, [func_node])
        ],
    )
    
    declaration = name_declaration.ExceptionHandlerTargetNode("error")
    references = References([
        (target_node, declaration),
        (ref_node, declaration),
        (func_node, name_declaration.VariableDeclarationNode("f")),
    ])
    
    try:
        _updated_bindings(try_node, references=references)
        assert False, "Expected error"
    except errors.UnboundLocalError as error:
        assert_equal(ref_node, error.node)
        assert_is("error", error.name)
예제 #10
0
def class_cannot_be_referenced_if_method_dependencies_are_not_bound():
    g_ref = nodes.ref("g")
    f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(g_ref, []))
    ])
    g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[])
    
    try:
        _updated_bindings(nodes.module([
            nodes.class_("a", [f]),
            nodes.expression_statement(nodes.ref("a")),
            g,
        ]))
        assert False, "Expected error"
    except errors.UnboundLocalError as error:
        assert_equal(g_ref, error.node)
예제 #11
0
def can_infer_type_of_function_with_explicit_signature_of_aliased_function_type():
    args = nodes.arguments([])
    node = nodes.func("f", args=args, body=[], type=nodes.ref("Action"))
    type_bindings = {
        "Action": types.meta_type(types.func([], types.none_type))
    }
    assert_equal(types.func([], types.none_type), _infer_func_type(node, type_bindings))
예제 #12
0
def attributes_assigned_in_init_can_be_used_outside_of_class():
    init_func = nodes.func(
        name="__init__",
        args=nodes.args([nodes.arg("self_init")]),
        body=[
            nodes.assign(
                [nodes.attr(nodes.ref("self_init"), "message")],
                nodes.str_literal("Hello"),
                type=nodes.ref("str"),
            )
        ],
        type=nodes.signature(
            args=[nodes.signature_arg(nodes.ref("Self"))],
            returns=nodes.ref("none")
        )
    )
    class_node = nodes.class_("User", [init_func])
    
    node = [
        class_node,
        nodes.assign([nodes.ref("x")], nodes.attr(nodes.call(nodes.ref("User"), []), "message")),
    ]
    
    context = _update_context(node, declared_names_in_node=NodeDict([
        (class_node, ["Self", "__init__"]),
        (init_func, ["self_init"]),
    ]))
    
    assert_equal(types.str_type, context.lookup_name("x"))
예제 #13
0
def function_cannot_be_referenced_before_definition_of_dependencies():
    g_ref = nodes.ref("g")
    f = nodes.func("f", type=None, args=nodes.Arguments([]), body=[
        nodes.ret(nodes.call(g_ref, []))
    ])
    g = nodes.func("g", type=None, args=nodes.Arguments([]), body=[])
    
    try:
        _updated_bindings(nodes.module([
            f,
            nodes.expression_statement(nodes.ref("f")),
            g,
        ]))
        assert False, "Expected error"
    except errors.UnboundLocalError as error:
        assert_equal(g_ref, error.node)
예제 #14
0
def declarations_in_function_include_declarations_in_body():
    node = nodes.func("f", nodes.arguments([]), [
        nodes.assign([nodes.ref("x")], nodes.none())
    ], type=None)
    
    declarations = _declarations_in(node)
    assert isinstance(declarations.declaration("x"), name_declaration.VariableDeclarationNode)
    assert not declarations.is_declared("f")
예제 #15
0
def break_is_not_valid_in_function_in_while_loop_body():
    break_node = nodes.break_()
    func_node = nodes.func("f", nodes.args([]), [break_node], type=None)
    node = nodes.while_(nodes.bool_literal(True), [func_node], [])
    error = assert_raises(errors.TypeCheckError,
        lambda: check_loop_control(node, False))
    assert_equal(break_node, error.node)
    assert_equal("'break' outside loop", str(error))
예제 #16
0
def function_definitions_in_statement_lists_are_type_checked_even_if_not_invoked():
    node = nodes.func("f", type=None, args=nodes.Arguments([]), body=[nodes.ret(nodes.int_literal(42))])
    try:
        _update_context([node])
        assert False, "Expected error"
    except errors.UnexpectedValueTypeError as error:
        assert_equal(types.int_type, error.actual)
        assert_equal(types.none_type, error.expected)
예제 #17
0
def type_parameters_of_function_are_definitely_bound():
    param = nodes.formal_type_parameter("T")
    arg_ref = nodes.ref("T")
    returns_ref = nodes.ref("T")
    explicit_type = nodes.signature(type_params=[param], args=[nodes.signature_arg(arg_ref)], returns=returns_ref)
    func_node = nodes.func("f", nodes.arguments([]), [], type=explicit_type)
    
    _updated_bindings(func_node)
예제 #18
0
 def test_function_definitions_in_body_are_stored_as_methods(self):
     _assert_transform(
         nodes.class_("Blah", [nodes.func("f", nodes.args([]), [], type=None)]),
         cc.class_(
             "Blah",
             methods=[cc.func("f", [], [cc.ret(cc.none)])],
             body=[cc.declare("f")],
         ),
     )
예제 #19
0
def _create_class_with_init(signature, args, body):
    return nodes.class_("User", [
        nodes.func(
            name="__init__",
            args=args,
            body=body,
            type=signature
        )
    ])
예제 #20
0
def function_adds_arguments_to_context():
    signature = nodes.signature(
        args=[nodes.signature_arg(nodes.ref("int"))],
        returns=nodes.ref("int")
    )
    args = nodes.arguments([nodes.argument("x")])
    body = [nodes.ret(nodes.ref("x"))]
    node = nodes.func("f", args, body, type=signature)
    assert_equal(types.func([types.int_type], types.int_type), _infer_func_type(node))
예제 #21
0
def function_can_have_no_signature_if_it_takes_no_args():
    source = """
def f():
    pass
"""
    
    module_node = parser.parse(source)
    expected = nodes.func("f", nodes.args([]), [], type=None)
    assert_equal(expected, module_node.body[0])
예제 #22
0
def error_if_type_signature_is_missing_from_function_with_args():
    args = nodes.arguments([nodes.argument("x")])
    body = [nodes.ret(nodes.ref("x"))]
    node = nodes.func("f", args, body, type=None)
    try:
        _infer_func_type(node)
        assert False, "Expected error"
    except errors.ArgumentsError as error:
        assert_equal("signature is missing from function definition", str(error))
예제 #23
0
def type_mismatch_if_return_type_is_incorrect():
    return_node = nodes.ret(nodes.str_literal("!"))
    node = nodes.func(
        "f",
        args=nodes.arguments([]),
        body=[return_node],
        type=nodes.signature(returns=nodes.ref("int")),
    )
    assert_type_mismatch(lambda: _infer_func_type(node), expected=types.int_type, actual=types.str_type, node=return_node)
예제 #24
0
def values_can_have_same_name_as_child_module_if_they_are_not_in_module_scope():
    value_node = nodes.assign([nodes.ref("x")], nodes.int_literal(1))
    node = nodes.module([
        nodes.func("f", nodes.args([]), [value_node], type=None)
    ], is_executable=False)
    
    _check_module(LocalModule("root/__init__.py", node), {
        (".", "x"): module({}),
    })
예제 #25
0
def function_definitions_assignments_shadow_variables_of_same_name_in_outer_scope():
    args = nodes.arguments([])
    ref = nodes.ref("x")
    body = [nodes.assign([ref], nodes.none())]
    node = nodes.func("f", args, body, type=None)
    
    declarations = _create_declarations(["x", "f"])
    
    references = resolve(node, declarations)
    assert_is_not(declarations.declaration("x"), references.referenced_declaration(ref))
예제 #26
0
def function_definitions_bodies_can_access_variables_from_outer_scope():
    args = nodes.arguments([])
    ref = nodes.ref("x")
    body = [nodes.ret(ref)]
    node = nodes.func("f", args, body, type=None)
    
    declarations = _create_declarations(["x", "f"])
    
    references = resolve(node, declarations)
    assert_is(declarations.declaration("x"), references.referenced_declaration(ref))
예제 #27
0
def can_infer_type_of_function_with_no_args_and_return_annotation():
    node = nodes.func(
        "f",
        args=nodes.arguments([]),
        body=[
            nodes.ret(nodes.int_literal(4))
        ],
        type=nodes.signature(returns=nodes.ref("int")),
    )
    assert_equal(types.func([], types.int_type), _infer_func_type(node))
예제 #28
0
def cannot_declare_name_with_two_different_declaration_types():
    try:
        declarations = _declarations_in(nodes.module([
            nodes.assign([nodes.ref("f")], nodes.none()),
            nodes.func("f", nodes.arguments([]), [], type=None)
        ]))
        declarations = find_declarations(node)
        assert False, "Expected error"
    except errors.InvalidReassignmentError as error:
        assert_equal("function declaration and variable assignment cannot share the same name", str(error))
예제 #29
0
def names_in_function_signature_are_not_declared_in_outer_scope():
    explicit_type = nodes.signature(
        type_params=[nodes.formal_type_parameter("T")],
        args=[],
        returns=nodes.ref("T"),
    )
    node = nodes.func("f", nodes.arguments([]), [], type=explicit_type)
    
    declarations = find_declarations(node)
    assert not declarations.is_declared("T")
예제 #30
0
def class_definition_functions_ignore_class_scope_when_resolving_references():
    ref = nodes.ref("x")
    node = nodes.class_("User", [
        nodes.assign([nodes.ref("x")], nodes.none()),
        nodes.func("f", nodes.args([]), [nodes.ret(ref)], type=None),
    ])
    
    declarations = _create_declarations(["x", "User"])
    
    references = resolve(node, declarations)
    assert_is(declarations.declaration("x"), references.referenced_declaration(ref))