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)
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')
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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')
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)
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)
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)
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)
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)
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)
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')
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)
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)
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)
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)
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')
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))
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)
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)
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)