def test_add_assignment_reserved(self): scope = codegen.Scope() let = codegen.Let(parent_scope=scope) name = let.add_assignment("x", codegen.String("a string")) self.assertEqual(name.name, "x") let.value = codegen.String("other") self.assertCodeEqual( let.as_source_code(), """ let x = "a string" in "other" """, )
def test_string_join_omit_empty_2(self): scope = codegen.Scope() scope.reserve_name("tmp", type=dtypes.String) var = scope.variables["tmp"] join = codegen.StringConcat([codegen.String(""), var]) join = codegen.simplify(join) self.assertCodeEqual( join.as_source_code(), """ tmp """, )
def test_string_join_collapse_strings(self): scope = codegen.Scope() scope.reserve_name("tmp", type=dtypes.String) var = scope.variables["tmp"] join1 = codegen.StringConcat([ codegen.String("hello "), codegen.String("there "), var, codegen.String(" how"), codegen.String(" are you?"), ]) join1 = codegen.simplify(join1) self.assertCodeEqual( join1.as_source_code(), """ String.concat [ "hello there " , tmp , " how are you?" ] """, )
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_string_join_two(self): scope = codegen.Scope() scope.reserve_name("tmp", type=dtypes.String) var = scope.variables["tmp"] join = codegen.StringConcat([codegen.String("hello "), var]) self.assertCodeEqual( join.as_source_code(), """ String.concat [ "hello " , tmp ] """, )
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_case(self): scope = codegen.Scope() tmp = scope.reserve_name("tmp") case = codegen.Case(scope.variables[tmp]) branch1 = case.add_branch(codegen.String("x")) branch1.value = codegen.Number(1) branch2 = case.add_branch(codegen.String("y")) branch2.value = codegen.Number(2) branch3 = case.add_branch(codegen.Otherwise()) branch3.value = codegen.Number(3) case = codegen.simplify(case) self.assertCodeEqual( case.as_source_code(), """ case tmp of "x" -> 1 "y" -> 2 _ -> 3 """, )
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_record_update(self): rec = types.Record() rec.add_field("name", dtypes.String) rec.add_field("age", dtypes.Number) rec.add_field("height", dtypes.Number) scope = codegen.Scope() tmp = scope.reserve_name("tmp", type=rec) var = scope.variables[tmp] update = codegen.RecordUpdate(var, name=codegen.String("Fred"), age=codegen.Number(34)) self.assertCodeEqual( update.as_source_code(), """ { tmp | age = 34, name = "Fred" } """, )
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 dom_nodes_to_elm(nodes, expr_replacements, local_scope, compiler_env): # We have to structure this as a list of lists, then do a List.concat # at the end. In many cases the List.concat will disappear after # simplify. from elm_fluent import compiler items = [] for node in nodes: if isinstance(node, bs4.element.NavigableString): parts = interpolate_replacements(text_type(node), expr_replacements) for part in parts: if isinstance(part, string_types): items.append( HtmlList( [ local_scope.variables["Html.text"].apply( codegen.String(text_type(part)) ) ] ) ) else: val = compiler.compile_expr(part, local_scope, compiler_env) if val.type == html_output_type: # This is a list type, so simply append to our list of lists items.append(val) else: val = local_scope.variables["Html.text"].apply( compiler.Stringable(val, local_scope) ) items.append(HtmlList([val])) else: assert isinstance(node, bs4.element.Tag) tag_name = node.name.lower() static_attributes = [] for attr_name, attr_value in sorted(node.attrs.items()): if isinstance(attr_value, list): # Bs4 treats class attribute differently, returns a list, which we convert # back to a string here: attr_value = " ".join(attr_value) attr_value_parts = interpolate_replacements( attr_value, expr_replacements ) attr_output_parts = [] for part in attr_value_parts: if isinstance(part, string_types): attr_output_parts.append(codegen.String(text_type(part))) else: with compiler_env.modified(html_context=False): attr_output_parts.append( compiler.Stringable( compiler.compile_expr( part, local_scope, compiler_env ), local_scope, from_ftl_source=compiler.make_ftl_source( part, compiler_env ), ) ) attr_final_value = codegen.StringConcat(attr_output_parts) if attr_name in html_attributes.ATTRIBUTES: attr_constructor = local_scope.variables[ "Attributes.{0}".format(attr_name) ] else: attr_constructor = local_scope.variables[ "Attributes.attribute" ].apply(codegen.String(attr_name)) static_attributes.append(attr_constructor.apply(attr_final_value)) if compiler_env.dynamic_html_attributes: selectors_for_node = codegen.List( list( map( codegen.String, get_selectors_for_node(node, expr_replacements), ) ) ) dynamic_attributes = local_scope.variables[ "Fluent.selectAttributes" ].apply( local_scope.variables[compiler.ATTRS_ARG_NAME], selectors_for_node ) else: dynamic_attributes = codegen.List([]) attributes = codegen.ListConcat( [codegen.List(static_attributes), dynamic_attributes], dtypes.List.specialize(a=html.Attribute), ) sub_items = dom_nodes_to_elm( list(node.children), expr_replacements, local_scope, compiler_env ) if tag_name in html.ELEMENTS: node_constructor = local_scope.variables["Html.{0}".format(tag_name)] else: node_constructor = local_scope.variables["Html.node"].apply( codegen.String(tag_name) ) item = node_constructor.apply(attributes, sub_items) items.append(HtmlList([item])) return HtmlListConcat(items)
def test_string_join_one(self): join = codegen.StringConcat([codegen.String("hello")]) join = codegen.simplify(join) self.assertCodeEqual(join.as_source_code(), '"hello"')