示例#1
0
class ExpressionTest(unittest.TestCase):
    def setUp(self):
        self._rules = TestingRules()
        self._registry = Registry()

    def test_variable_repr(self):
        self.assertEqual('Variable(foo)', repr(Variable('foo')))

    def test_variable(self):
        scoped_id = 'var_foo_1'
        self._registry.push_new_scope({'foo': (scoped_id, False)})
        v = Variable('foo')
        v_id = v.add_to_rules(self._rules, self._registry)
        self.assertEqual(v_id, scoped_id)
        self.assertEqual([], self._rules.instance_of_calls)

    def test_polymorphic_variable(self):
        scoped_id = 'var_foo_1'
        self._registry.push_new_scope({'foo': (scoped_id, True)})
        v = Variable('foo')
        v_id = v.add_to_rules(self._rules, self._registry)
        self.assertIn((v_id, scoped_id), self._rules.instance_of_calls)

    def test_literal_repr(self):
        self.assertEqual('Literal(Int, 123)', repr(Literal('Int', 123)))

    def test_literal(self):
        l = Literal('Int', 123)
        l_id = l.add_to_rules(self._rules, self._registry)
        self.assertTrue(l_id > 0)
        self.assertEqual([(l_id, 'Int')], self._rules.specify_calls)

    def test_typed_expression(self):
        l = Literal('Int', 123)
        te = TypedExpression('Num', l)
        self.assertEqual('TypedExpression(Num, Literal(Int, 123))', repr(te))
        te_id = te.add_to_rules(self._rules, self._registry)
        l_id = self._registry.get_id_for(l)
        self.assertNotEqual(l_id, te_id)
        self.assertSetEqual(
            set([(te_id, 'Num'), (l_id, 'Int')]),
            set(self._rules.specify_calls)
        )

    def test_application(self):
        scoped_id = 'var_times2_1'
        self._registry.push_new_scope({'times2': (scoped_id, True)})
        v = Variable('times2')
        l = Literal('Int', 123)
        a = Application(v, [l])
        a_id = a.add_to_rules(self._rules, self._registry)
        v_id = self._registry.get_id_for(v)
        l_id = self._registry.get_id_for(l)

        self.assertIn((v_id, scoped_id), self._rules.instance_of_calls)
        self.assertIn((v_id, ('Fn_1', l_id, a_id)), self._rules.specify_calls)

    def test_simple_let(self):
        l1 = Literal('Int', 123)
        l2 = Literal('Int', 456)
        lt = Let([('x', l1)], l2)
        lt_id = lt.add_to_rules(self._rules, self._registry)
        l1_id = self._registry.get_id_for(l1)
        l2_id = self._registry.get_id_for(l2)
        # TODO: the test is dependent on order for the name of var_x_1
        self.assertIn(('var_x_2', l1_id), self._rules.equal_calls)
        self.assertIn((lt_id, l2_id), self._rules.equal_calls)
        self.assertEqual([], self._rules.instance_of_calls)
        self.assertIn((l1_id, 'Int'), self._rules.specify_calls)
        self.assertIn((l2_id, 'Int'), self._rules.specify_calls)

    def _has_call_matching(self, test, calls):
        return any(test(call) for call in calls)

    def _has_equal_call_matching(self, test):
        return self._has_call_matching(test, self._rules.equal_calls)

    def test_let(self):
        l = Literal('Int', 123)
        var_x = Variable('x')
        var_y = Variable('y')
        lt = Let([('x', var_y), ('y', l)], var_x)
        lt_id = lt.add_to_rules(self._rules, self._registry)
        l_id = self._registry.get_id_for(l)
        var_x_id = self._registry.get_id_for(var_x)
        var_y_id = self._registry.get_id_for(var_y)

        self.assertIn((lt_id, var_x_id), self._rules.equal_calls)
        self.assertIn(('var_x_2', var_y_id), self._rules.equal_calls)
        self.assertIn(('var_y_3', l_id), self._rules.equal_calls)

    def test_simple_lambda_expression(self):
        lit = Literal('Int', 123)
        lm = Lambda(['x'], lit) # The `x` argument is unused
        lm_id = lm.add_to_rules(self._rules, self._registry)
        lit_id = self._registry.get_id_for(lit)
        # TODO: test is dependant on order for the name of var_x_2
        self.assertIn(
            (1, ('Fn_1', 'var_x_2', lit_id)),
            self._rules.specify_calls
        )
        self.assertIn((lit_id, 'Int'), self._rules.specify_calls)

    def test_lambda_exprssion(self):
        lm = Lambda(['x'], Variable('x'))
        lmid = lm.add_to_rules(self._rules, self._registry)
        self.assertEqual(
            [(1, ('Fn_1', 'var_x_2', 'var_x_2'))],
             self._rules.specify_calls
         )

    def test_let_with_lambda(self):
        lm = Lambda(['x'], Variable('x'))
        var_id = Variable('id')
        app = Application(var_id, [Literal('Int', 123)])
        lt = Let([('id', lm)], app)

        lt_id = lt.add_to_rules(self._rules, self._registry)
        app_id = self._registry.get_id_for(app)
        self.assertIn((lt_id, app_id), self._rules.equal_calls)
