def test_fun_call_empty(): a = parse("let a: u8 = foo()") assert a.select("toplevels", "stmt", "value") == [ ast.AstNode("call", { "target": ast.AstNode("identifier", {"name": "foo"}), "args": None }) ]
def test_assign(): a = parse("fun foo() a = 7 endfun") assert a.select("toplevels", "stmt", "body", "stmt") == [ ast.AstNode( "set", { "lvalue": ast.AstNode("identifier", {"name": "a"}), "rvalue": ast.AstNode("numeric", {"value": 7}), }, ) ]
def test_let_without_storage_class(): a = parse("let a: u8 = 7") assert a.select("toplevels", "stmt") == [ ast.AstNode( "let", { "name": "a", "type": "u8", "storage": None, "value": ast.AstNode("numeric", {"value": 7}), }, ) ]
def test_sign(): a = parse("constant x: u8 = -1 + 2") assert a.select("toplevels", "stmt", "value") == [ ast.AstNode( "add", { "lhs": ast.AstNode("negate", {"value": ast.AstNode("numeric", {"value": 1})}), "rhs": ast.AstNode("numeric", {"value": 2}), }, ) ]
def test_fun_call_one(): a = parse("let a: u8 = foo(7)") assert a.select("toplevels", "stmt", "value") == [ ast.AstNode( "call", { "target": ast.AstNode("identifier", {"name": "foo"}), "args": ast.AstNode.make_sequence( "alist", "arg", [ast.AstNode("numeric", {"value": 7})]), }, ) ]
def test_complex_type(): a = parse("let a: &u8 = 0") assert a.select("toplevels", "stmt") == [ ast.AstNode( "let", { "name": "a", "storage": None, "type": ast.AstNode("type_ref", { "storage": None, "type": "u8" }), "value": ast.AstNode("numeric", {"value": 0}), }, ) ]
def exit_unscoped_node(self, t): # this would probably be more efficient if we could use preconditions # somehow? assume(self.frames[-1].t == t) frame = self.frames.pop() node = self.transform.transform_exit(t, frame.node) assert frame.orig == ast.AstNode(t) assert "known_names" not in node.attrs
def test_assemble_lda_imm_too_wide(): with pytest.raises(asm.AssemblyError): assemble( asm.lda( ast.AstNode("immediate_storage", attrs={"value": 0xCAFE, "width": 2}), None, ) )
def test_assemble_sta_abs_too_wide(): with pytest.raises(asm.AssemblyError): assemble( asm.sta( ast.AstNode("absolute_storage", attrs={"address": 0xBEEF, "width": 2}), None, ) )
def test_nested_parentheses(): a = parse("constant x: u8 = ((1 + 2) / 3) + 4") assert a.select("toplevels", "stmt", "value") == [ ast.AstNode( "add", { "lhs": ast.AstNode( "div", { "lhs": ast.AstNode( "add", { "lhs": ast.AstNode("numeric", {"value": 1}), "rhs": ast.AstNode("numeric", {"value": 2}), }, ), "rhs": ast.AstNode("numeric", {"value": 3}), }, ), "rhs": ast.AstNode("numeric", {"value": 4}), }, ) ]
def test_string_multiline(): a = parse(""" let a: [u8; 5] = "this is a very long string" """) assert a.select("toplevels", "stmt", "value") == [ ast.AstNode("string", {"value": "this is a\nvery long\nstring"}) ]
def test_assemble_lda_imm(): assert ( assemble( asm.lda( ast.AstNode("immediate_storage", attrs={"value": 0x42, "width": 1}), None, ) ) == b"\xa9\x42" )
def test_fun_def_void_empty(): a = parse("fun foo() endfun") assert a.select("toplevels", "stmt") == [ ast.AstNode("fun", { "name": "foo", "args": None, "return": None, "body": None }) ]
def test_assemble_jmp_abs(): assert ( assemble( asm.jmp( ast.AstNode("absolute_storage", attrs={"address": 0xBEEF, "width": 0}), None, ) ) == b"\x4c\xef\xbe" )
def test_associativity(): a = parse("constant x: u8 = 1 + 2 * 3") assert a.select("toplevels", "stmt", "value") == [ ast.AstNode( "add", { "lhs": ast.AstNode("numeric", {"value": 1}), "rhs": ast.AstNode( "mul", { "lhs": ast.AstNode("numeric", {"value": 2}), "rhs": ast.AstNode("numeric", {"value": 3}), }, ), }, ) ]
def test_assemble_sta_abs(): assert ( assemble( asm.sta( ast.AstNode("absolute_storage", attrs={"address": 0xBEEF, "width": 1}), None, ) ) == b"\x8d\xef\xbe" )
def test_parentheses_with_sign(): a = parse("constant x: u8 = -(1 + 2)") e = a.select("toplevels", "stmt", "value")[0] assert e.t == "negate" assert e.attrs["value"].t == "add" assert a.select("toplevels", "stmt", "value") == [ ast.AstNode( "negate", { "value": ast.AstNode( "add", { "lhs": ast.AstNode("numeric", {"value": 1}), "rhs": ast.AstNode("numeric", {"value": 2}), }, ) }, ) ]
def test_fun_call_many(): a = parse('let a: u8 = foo(7, "hello")') assert a.select("toplevels", "stmt", "value") == [ ast.AstNode( "call", { "target": ast.AstNode("identifier", {"name": "foo"}), "args": ast.AstNode.make_sequence( "alist", "arg", [ ast.AstNode("numeric", {"value": 7}), ast.AstNode("string", {"value": "hello"}), ], ), }, ) ]
def test_member_access(): a = parse("let a: u8 = foo.bar") assert a.select("toplevels", "stmt") == [ ast.AstNode( "let", { "name": "a", "type": "u8", "storage": None, "value": ast.AstNode( "member_access", { "namespace": ast.AstNode("identifier", {"name": "foo"}), "member": "bar", }, ), }, ) ]
def test_flatten_symbol(): assert flatten( ast.AstNode( "unit", { "toplevels": ast.AstNode.make_sequence( "toplevel", "stmt", [ ast.AstNode( "fun", attrs={ "name": "meaning-of-life", "type": types.FunctionType(types.u8), "body": ast.AstNode.make_sequence( "block", "stmt", [ ast.AstNode( "asmrun", attrs={"bin": b"\xa9\x42"} ), ast.AstNode("asmrun", attrs={"bin": b"\x60"}), ], ), }, ) ], ) }, ) ) == ast.AstNode( "unit", { "toplevels": ast.AstNode.make_sequence( "toplevel", "stmt", [ ast.AstNode( "fun_symbol", attrs={ "name": "meaning-of-life", "type": types.FunctionType(types.u8), "text": b"\xa9\x42\x60", }, ) ], ) }, )
def test_identifiers(name0, name): name = name0 + name a = parse(f"let a: u8 = {name}") assert a.select("toplevels", "stmt", "value") == [ast.AstNode("identifier", {"name": name})]
def test_numeric_bin_valid(n): a = parse(f"let a: u8 = 0b{n:b}") assert a.select("toplevels", "stmt", "value") == [ast.AstNode("numeric", {"value": n})]
def test_string_literal_with_space_after(): a = parse('let a: [u8; 5] = "this is a string" ') assert a.select("toplevels", "stmt", "value") == [ ast.AstNode("string", {"value": "this is a string"}) ]
def test_string_escaped(): a = parse(r'let a: [u8; 5] = "this is a \"string"') assert a.select("toplevels", "stmt", "value") == [ ast.AstNode("string", {"value": 'this is a "string'}) ]
def test_use(): a = parse("use mem") assert a.select("toplevels", "stmt") == [ast.AstNode("use", {"name": "mem"})]
def enter_unscoped_node(self, t): orig = ast.AstNode(t) node = self.transform.transform_enter(t, orig) self.frames.append(Frame(t, node, orig, None))