def children_of_for_loop_are_checked(): _assert_child_expression_is_checked(lambda generate: nodes.for_( nodes.attr(generate.unbound_ref(), "blah"), nodes.list_literal([]), [], [] ) ) _assert_child_expression_is_checked(lambda generate: nodes.for_( generate.target(), generate.unbound_ref(), [], [] ), ) _assert_child_statement_is_checked(lambda generate: nodes.for_( generate.target(), nodes.list_literal([]), [generate.unbound_ref_statement()], [] ), ) _assert_child_statement_is_checked(lambda generate: nodes.for_( generate.target(), nodes.list_literal([]), [], [generate.unbound_ref_statement()], ), )
def for_loop_has_child_names_resolved(): _assert_children_resolved( lambda ref: nodes.for_(ref, nodes.list_literal([]), [], []), ) _assert_children_resolved( lambda ref: nodes.for_(nodes.ref("target"), ref, [], []), other_names=["target"] ) _assert_children_resolved( lambda ref: nodes.for_(nodes.ref("target"), nodes.list_literal([]), [nodes.expression_statement(ref)], []), other_names=["target"] ) _assert_children_resolved( lambda ref: nodes.for_(nodes.ref("target"), nodes.list_literal([]), [], [nodes.expression_statement(ref)]), other_names=["target"] )
def for_statement_target_can_be_supertype_of_iterable_element_type(): ref_node = nodes.ref("xs") node = nodes.for_(nodes.subscript(nodes.ref("ys"), nodes.int_literal(0)), ref_node, []) update_context(node, type_bindings={ "xs": types.list_type(types.int_type), "ys": types.list_type(types.object_type), })
def test_parse_for_loop_with_else_body(): expected = nodes.for_( nodes.ref("x"), nodes.ref("xs"), [], [nodes.ret(nodes.ref("x"))], ) _assert_statement_parse(expected, "for x in xs:\n pass\nelse:\n return x")
def declarations_in_both_body_and_else_body_of_for_loop_are_not_definitely_bound(): _assert_name_is_not_definitely_bound(lambda generate: nodes.for_( generate.target(), nodes.list_literal([]), [generate.assignment()], [generate.assignment()] ), )
def for_statement_has_iterable_type_checked(): ref_node = nodes.ref("xs") node = nodes.for_(nodes.ref("x"), ref_node, []) try: update_context(node) assert False, "Expected error" except errors.TypeCheckError as error: assert_equal(ref_node, error.node)
def else_body_of_for_loop_is_type_checked(): assert_statement_is_type_checked( lambda bad_statement: nodes.for_(nodes.ref("x"), nodes.ref("xs"), [], [ bad_statement ]), type_bindings={ "xs": types.list_type(types.str_type), } )
def iter_method_must_take_no_arguments(): cls = types.class_type("Blah") cls.attrs.add("__iter__", types.func([types.str_type], types.iterable(types.str_type))) ref_node = nodes.ref("xs") node = nodes.for_(nodes.ref("x"), ref_node, []) try: update_context(node, type_bindings={"x": None, "xs": cls}) assert False, "Expected error" except errors.TypeCheckError as error: assert_equal(ref_node, ephemeral.root_node(error.node))
def for_statement_requires_iterable_to_have_iter_method(): ref_node = nodes.ref("xs") node = nodes.for_(nodes.ref("x"), ref_node, []) try: update_context(node, type_bindings={"xs": types.int_type}) assert False, "Expected error" except errors.UnexpectedValueTypeError as error: assert_equal(ref_node, error.node) assert_equal("iterable type", error.expected) assert_equal(types.int_type, error.actual)
def iter_method_must_return_iterator(): cls = types.class_type("Blah") cls.attrs.add("__iter__", types.func([], types.iterable(types.str_type))) ref_node = nodes.ref("xs") node = nodes.for_(nodes.ref("x"), ref_node, []) try: update_context(node, type_bindings={"x": None, "xs": cls}) assert False, "Expected error" except errors.BadSignatureError as error: assert_equal(ref_node, error.node)
def for_statement_target_can_be_variable(): node = nodes.for_(nodes.ref("x"), nodes.ref("xs"), []) # Unassigned case update_context(node, type_bindings={ "xs": types.list_type(types.str_type), }) # Assigned case update_context(node, type_bindings={ "x": types.str_type, "xs": types.list_type(types.str_type), })
def for_statement_accepts_iterable_with_iter_method(): cls = types.class_type("Blah") cls.attrs.add("__iter__", types.func([], types.iterator(types.str_type))) node = nodes.for_(nodes.ref("x"), nodes.ref("xs"), []) type_bindings = { "xs": cls, } context = update_context(node, type_bindings=type_bindings) assert_equal(types.str_type, context.lookup_name("x"))
def test_transform_for_loop(self): _assert_transform( nodes.for_( nodes.ref("x"), nodes.ref("xs"), [nodes.ret(nodes.ref("x"))], ), """ var __nope_u_iterator0 = $builtins.iter(xs) var __nope_u_element1 while True: __nope_u_element1 = $builtins.next(__nope_u_iterator0, $internals.loop_sentinel) if __nope_u_element1 is $internals.loop_sentinel: break x = __nope_u_element1 return x """ )
def for_statement_target_cannot_be_strict_subtype_of_iterable_element_type(): target_sequence_node = nodes.ref("ys") target_node = nodes.subscript(target_sequence_node, nodes.int_literal(0)) iterable_node = nodes.ref("xs") node = nodes.for_(target_node, iterable_node, []) try: update_context(node, type_bindings={ "xs": types.list_type(types.object_type), "ys": types.list_type(types.int_type), }) assert False, "Expected error" except errors.UnexpectedTargetTypeError as error: assert_equal(target_sequence_node, ephemeral.root_node(error.node)) assert_equal( ephemeral.FormalArg(ephemeral.attr(target_sequence_node, "__setitem__"), 1), ephemeral.underlying_node(error.node) ) assert_equal(types.object_type, error.value_type) assert_equal(types.int_type, error.target_type)
def for_statement_requires_iterable_getitem_method_to_accept_integers(): cls = types.class_type("Blah") cls.attrs.add("__getitem__", types.func([types.str_type], types.str_type)) ref_node = nodes.ref("xs") node = nodes.for_(nodes.ref("x"), ref_node, []) type_bindings = { "xs": cls, } try: update_context(node, type_bindings=type_bindings) assert False, "Expected error" except errors.UnexpectedTargetTypeError as error: assert_equal(ref_node, ephemeral.root_node(error.node)) assert_equal( ephemeral.FormalArg(ephemeral.attr(ref_node, "__getitem__"), 0), ephemeral.underlying_node(error.node) ) assert_equal(types.int_type, error.value_type) assert_equal(types.str_type, error.target_type)
def test_transform_for_loop_with_else_branch(self): _assert_transform( nodes.for_( nodes.ref("x"), nodes.ref("xs"), [nodes.ret(nodes.ref("x"))], [nodes.ret(nodes.ref("y"))], ), """ var __nope_u_iterator0 = $builtins.iter(xs) var __nope_u_element1 var __nope_u_normal_exit2 = False while True: __nope_u_element1 = $builtins.next(__nope_u_iterator0, $internals.loop_sentinel) if __nope_u_element1 is $internals.loop_sentinel: __nope_u_normal_exit2 = True break x = __nope_u_element1 return x if __nope_u_normal_exit2: return y """ )
def break_is_valid_in_for_loop_body(): node = nodes.for_(nodes.ref("x"), nodes.ref("xs"), [nodes.break_()]) check_loop_control(node, False)
def test_parse_for_loop(): expected = nodes.for_(nodes.ref("x"), nodes.ref("xs"), [nodes.ret(nodes.ref("x"))]) _assert_statement_parse(expected, "for x in xs:\n return x")
def for_loop_target_is_defined_but_not_definitely_bound(): _assert_name_is_not_definitely_bound(lambda generate: nodes.for_(generate.target(), nodes.list_literal([]), [], []) )
def for_loop_target_is_declared(): node = nodes.for_(nodes.ref("target"), nodes.list_literal([]), [], []) declarations = find_declarations(node) assert_equal("target", declarations.declaration("target").name) assert isinstance(declarations.declaration("target"), name_declaration.VariableDeclarationNode)