def test_function_apply_args(self): def typed_expr(type_obj): class Expr(codegen.Expression): type = type_obj def constrain_type(self, type_obj, from_ftl_source=None): self.type = type_obj return Expr() function = types.Function.for_multiple_inputs( [dtypes.String, dtypes.Number], dtypes.Bool) zero_applied = function.apply_args([]) self.assertEqual(zero_applied.as_signature(codegen.Module()), "String -> number -> Bool") self.assertEqual(zero_applied, function) one_applied = function.apply_args([typed_expr(dtypes.String)]) self.assertEqual(one_applied.as_signature(codegen.Module()), "number -> Bool") self.assertEqual(one_applied, types.Function(dtypes.Number, dtypes.Bool)) two_applied = function.apply_args( [typed_expr(dtypes.String), typed_expr(dtypes.Number)]) self.assertEqual(two_applied.as_signature(codegen.Module()), "Bool") self.assertEqual(two_applied, dtypes.Bool)
def test_function_signature_type_parameters(self): param = types.TypeParam("a") f = types.Function(param, param) self.assertEqual(f.as_signature(codegen.Module()), "a -> a") f2 = types.Function(param, dtypes.List.specialize(a=param)) self.assertEqual(f2.as_signature(codegen.Module()), "a -> List a")
def test_non_builtin_simple_types(self): source_module = codegen.Module(name="MyModule") mytype = types.Type("MyType", source_module) self.assertEqual(mytype.as_signature(source_module), "MyType") main_module = codegen.Module() main_module.add_import(source_module, "MyAlias") self.assertEqual(mytype.as_signature(main_module), "MyAlias.MyType")
def test_function_signature(self): self.assertEqual( types.Function(dtypes.String, dtypes.Number).as_signature(codegen.Module()), "String -> number", ) self.assertEqual( types.Function.for_multiple_inputs([dtypes.String, dtypes.Number], dtypes.Bool).as_signature( codegen.Module()), "String -> number -> Bool", )
def test_type_parameters_specialize(self): source_module = codegen.Module(name="MyModule") container_type = types.Type("Container a", source_module) specialized = container_type.specialize(a=dtypes.Int) specialized2 = container_type.specialize(a=dtypes.Int) self.assertEqual(specialized, specialized2) self.assertNotEqual(specialized, container_type)
def test_function_signature_with_type_variables(self): function = types.Function.for_multiple_inputs( [types.UnconstrainedType(), types.UnconstrainedType()], types.UnconstrainedType(), ) self.assertEqual(function.as_signature(codegen.Module()), "a -> b -> c")
def test_function_args_name_check(self): module = codegen.Module() module.reserve_name("my_arg") func_name = module.reserve_name("myfunc") self.assertRaises( AssertionError, codegen.Function, func_name, args=["my_arg"], parent_scope=module, )
def test_variable_reference_function_arg_check(self): module = codegen.Module() func_name = module.reserve_name("myfunc") func = codegen.Function(func_name, args=["my_arg"], parent_scope=module) # Can't use undefined 'some_name' self.assertRaises(AssertionError, lambda: func.variables["some_name"]) # But can use function argument 'my_arg' ref = func.variables["my_arg"] self.assertCodeEqual(ref.as_source_code(), "my_arg")
def test_type_variables_complex(self): r1 = types.Record() r1.add_field("foo") r1.add_field("bar") r2 = types.Record() r2.add_field("baz") function = types.Function.for_multiple_inputs( [r1, r2], types.UnconstrainedType()) self.assertEqual( function.as_signature(codegen.Module()), "{ a | bar : b, foo : c } -> { d | baz : e } -> f", )
def test_type_parameters_constructors(self): source_module = codegen.Module(name="MyModule") container_type = types.Type("Container a", source_module, constructors=["Empty", ("Single", "a")]) self.assertEqual(container_type.as_signature(source_module), "Container a") Empty = source_module.variables["Empty"] Single = source_module.variables["Single"] self.assertEqual(Empty.type.as_signature(source_module), "Container a") self.assertEqual(Single.type.as_signature(source_module), "a -> Container a")
def test_let_no_assignments(self): module = codegen.Module() func = codegen.Function("myfunc", parent_scope=module) func.body.value = codegen.String("Hello") func = codegen.simplify(func) self.assertCodeEqual( func.as_source_code(), """ myfunc = "Hello" """, )
def test_function_args_name_reserved_check(self): module = codegen.Module() module.reserve_function_arg_name("myarg") func_name = module.reserve_name("myfunc") func = codegen.Function(func_name, args=["myarg"], parent_scope=module) func.body.value = func.variables["myarg"] func = codegen.simplify(func) self.assertCodeEqual( func.as_source_code(), """ myfunc myarg = myarg """, )
def test_function(self): module = codegen.Module() func = codegen.Function("myfunc", args=["myarg1", "myarg2"], parent_scope=module) func.body.value = codegen.String("hello") func = codegen.simplify(func) self.assertCodeEqual( func.as_source_code(), """ myfunc myarg1 myarg2 = "hello" """, )
def test_add_function(self): module = codegen.Module(name="Main") func_name = module.reserve_name("myfunc") func = codegen.Function(func_name, parent_scope=module) func.body.value = codegen.String("hi") module.add_function(func_name, func) func = codegen.simplify(func) self.assertCodeEqual( module.as_source_code(), """ module Main exposing (myfunc) myfunc = "hi" """, )
def test_let_one_assignment(self): module = codegen.Module() func = codegen.Function("myfunc", parent_scope=module) let = func.body x = let.add_assignment("x", codegen.String("Hello")) self.assertEqual(x.name, "x") self.assertEqual(x.type, dtypes.String) let.value = x func = codegen.simplify(func) self.assertCodeEqual( func.as_source_code(), """ myfunc = "Hello" """, )
def test_type_parameters_signatures(self): source_module = codegen.Module(name="MyModule") dict_type = types.Type("Dict k v", source_module) self.assertEqual(dict_type.as_signature(source_module), "Dict k v") env = types.SignatureEnv(used_type_variables={"k": 1, "v": 2}) self.assertEqual(dict_type.as_signature(source_module, env=env), "Dict k2 v2") dict_type = types.Type("Dict k v", source_module) str_to_float_dict = dict_type.specialize(k=dtypes.String, v=dtypes.Float) self.assertEqual(str_to_float_dict.as_signature(source_module), "Dict String Float") container_type = types.Type("Container a", source_module) complex_type = container_type.specialize(a=dict_type) self.assertEqual(complex_type.as_signature(source_module), "Container (Dict k v)")
def test_let_two_assignments(self): module = codegen.Module() func = codegen.Function("myfunc", parent_scope=module) let = func.body x = let.add_assignment("x", codegen.Number(1)) y = let.add_assignment("y", codegen.Number(2)) let.value = codegen.Add(x, y) func = codegen.simplify(func) # TODO SOMEDAY - remove unnecessary parenthesis in final expression self.assertCodeEqual( func.as_source_code(), """ myfunc = let x = 1 y = 2 in (x + y) """, )
def test_function_typed(self): module = codegen.Module() function_type = types.Function.for_multiple_inputs( [dtypes.String, dtypes.Number], dtypes.String) module.reserve_name("myfunc", type=function_type) func = codegen.Function( "myfunc", args=["myarg1", "myarg2"], parent_scope=module, function_type=function_type, ) func.body.value = codegen.String("hello") func = codegen.simplify(func) self.assertCodeEqual( func.as_source_code(), """ myfunc : String -> number -> String myfunc myarg1 myarg2 = "hello" """, ) self.assertEqual(func.variables["myarg2"].type, dtypes.Number)
def test_empty_record_signature(self): self.assertEqual(types.Record().as_signature(codegen.Module()), "a")
def test_unconstrained_signature(self): u = types.UnconstrainedType() self.assertEqual(u.as_signature(codegen.Module()), "a")
def test_module_builtins(self): module = codegen.Module() self.assertIn("min", module.all_reserved_names())
def test_tuple_signature(self): module = codegen.Module(name="MyModule") t = types.Tuple(dtypes.String, dtypes.Number) self.assertEqual(t.as_signature(module), "(String, number)")
def test_variable_reference(self): module = codegen.Module() name = module.reserve_name("name") ref = codegen.VariableReference(name, module) self.assertEqual(ref.as_source_code(), "name")
def test_elm_type_signature(self): self.assertEqual(dtypes.String.as_signature(codegen.Module()), "String")
def test_module_keywords(self): module = codegen.Module() self.assertIn("import", module.all_reserved_names())
def test_variable_reference_check(self): module = codegen.Module() self.assertRaises(AssertionError, codegen.VariableReference, "name", module)
def test_empty_record_signature_in_function(self): function = types.Function(types.Record(), types.UnconstrainedType()) self.assertEqual(function.as_signature(codegen.Module()), "a -> b")
def test_one_field_record_signature(self): r = types.Record() r.add_field("foo", type_obj=dtypes.String) self.assertEqual(r.as_signature(codegen.Module()), "{ a | foo : String }")
def test_one_field_fixed_record_signature(self): r = types.Record(foo=dtypes.String) self.assertEqual(r.as_signature(codegen.Module()), "{ foo : String }")