示例#2
0
 def setUp(self):
     self._rules = TestingRules()
     self._registry = Registry()
示例#3
0
 def setUp(self):
     self._rules = Rules()
     self._registry = Registry()
示例#4
0
class InferenceTest(unittest.TestCase):
    def setUp(self):
        self._rules = Rules()
        self._registry = Registry()

    def test_nonpolymorphic_variable(self):
        self._registry.push_new_scope({'foo': ('var_foo_1', False)})
        v = Variable('foo')
        v_id = v.add_to_rules(self._rules, self._registry)
        self.assertEqual(Result({}, {}), self._rules.infer())

    def test_polymorphic_variable(self):
        self._registry.push_new_scope({'foo': ('var_foo_1', True)})
        v = Variable('foo')
        v_id = v.add_to_rules(self._rules, self._registry)
        self.assertEqual(Result({}, {}), self._rules.infer())

    def test_literal(self):
        l = Literal('Int', 123)
        l_id = l.add_to_rules(self._rules, self._registry)
        self.assertEqual(Result({l_id: 'Int'}, {}), self._rules.infer())

    def test_typed_expression_mismatch(self):
        te = TypedExpression('String', Literal('Int', 123))
        te_id = te.add_to_rules(self._rules, self._registry)
        with self.assertRaises(InferenceError):
            self._rules.infer()

    def test_typed_expression_match(self):
        lit = Literal('Int', 123)
        te = TypedExpression('Int', lit)
        te_id = te.add_to_rules(self._rules, self._registry)
        lit_id = self._registry.get_id_for(lit)
        result = self._rules.infer()
        self.assertEqual('Int', result.get_type_by_id(te_id))
        self.assertEqual('Int', result.get_type_by_id(lit_id))

    def test_application(self):
        self._registry.push_new_scope({'times2': ('var_times2_1', True)})
        v = Variable('times2')
        l = Literal('Int', 123)
        a = Application(v, [l])
        a_id = a.add_to_rules(self._rules, self._registry)
        v_id = self._registry.get_id_for(v)
        l_id = self._registry.get_id_for(l)

        result = self._rules.infer()
        self.assertEqual('Int', result.get_type_by_id(l_id))
        self.assertEqual(None, result.get_type_by_id(a_id))

    def test_let(self):
        l = Literal('Int', 123)
        lt = Let([('x', l)], Variable('x'))
        lt_id = lt.add_to_rules(self._rules, self._registry)

        result = self._rules.infer()
        self.assertEqual('Int', result.get_type_by_id(lt_id))

    def test_multi_let(self):
        l = Literal('Int', 123)
        lt = Let([('x', Variable('y')), ('y', l)], Variable('x'))
        lt_id = lt.add_to_rules(self._rules, self._registry)
        l_id = self._registry.get_id_for(l)

        result = self._rules.infer()
        self.assertEqual('Int', result.get_type_by_id(lt_id))

    def test_lambda_exprssion(self):
        lm = Lambda(['x'], Variable('x'))
        lmid = lm.add_to_rules(self._rules, self._registry)

        result = self._rules.infer()
        self.assertEqual(
            ('Fn_1', 'var_x_2', 'var_x_2'),
            result.get_type_by_id(lmid)
        )

    def test_let_with_lambda(self):
        ''' ML code:
        let id = \\x -> x
        in id 'foo'
        '''
        lm = Lambda(['x'], Variable('x'))
        var_id = Variable('id')
        app = Application(var_id, [Literal('String', 'foo')])
        lt = Let([('id', lm)], app)
        lt_id = lt.add_to_rules(self._rules, self._registry)

        result = self._rules.infer()
        self.assertEqual('String', result.get_type_by_id(lt_id))

    def test_polymorphism(self):
        ''' ML code:
        let id = \\x -> x
        in (id id) 123
        '''
        lm = Lambda(['x'], Variable('x'))
        app1 = Application(Variable('id'), [Variable('id')])
        app2 = Application(app1, [Literal('Int', 123)])
        lt = Let([('id', lm)], app2)
        lt_id = lt.add_to_rules(self._rules, self._registry)

        result = self._rules.infer()
        self.assertEqual('Int', result.get_type_by_id(lt_id))

    def test_if_statement(self):
        test = Literal('Bool', True)
        if_case = Literal('Int', 123)
        else_case = Literal('Int', 456)
        if_block = If(test, if_case, else_case)

        if_id = if_block.add_to_rules(self._rules, self._registry)
        result = self._rules.infer()

        self.assertEqual('Int', result.get_type_by_id(if_id))

    def test_if_statement_requires_branches_to_equal(self):
        test = Literal('Bool', True)
        if_case = Literal('Int', 123)
        else_case = Literal('Float', 456)
        if_block = If(test, if_case, else_case)

        if_id = if_block.add_to_rules(self._rules, self._registry)
        with self.assertRaises(InferenceError):
            self._rules.infer()

    def test_if_statement_requires_test_to_be_boolean(self):
        test = Literal('String', 'not a boolean')
        if_case = Literal('Int', 123)
        else_case = Literal('Int', 456)
        if_block = If(test, if_case, else_case)

        if_id = if_block.add_to_rules(self._rules, self._registry)
        with self.assertRaises(InferenceError):
            self._rules.infer()

    def test_mutual_recursion(self):
        '''
        Equivalent ML:

        let-rec f = if True then 123 else g
                g = f
        in f
        '''
        test = Literal('Bool', True)
        if_case = Literal('Int', 123)
        else_case = Application(Variable('g'), [])
        if_block = If(test, if_case, else_case)
        f_func = Lambda([], if_block)

        g_body = Application(Variable('f'), [])
        g_func = Lambda([], g_body)

        let_body = Variable('f')
        let_expr = Let([('f', f_func), ('g', g_func)], let_body)

        let_id = let_expr.add_to_rules(self._rules, self._registry)
        result = self._rules.infer()
        self.assertEqual(('Fn_0', 'Int'), result.get_full_type_by_id(let_id))

    def test_generic_mutual_recursion(self):
        '''
        Equivalent ML:

        let-rec f x = if True then x else g x
                g y = f y
        in g
        '''
        test = Literal('Bool', True)
        if_case = Variable('x')
        else_case = Application(Variable('g'), [Variable('x')])
        if_block = If(test, if_case, else_case)
        f_func = Lambda(['x'], if_block)

        g_body = Application(Variable('f'), [Variable('y')])
        g_func = Lambda(['y'], g_body)

        let_body = Variable('f')
        let_expr = Let([('f', f_func), ('g', g_func)], let_body)

        let_id = let_expr.add_to_rules(self._rules, self._registry)
        result = self._rules.infer()
        self.assertEqual(('Fn_1', 'a0', 'a0'), result.get_full_type_by_id(let_id))
示例#5
0
 def test_add_and_get_from_registry(self):
     registry = Registry()
     id1 = registry.add_to_registry('x')
     id2 = registry.add_to_registry('y')
     self.assertEqual('x', registry.get_registered()[id1])
     self.assertEqual('y', registry.get_registered()[id2])
示例#6
0
 def test_catches_duplicate_use_of_ids(self):
     registry = Registry()
     registry.register_for_id(1, 'x')
     with self.assertRaises(Exception):
         registry.register_for_id(1, 'x')
示例#7
0
 def test_generates_new_ids(self):
     registry = Registry()
     self.assertEqual([1, 2, 3, 4],
                      [registry.generate_new_id() for _ in range(4)])