Beispiel #1
0
    def test_if_as_statement(self):
        module = self.prepare('if true {} else {}')
        infer_types(module)

        module = self.prepare('if false {} else if 1 < 3 {}')
        infer_types(module)

        module = self.prepare('''
        cst x: Bool
        if x {}
        ''')
        infer_types(module)

        module = self.prepare('if 0 {}')
        with self.assertRaises(InferenceError):
            infer_types(module)

        module = self.prepare('''
        mut x = 1
        if true {
            x = 2
        } else {
            x = 'foo'
        }
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)
Beispiel #2
0
    def test_nested_types(self):
        module = self.prepare('''
        enum E {
            struct S { cst y: Self }
        }
        cst x: E.S
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        self.assertEqual(
            self.type_of(declaration_nodes[0], environment).name, 'S')
        self.assertEqual(
            self.type_of(declaration_nodes[1], environment).name, 'S')

        module = self.prepare('''
        cst x: E.S.F
        enum E {
            struct S {
                enum F {}
            }
        }
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type.name, 'F')
Beispiel #3
0
    def test_prefixed_expression(self):
        module = self.prepare('cst x = -0')
        (module, environment) = infer_types(module)
        x_type = self.type_of(find('ContainerDecl', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('''
        cst s: S
        cst x = not s

        struct S {
            fun not(cst _ self: Self) -> Self {}
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        s_type = self.type_of(declaration_nodes[0], environment)
        x_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(x_type, s_type)

        module = self.prepare('''
        cst s: S
        cst x = not s

        struct S {
            fun not(cst _ self: Self) -> Bool {}
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(x_type, Bool)
Beispiel #4
0
    def test_switch_as_expression(self):
        module = self.prepare('''
        cst x = switch 0 {
            case 0 {
                cst a = 9
                return 'foo'
            }
            case _ {
                cst a = '9'
                return 'bar'
            }
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl:*', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertEqual(x_type, String)
        a0_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(a0_type, Int)
        a1_type = self.type_of(declaration_nodes[2], environment)
        self.assertEqual(a1_type, String)

        module = self.prepare('''
        cst x = switch 0 {
            case 0 { return 'foo' }
            case _ { return 0 }
        }
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)
Beispiel #5
0
    def test_binary_expression(self):
        module = self.prepare('cst x = 0 + 2')
        (module, environment) = infer_types(module)
        x_type = self.type_of(find('ContainerDecl', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('''
        cst s: S
        cst x = s + s

        struct S {
            fun +(cst _ lhs: Self, cst _ rhs: Self) -> Self {}
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        s_type = self.type_of(declaration_nodes[0], environment)
        x_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(x_type, s_type)

        module = self.prepare('''
        cst s: S
        cst x = s + 0

        struct S {
            fun +(cst _ lhs: Self, cst _ rhs: Int) -> Int {}
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(x_type, Int)
Beispiel #6
0
    def test_functions_as_first_class(self):
        module = self.prepare('''
        fun f(cst x: Int, cst y: Int) -> Int {}
        cst x = f
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        f_type = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertEqual(x_type, f_type)

        module = self.prepare('''
        cst x = f
        fun f(cst x: Int, cst y: Int) -> Int {}
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        f_type = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertEqual(x_type, f_type)

        module = self.prepare('''
        cst x = f
        fun f(cst x: Int, cst y: Int) -> Int {}
        fun f(cst x: String, cst y: String) -> String {}
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        f_type = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertEqual(x_type, f_type)
Beispiel #7
0
    def test_assignment(self):
        module = self.prepare('''
        cst x
        x = 0
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('''
        cst x: Int
        cst y
        x = y
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        self.assertEqual(self.type_of(declaration_nodes[0], environment), Int)
        self.assertEqual(self.type_of(declaration_nodes[1], environment), Int)

        module = self.prepare('''
        cst x: Int
        cst y: String
        x = y
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)
Beispiel #8
0
    def test_call_with_generic_parameters(self):
        module = self.prepare('''
        fun f<T, U>(cst x: T, cst y: U) -> T {}

        cst x = f(x: 0, y: 'hello world')
        cst y = f(x: 'hello world', y: 0)
        cst z = f(x: 1.0, y: 2.0)
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertEqual(x_type, Int)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(y_type, String)
        y_type = self.type_of(declaration_nodes[2], environment)
        self.assertEqual(y_type, Double)

        module = self.prepare('''
        cst x = f(x: g)

        fun f<T>(cst x: T) -> T {}
        fun g() {}
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertIsInstance(x_type, FunctionType)
        self.assertFalse(x_type.domain)
        self.assertFalse(x_type.labels)
        self.assertEqual(x_type.codomain, Nothing)

        module = self.prepare('''
        cst x = f(x: g)
        cst y = f(x: h)

        fun f<T, U>(cst x: (cst y: T, cst z: U) -> U) -> T {}
        fun g(cst y: Int, cst z: Int) -> Int {}
        fun h(cst y: String, cst z: Double) -> Double {}
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertEqual(x_type, Int)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(y_type, String)

        module = self.prepare('''
        cst x = f(x: f(x: g))

        fun f<T>(cst x: T) -> T {}
        fun g(cst x: Int) -> Int {}
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertIsInstance(x_type, FunctionType)
        self.assertEqual(x_type.domain, [Int])
        self.assertEqual(x_type.codomain, Int)
Beispiel #9
0
 def test_switch_as_statement(self):
     module = self.prepare('''
     mut x = 1
     switch x {
         case 1 { x = 2 }
         case 2 { x = 'foo' }
     }
     ''')
     with self.assertRaises(InferenceError):
         infer_types(module)
Beispiel #10
0
    def test_call_constraints_propagation(self):
        module = self.prepare('''
        cst x = f()
        cst y = g(x)
        cst z = h(y)

        fun f() -> Int {}
        fun f() -> String {}
        fun f() -> Double {}

        fun g(cst _ arg: Int) -> Int {}
        fun g(cst _ arg: String) -> String {}
        fun g<T>(cst _ arg: T) -> T {}

        fun h(cst _ arg: Int) -> Int {}
        fun h(cst _ arg: Double) -> Int {}
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertIsInstance(x_type, TypeUnion)
        self.assertIn(Int, x_type)
        self.assertIn(Double, x_type)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertIsInstance(y_type, TypeUnion)
        self.assertIn(Int, y_type)
        self.assertIn(Double, y_type)
        z_type = self.type_of(declaration_nodes[2], environment)
        self.assertEqual(z_type, Int)
Beispiel #11
0
    def test_enum_decl(self):
        module = self.prepare('enum E {}')
        (module, environment) = infer_types(module)
        e_type = self.type_of(find('EnumDecl:first', module)[0], environment)
        self.assertIsInstance(e_type, EnumType)
        self.assertEqual(e_type.name, 'E')

        module = self.prepare('''
        enum E {
            case foo
            case bar(x: Int, y: Self)
        }
        ''')
        (module, environment) = infer_types(module)
        e_type = self.type_of(find('EnumDecl:first', module)[0], environment)
        self.assertIsInstance(e_type, EnumType)
        self.assertEqual(e_type.name, 'E')

        # TODO Fix reification of nominal types.
        self.assertEqual(environment[e_type.members['foo']], e_type)
        bar_type = environment[e_type.members['bar']]
        self.assertIsInstance(bar_type, FunctionType)
        self.assertEqual(len(bar_type.domain), 2)
        self.assertEqual(bar_type.domain, [Int, e_type])
        self.assertEqual(bar_type.codomain, e_type)

        module = self.prepare('''
        enum E {
            case foo
            case bar(x: Int, y: Self)

            fun baz(mut self: Self) {}
        }
        ''')
        (module, environment) = infer_types(module)
        e_type = self.type_of(find('EnumDecl:first', module)[0], environment)
        self.assertIsInstance(e_type, EnumType)
        self.assertEqual(e_type.name, 'E')

        # TODO Fix reification of nominal types.
        self.assertEqual(environment[e_type.members['foo']], e_type)
        self.assertIsInstance(environment[e_type.members['bar']], FunctionType)
        self.assertIsInstance(environment[e_type.members['baz']], FunctionType)
Beispiel #12
0
    def test_shadowing(self):
        module = self.prepare('''
        cst x = 0
        fun f() { cst x = 'Hello, World!' }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        self.assertEqual(self.type_of(declaration_nodes[0], environment), Int)
        self.assertEqual(self.type_of(declaration_nodes[1], environment),
                         String)

        module = self.prepare('''
        cst x = 0
        fun f() { cst x = x }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        self.assertEqual(self.type_of(declaration_nodes[0], environment), Int)
        self.assertEqual(self.type_of(declaration_nodes[1], environment), Int)
Beispiel #13
0
    def test_parameter_overloading(self):
        module = self.prepare('''
        fun f(cst x: Int) {}
        fun f(cst x: String) {}
        ''')
        (module, environment) = infer_types(module)
        f_types = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertIsInstance(f_types, TypeUnion)
        self.assertEqual(len(f_types), 2)
        self.assertIn(Int, (f.domain[0] for f in f_types.types))
        self.assertIn(String, (f.domain[0] for f in f_types.types))

        self.assertEqual(len(f_types.types[0].domain), 1)
        self.assertEqual(f_types.types[0].codomain, Nothing)

        self.assertEqual(len(f_types.types[1].domain), 1)
        self.assertEqual(f_types.types[1].codomain, Nothing)

        module = self.prepare('''
        fun f(cst x: Int, cst y: Int) {}
        fun f(cst x: Int) {}
        ''')
        (module, environment) = infer_types(module)
        f_types = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertIsInstance(f_types, TypeUnion)
        self.assertEqual(len(f_types), 2)
        self.assertTrue((len(f_types.types[0].domain) == 1)
                        or (len(f_types.types[1].domain) == 1))
        self.assertTrue((len(f_types.types[0].domain) == 2)
                        or (len(f_types.types[1].domain) == 2))

        f0 = f_types.types[0] if len(
            f_types.types[0].domain) == 1 else f_types.types[1]
        self.assertEqual(f0.domain, [Int])
        self.assertEqual(f0.codomain, Nothing)

        f1 = f_types.types[0] if len(
            f_types.types[0].domain) == 2 else f_types.types[1]
        self.assertEqual(f1.domain, [Int, Int])
        self.assertEqual(f1.codomain, Nothing)
Beispiel #14
0
    def test_constructor(self):
        module = self.prepare('''
        cst s = S()

        struct S {
            fun new(mut self: Self) -> Self {}
        }
        ''')
        (module, environment) = infer_types(module)
        s_type = self.type_of(find('ContainerDecl', module)[0], environment)
        self.assertIsInstance(s_type, StructType)
        self.assertEqual(s_type.name, 'S')
Beispiel #15
0
    def test_annotating_custom_nominal_type(self):
        module = self.prepare('''
        struct S {}
        cst x: S
        ''')
        (module, environment) = infer_types(module)
        s_type = self.type_of(find('StructDecl:first', module)[0], environment)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, s_type)

        module = self.prepare('''
        cst x: S
        struct S {}
        ''')
        (module, environment) = infer_types(module)
        s_type = self.type_of(find('StructDecl:first', module)[0], environment)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, s_type)

        module = self.prepare('''
        enum E {}
        cst x: E
        ''')
        (module, environment) = infer_types(module)
        e_type = self.type_of(find('EnumDecl:first', module)[0], environment)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, e_type)

        module = self.prepare('''
        cst x: E
        enum E {}
        ''')
        (module, environment) = infer_types(module)
        e_type = self.type_of(find('EnumDecl:first', module)[0], environment)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, e_type)
Beispiel #16
0
    def test_auto_self_binding(self):
        module = self.prepare('''
        cst s: S
        cst x = s.baz
        cst y = S.baz

        struct S {
            fun baz(mut self: Self) -> Int {}
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        s_type = self.type_of(declaration_nodes[0], environment)
        x_type = self.type_of(declaration_nodes[1], environment)
        self.assertIsInstance(x_type, FunctionType)
        self.assertFalse(x_type.domain)
        self.assertFalse(x_type.labels)
        self.assertEqual(x_type.codomain, Int)
        y_type = self.type_of(declaration_nodes[2], environment)
        self.assertIsInstance(y_type, FunctionType)
        self.assertEqual(y_type.domain, [s_type])
        self.assertEqual(y_type.labels, ['self'])
        self.assertEqual(y_type.codomain, Int)

        module = self.prepare('''
        cst x = Point()
        cst y = x.distance(to: x)

        struct Point {
            fun new(cst self: Self) -> Self {}
            fun distance(cst self: Self, cst to other: Self) -> Double {}
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertIsInstance(x_type, StructType)
        self.assertEqual(x_type.name, 'Point')
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(y_type, Double)
Beispiel #17
0
    def test_container_decl(self):
        module = self.prepare('cst x = 0')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('cst x: Int')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('cst x: Int = 0')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('cst x: String = 0')
        with self.assertRaises(InferenceError):
            infer_types(module)

        module = self.prepare('cst x: (cst _: Int) -> Nothing')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertIsInstance(x_type, FunctionType)
        self.assertEqual(x_type.domain, [Int])
        self.assertEqual(x_type.codomain, Nothing)
        self.assertEqual(x_type.labels, [None])

        module = self.prepare('''
        mut x
        x = 1.0
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Double)

        module = self.prepare('''
        mut x
        mut y = x
        mut z: Int = y
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        for node in declaration_nodes:
            self.assertEqual(self.type_of(node, environment), Int)
Beispiel #18
0
    def test_specialization_by_type_annotation(self):
        module = self.prepare('''
        fun f<T, U>(cst _ a: T) -> U {}
        cst x: (cst _: Int) -> String = f
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertIsInstance(x_type, FunctionType)
        self.assertEqual(x_type.domain, [Int])
        self.assertEqual(x_type.codomain, String)

        module = self.prepare('''
        fun f<T, U> (cst _ a: T) -> U {}
        fun g(cst x: (cst _: Int) -> String = f) {}
        ''')
        (module, environment) = infer_types(module)
        g_type = self.type_of(find('FunctionDecl', module)[1], environment)
        self.assertIsInstance(g_type, FunctionType)
        self.assertIsInstance(g_type.domain[0], FunctionType)
        self.assertEqual(g_type.domain[0].domain, [Int])
        self.assertEqual(g_type.domain[0].codomain, String)
Beispiel #19
0
    def test_if_as_expression(self):
        module = self.prepare('cst x = if true { return 0 } else { return 1 }')
        (module, environment) = infer_types(module)
        x_type = self.type_of(find('ContainerDecl', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('''
        cst x = if true {
            cst a = 9
            return 1
        } else if true {
            cst a = 'bar'
            return 2
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl:*', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertEqual(x_type, Int)
        a0_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(a0_type, Int)
        a1_type = self.type_of(declaration_nodes[2], environment)
        self.assertEqual(a1_type, String)

        module = self.prepare(
            'cst x = true and if true { return true } else { return false }')
        (module, environment) = infer_types(module)
        x_type = self.type_of(find('ContainerDecl', module)[0], environment)
        self.assertEqual(x_type, Bool)

        module = self.prepare('''
        cst x = if true {
            return 1
        } else if true {
            return 'bar'
        }
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)
Beispiel #20
0
    def test_struct_decl(self):
        module = self.prepare('struct S {}')
        (module, environment) = infer_types(module)
        s_type = self.type_of(find('StructDecl:first', module)[0], environment)
        self.assertIsInstance(s_type, StructType)
        self.assertEqual(s_type.name, 'S')

        module = self.prepare('''
        struct S {
            cst foo: Int
            cst bar: String
        }
        ''')
        (module, environment) = infer_types(module)
        s_type = self.type_of(find('StructDecl:first', module)[0], environment)
        self.assertIsInstance(s_type, StructType)
        self.assertEqual(s_type.name, 'S')

        # TODO Fix reification of nominal types.
        self.assertEqual(environment[s_type.members['foo']], Int)
        self.assertEqual(environment[s_type.members['bar']], String)

        module = self.prepare('''
        struct S {
            cst foo: Int
            cst bar: String

            fun baz(mut self: Self) {}
        }
        ''')
        (module, environment) = infer_types(module)
        s_type = self.type_of(find('StructDecl:first', module)[0], environment)
        self.assertIsInstance(s_type, StructType)
        self.assertEqual(s_type.name, 'S')

        # TODO Fix reification of nominal types.
        self.assertEqual(environment[s_type.members['foo']], Int)
        self.assertEqual(environment[s_type.members['bar']], String)
        self.assertIsInstance(environment[s_type.members['baz']], FunctionType)
Beispiel #21
0
    def test_enum_case_constructor(self):
        module = self.prepare('''
        cst x = E.foo
        cst y = E.bar(x: 0, y: E.foo)

        enum E {
            case foo
            case bar(x: Int, y: Self)
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertIsInstance(x_type, EnumType)
        self.assertEqual(x_type.name, 'E')
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertIsInstance(y_type, EnumType)
        self.assertEqual(y_type.name, 'E')

        module = self.prepare('''
        cst x: E = .foo
        cst y: E = .bar(x: 0, y: .foo)

        enum E {
            case foo
            case bar(x: Int, y: Self)
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertIsInstance(x_type, EnumType)
        self.assertEqual(x_type.name, 'E')
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertIsInstance(y_type, EnumType)
        self.assertEqual(y_type.name, 'E')
Beispiel #22
0
    def test_return_type_overloading(self):
        module = self.prepare('''
        fun f() -> Int {}
        fun f() -> String {}
        ''')
        (module, environment) = infer_types(module)
        f_types = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertIsInstance(f_types, TypeUnion)
        self.assertEqual(len(f_types), 2)
        self.assertIn(Int, (f.codomain for f in f_types))
        self.assertIn(String, (f.codomain for f in f_types))

        self.assertFalse(f_types.types[0].domain)
        self.assertFalse(f_types.types[1].domain)
Beispiel #23
0
    def test_select(self):
        module = self.prepare('''
        cst s: S
        cst x = s.foo
        cst y = s.bar

        struct S {
            cst foo: Int
            cst bar: String
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(x_type, Int)
        y_type = self.type_of(declaration_nodes[2], environment)
        self.assertEqual(y_type, String)
Beispiel #24
0
    def test_parameter_mutability_overloading(self):
        module = self.prepare('''
        fun f(cst x: Int) {}
        fun f(mut x: Int) {}
        ''')
        (module, environment) = infer_types(module)
        f_types = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertIsInstance(f_types, TypeUnion)
        self.assertEqual(len(f_types), 2)
        self.assertTrue(('mutable' in f_types.types[0].attributes[0]) != (
            'mutable' in f_types.types[1].attributes[0]))

        self.assertEqual(f_types.types[0].domain, [Int])
        self.assertEqual(f_types.types[0].codomain, Nothing)

        self.assertEqual(f_types.types[1].domain, [Int])
        self.assertEqual(f_types.types[1].codomain, Nothing)
Beispiel #25
0
    def test_type_as_first_class(self):
        module = self.prepare('cst x = Int.self')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Type)

        module = self.prepare('cst x = Int')
        with self.assertRaises(SyntaxError):
            infer_types(module)

        module = self.prepare('''
        struct S {}
        cst x = S.self
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Type)

        module = self.prepare('''
        cst x = S.self
        struct S {}
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Type)

        module = self.prepare('''
        enum E {}
        cst x = E.self
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Type)

        module = self.prepare('''
        cst x = E.self
        enum E {}
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Type)
Beispiel #26
0
    def test_if_with_pattern(self):
        module = self.prepare('''
        cst e: E = .bar(x: 0, y: .foo)
        if let cst a, cst b in e == .bar(x: a, y: b) {}

        enum E {
            case foo
            case bar(x: Int, y: Self)

            fun == (cst _ lhs: Self, cst _ rhs: Self) -> Bool {}
        }
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        a_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(a_type, Int)
        b_type = self.type_of(declaration_nodes[2], environment)
        self.assertIsInstance(b_type, EnumType)
        self.assertEqual(b_type.name, 'E')
Beispiel #27
0
    def test_inner_scoped_overloading(self):
        module = self.prepare('''
        fun f() -> Int {
            fun f() -> String {}
        }
        ''')
        (module, environment) = infer_types(module)
        function_nodes = find('FunctionDecl:*', module)

        outer_f = self.type_of(function_nodes[0], environment)
        self.assertIsInstance(outer_f, FunctionType)
        self.assertEqual(outer_f.codomain, Int)

        inner_f = self.type_of(function_nodes[1], environment)
        self.assertIsInstance(inner_f, TypeUnion)
        self.assertEqual(len(inner_f), 2)
        self.assertTrue(any(f == outer_f for f in inner_f))
        self.assertIn(Int, (f.codomain for f in inner_f))
        self.assertIn(String, (f.codomain for f in inner_f))
Beispiel #28
0
    def test_label_overloading(self):
        module = self.prepare('''
        fun f(cst a x: Int) {}
        fun f(cst b x: Int) {}
        ''')
        (module, environment) = infer_types(module)
        f_types = self.type_of(
            find('FunctionDecl:first', module)[0], environment)
        self.assertIsInstance(f_types, TypeUnion)
        self.assertEqual(len(f_types), 2)

        self.assertIn('a', (f.labels[0] for f in f_types))
        self.assertIn('b', (f.labels[0] for f in f_types))

        self.assertEqual(len(f_types.types[0].domain), 1)
        self.assertEqual(f_types.types[0].domain, [Int])
        self.assertEqual(f_types.types[0].codomain, Nothing)

        self.assertEqual(len(f_types.types[1].domain), 1)
        self.assertEqual(f_types.types[1].domain, [Int])
        self.assertEqual(f_types.types[1].codomain, Nothing)
Beispiel #29
0
    def test_call_with_overloading(self):
        module = self.prepare('''
        fun f(cst x: Int, cst y: Int) -> Int {}
        fun f(cst x: String, cst y: String) -> String {}

        cst x = f(x: 0, y: 0)
        cst y = f(x: 'hello', y: 'world')
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertEqual(x_type, Int)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(y_type, String)

        module = self.prepare('''
        cst x = f(x: 0, y: 0)
        cst y = f(x: 'hello', y: 'world')

        fun f(cst x: Int, cst y: Int) -> Int {}
        fun f(cst x: String, cst y: String) -> String {}
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertEqual(x_type, Int)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(y_type, String)

        module = self.prepare('''
        fun f(cst x: Int, cst y: Int) -> Int {}
        fun f(cst _ x: String, cst _ y: String) -> String {}

        cst x = f(x: 0, y: 0)
        cst y = f('hello', 'world')
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        x_type = self.type_of(declaration_nodes[0], environment)
        self.assertEqual(x_type, Int)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(y_type, String)

        module = self.prepare('''
        cst x = f()

        fun f() -> Int {}
        fun f() -> String {}
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(find('ContainerDecl', module)[0], environment)
        self.assertIsInstance(x_type, TypeUnion)
        self.assertIn(Int, x_type)
        self.assertIn(String, x_type)

        module = self.prepare('''
        mut x = 9
        cst y = f(x)

        fun f(mut _ a: Int) -> Int {}
        fun f(cst _ a: Int) -> String {}
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertIsInstance(y_type, TypeUnion)
        self.assertIn(Int, y_type)
        self.assertIn(String, y_type)

        module = self.prepare('''
        cst x = 9
        cst y = f(x)

        fun f(mut _ a: Int) -> Int {}
        fun f(cst _ a: Int) -> String {}
        ''')
        (module, environment) = infer_types(module)
        declaration_nodes = find('ContainerDecl', module)
        y_type = self.type_of(declaration_nodes[1], environment)
        self.assertEqual(y_type, String)
Beispiel #30
0
    def test_call_without_overloading(self):
        module = self.prepare('''
        fun f() -> Int {}
        cst x = f()
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('''
        cst x = f(x: 0, y: 0)
        fun f(cst x: Int, cst y: Int) -> Int {}
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('''
        cst x = f(x: g)

        fun f(cst x: (cst y: Int) -> Int) -> Int {}
        fun g(cst y: Int) -> Int {}
        ''')
        (module, environment) = infer_types(module)
        x_type = self.type_of(
            find('ContainerDecl:first', module)[0], environment)
        self.assertEqual(x_type, Int)

        module = self.prepare('''
        fun f(cst x: Int, cst y: Int) -> Int {}
        cst x = f(x: 0, z: 0)
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)

        module = self.prepare('''
        fun f(cst x: Int, cst y: Int) -> Int {}
        cst x = f(x: 0, 0)
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)

        module = self.prepare('''
        fun f(cst x: Int, cst y: Int) -> Int {}
        cst x = f(x: 0, y: 0.0)
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)

        module = self.prepare('''
        cst x = f(x: g)

        fun f(cst x: (cst y: Int) -> Int) -> Int {}
        fun g(cst x: Int) -> Int {}
        ''')
        with self.assertRaises(InferenceError):
            infer_types(module)