def test_add_operator_inference(self, a: int, b: int) -> None: try_prog = '{!r} {!r} +\n'.format(a, b) tree = parse(try_prog) _, type = concat.typecheck.infer( concat.typecheck.Environment(), tree.children, is_top_level=True, ) note(str(type)) self.assertEqual(type, StackEffect([], [int_type]))
def test_pushed_subscription_failure(self) -> None: """Test that pushed subscription words without something on the stack are disallowed.""" tree = parse('$[0] cast (int)') self.assertRaises( concat.typecheck.TypeError, concat.typecheck.infer, Environment(concat.typecheck.preamble_types.types), tree.children, )
def test_cast_word(self) -> None: """Test that the type checker properly checks casts.""" tree = parse('"str" cast (int)') _, type = concat.typecheck.infer( Environment(concat.typecheck.preamble_types.types), tree.children, is_top_level=True, ) self.assertEqual(type, StackEffect([], [int_type]))
def test_slice_inference(self) -> None: slice_prog = '[1, 2, 3, 4, 5, 6, 7, 8] $[1:None:2]\n' tree = parse(slice_prog) _, type = concat.typecheck.infer( Environment(concat.typecheck.preamble_types.types), tree.children, is_top_level=True, ) self.assertEqual(type, StackEffect([], [list_type[int_type,]]))
def test_attribute_error_location(self) -> None: bad_code = '5 .attr' tree = parse(bad_code) try: concat.typecheck.infer( concat.typecheck.Environment(), tree.children ) except concat.typecheck.TypeError as e: self.assertEqual(e.location, tree.children[1].location) else: self.fail('no type error')
def test_function_with_stack_effect(self) -> None: funcdef = 'def f(a b -- c): ()\n' tree = parse(funcdef) self.assertRaises( concat.typecheck.TypeError, concat.typecheck.infer, concat.typecheck.Environment(), tree.children, None, True, )
def test_call_inference(self) -> None: try_prog = '$(42) call\n' tree = parse(try_prog) _, type = concat.typecheck.infer( concat.typecheck.Environment( concat.typecheck.preamble_types.types ), tree.children, is_top_level=True, ) self.assertEqual(type, StackEffect([], [int_type]))
def test_with_word(self) -> None: wth = '$() ctxmgr with\n' tree = parse(wth) a_bar = SequenceVariable() self.assertRaises( concat.typecheck.TypeError, concat.typecheck.infer, concat.typecheck.Environment( { 'ctxmgr': concat.typecheck.types.ForAll( [a_bar], StackEffect([a_bar], [a_bar, object_type]) ) } ), tree.children, )
def test_function_with_strict_effect(self) -> None: """Test that a function type checks with a strict annotated effect. The type checker should allow the annotated effect of a function to be stricter than what would be inferred without the annotation.""" tree = parse( dedent( """\ def seek_file(file:file offset:int whence:int --): swap [(), (),] [,] swap pick $.seek py_call drop drop """ ) ) env = concat.typecheck.Environment( concat.typecheck.preamble_types.types ) concat.typecheck.infer(env, tree.children, None, True)
def test_with_word_and_funcdef_inference(self) -> None: wth = 'def fn(f:object -- n:int): drop 0 ~\n$fn {"file": "a_file"} open with' tree = parse(wth) in_var = SequenceVariable() _, type = concat.typecheck.infer( Environment( { **concat.typecheck.preamble_types.types, 'drop': concat.typecheck.types.ForAll( [in_var], StackEffect([in_var, object_type], [in_var]) ), 'open': concat.typecheck.types.ForAll( [in_var], # FIXME: dict_type should be a type constructor StackEffect([in_var, dict_type], [in_var, file_type]), ), } ), tree.children, initial_stack=TypeSequence([in_var]), ) self.assertEqual(type, StackEffect([in_var], [in_var, int_type]))
def test_try_word(self) -> None: try_prog = '$() $() try\n' tree = parse(try_prog) concat.typecheck.infer(concat.typecheck.Environment(), tree.children)
def test_list_subscription(self) -> None: """Test that the type checker allows subscription into lists.""" tree = parse('["a string", "another string",] $[1]') concat.typecheck.infer( concat.typecheck.Environment(), tree.children, None, True, )