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")
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))
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)
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)
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")
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))
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))
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)
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))
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))
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")
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))
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))
def function_definitions_adds_argument_names_to_body_context(): arg = nodes.argument("x") args = nodes.arguments([arg]) ref = nodes.ref("x") body = [nodes.ret(ref)] node = nodes.func("f", args, body, type=None) declarations = _create_declarations(["f"]) references = resolve(node, declarations) assert not declarations.is_declared("x") assert_is(references.referenced_declaration(arg), references.referenced_declaration(ref))
def can_type_check_generic_function_with_type_parameters(): signature = nodes.signature( type_params=[nodes.formal_type_parameter("T")], args=[ nodes.signature_arg(nodes.ref("T")), ], returns=nodes.ref("T"), ) args = nodes.arguments([ nodes.argument("value"), ]) node = nodes.func("f", args=args, body=[nodes.ret(nodes.ref("value"))], type=signature) assert_equal(types.func([types.int_type], types.int_type), _infer_func_type(node).instantiate([types.int_type]))
def error_if_name_of_argument_does_not_match_name_in_signature(): signature = nodes.signature( args=[nodes.signature_arg("y", 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) try: _infer_func_type(node) assert False, "Expected error" except errors.ArgumentsError as error: assert_equal("argument 'x' has name 'y' in signature", str(error))
def error_if_type_signature_has_different_number_of_args_from_def(): signature = nodes.signature( args=[nodes.signature_arg(nodes.ref("int")), 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) try: _infer_func_type(node) assert False, "Expected error" except errors.ArgumentsError as error: assert_equal("args length mismatch: def has 1, signature has 2", str(error))
def error_if_type_signature_argument_is_optional_but_def_argument_is_not_optional(): signature = nodes.signature( args=[nodes.signature_arg(nodes.ref("int"), optional=True)], returns=nodes.type_union([nodes.ref("int"), nodes.ref("none")]) ) args = nodes.arguments([nodes.argument("x")]) body = [nodes.ret(nodes.ref("x"))] node = nodes.func("f", args, body, type=signature) try: _infer_func_type(node) assert False, "Expected error" except errors.ArgumentsError as error: assert_equal("optional argument 'x' must have default value", str(error))
def type_error_if_return_is_missing(): node = nodes.func( "f", args=nodes.arguments([]), body=[], type=nodes.signature(returns=nodes.ref("int")), ) try: _infer_func_type(node) assert False, "Expected error" except errors.MissingReturnError as error: assert_equal(node, error.node) assert_equal("Function must return value of type 'int'", str(error))
def can_infer_type_of_function_with_args_and_no_return(): signature = nodes.signature( args=[ nodes.signature_arg(nodes.ref("int")), nodes.signature_arg(nodes.ref("str")), ], returns=nodes.ref("none"), ) args = nodes.arguments([ nodes.argument("x"), nodes.argument("y"), ]) node = nodes.func("f", args=args, body=[], type=signature) assert_equal(types.func([types.int_type, types.str_type], types.none_type), _infer_func_type(node))
def function_definition_signature_has_names_resolved(): int_ref = nodes.ref("int") str_ref = nodes.ref("str") signature = nodes.signature( args=[nodes.signature_arg(int_ref)], returns=str_ref, ) node = nodes.func("f", nodes.arguments([]), [], type=signature) declarations = _create_declarations(["f", "int", "str"]) references = resolve(node, declarations) assert_is(declarations.declaration("int"), references.referenced_declaration(int_ref)) assert_is(declarations.declaration("str"), references.referenced_declaration(str_ref))
def argument_type_in_signature_is_unioned_with_none_if_argument_is_optional(): signature = nodes.signature( args=[nodes.signature_arg(nodes.ref("int"))], returns=nodes.ref("int") ) args = nodes.arguments([nodes.argument("x", optional=True)]) body = [nodes.ret(nodes.ref("x"))] node = nodes.func("f", args, body, type=signature) try: _infer_func_type(node) assert False, "Expected error" except errors.UnexpectedValueTypeError as error: assert_equal(types.int_type, error.expected) assert_equal(types.union(types.int_type, types.none_type), error.actual)
def can_infer_type_of_function_with_named_arg(): signature = nodes.signature( args=[ nodes.signature_arg("message", nodes.ref("int")), ], returns=nodes.ref("none") ) args = nodes.arguments([ nodes.argument("message"), ]) node = nodes.func("f", args=args, body=[], type=signature) assert_equal( types.func([types.func_arg("message", types.int_type)], types.none_type), _infer_func_type(node) )
def can_infer_type_of_function_with_optional_arg(): signature = nodes.signature( args=[ nodes.signature_arg(nodes.ref("int"), optional=True), ], returns=nodes.ref("none") ) args = nodes.arguments([ nodes.argument("x", optional=True), ]) node = nodes.func("f", args=args, body=[], type=signature) assert_equal( types.func([types.func_arg(None, types.int_type, optional=True)], types.none_type), _infer_func_type(node) )
def generic_function_definition_signature_has_names_resolved(): param = nodes.formal_type_parameter("T") arg_ref = nodes.ref("T") return_ref = nodes.ref("T") signature = nodes.signature( type_params=[param], args=[nodes.signature_arg(arg_ref)], returns=return_ref, ) node = nodes.func("f", nodes.arguments([]), [], type=signature) declarations = _create_declarations(["f"]) references = resolve(node, declarations) assert not declarations.is_declared("T") assert_is(references.referenced_declaration(param), references.referenced_declaration(arg_ref)) assert_is(references.referenced_declaration(param), references.referenced_declaration(return_ref))
def body_of_function_is_checked(): _assert_child_statement_is_checked(lambda generate: generate.func("f", nodes.arguments([]), [generate.unbound_ref_statement()], type=None) )
def function_definitions_adds_function_name_to_context(): node = nodes.func("f", nodes.arguments([]), [], type=None) declarations = _create_declarations(["f"]) references = resolve(node, declarations) assert_is(declarations.declaration("f"), references.referenced_declaration(node))
def function_name_is_definitely_bound_after_function_definition(): node = nodes.func("f", nodes.arguments([]), [], type=None) bindings = _updated_bindings(node) assert_equal(True, bindings.is_definitely_bound(node))
def arguments_of_function_are_definitely_bound(): arg = nodes.arg("x") arg_ref = nodes.ref("x") func_node = nodes.func("f", nodes.arguments([arg]), [nodes.expression_statement(arg_ref)], type=None) _updated_bindings(func_node)
def variables_from_outer_scope_remain_bound(): ref = nodes.ref("x") func_node = nodes.func("f", nodes.arguments([]), [nodes.expression_statement(ref)], type=None) _updated_bindings(func_node, is_definitely_bound={"x": True})