def setUp(self): self.parser = AssemblyParser() self.parse = self.parser.parse
class TestParseInstructions(unittest.TestCase): def setUp(self): self.parser = AssemblyParser() self.parse = self.parser.parse def assertParses(self, given, expected): self.assertEquals(self.parse(given), [from_opcode(*expected[:3])] + expected[3:]) def assertEmpty(self, given): self.assertEquals(self.parse(given), []) def assertOp(self, given, expected): self.assertEquals(self.parser.opcode(given), expected) def test_parse_SET(self): self.assertOp("SET", 0x1) def test_parse_ADD(self): self.assertOp("ADD", 0x2) def test_parse_SUB(self): self.assertOp("SUB", 0x3) def test_parse_MUL(self): self.assertOp("MUL", 0x4) def test_parse_DIV(self): self.assertOp("DIV", 0x5) def test_parse_MOD(self): self.assertOp("MOD", 0x6) def test_parse_SHL(self): self.assertOp("SHL", 0x7) def test_parse_SHR(self): self.assertOp("SHR", 0x8) def test_parse_AND(self): self.assertOp("AND", 0x9) def test_parse_BOR(self): self.assertOp("BOR", 0xa) def test_parse_XOR(self): self.assertOp("XOR", 0xb) def test_parse_IFE(self): self.assertOp("IFE", 0xc) def test_parse_IFN(self): self.assertOp("IFN", 0xd) def test_parse_IFG(self): self.assertOp("IFG", 0xe) def test_parse_IFB(self): self.assertOp("IFB", 0xf) def test_lowercase_ops(self): self.assertOp("ifb", 0xf) self.assertOp("shr", 0x8) self.assertOp("and", 0x9) self.assertOp("bor", 0xa) self.assertOp("XOR", 0xb) def test_instruction(self): self.assertParses("SET A, 0x30", [0x1, 0x0, 0x1f, 0x30]) self.assertParses("SET A 0x30", [0x1, 0x0, 0x1f, 0x30]) self.assertParses("SET I, 10", [0x1, 0x06, 0x2a]) self.assertParses("SUB A, [0x1000]", [0x3, 0x0, 0x1e, 0x1000]) self.assertParses("IFN A, 0x10", [0xd, 0x0, 0x30]) def test_instruction_spaces(self): self.assertParses("SET A,0x30", [0x1, 0x0, 0x1f, 0x30]) def test_spaces_in_brackets(self): a = self.parser.parse("SET A, [0x30+A]") b = self.parser.parse("SET A, [0x30 + A]") self.assertEquals(a, b) c = self.parser.parse("SET [0x30+A], A") d = self.parser.parse("SET [0x30 + A], A") self.assertEquals(c, d) e = self.parser.parse("SET [0x30+A], [0x0+J]") f = self.parser.parse("SET [0x30 + A], [0x0 + J]") self.assertEquals(e, f) def test_spaces_in_brackets_nonbasic(self): a = self.parser.parse("JSR [0x30+A]") b = self.parser.parse("JSR [0x30 + A]") self.assertEquals(a, b) def test_nonbasic_instruction(self): self.assertParses("JSR, 0x0002", [0x0, 0x01, 0x22]) self.assertParses("JSR 0x0002", [0x0, 0x01, 0x22]) def test_comments(self): self.assertParses("SET I, 10; comment", [0x1, 0x06, 0x2a]) self.assertParses("SET I, 10;comment", [0x1, 0x06, 0x2a]) self.assertParses("SET I, 10 ;comment", [0x1, 0x06, 0x2a]) self.assertParses("SET I, 10 ; comment", [0x1, 0x06, 0x2a]) def test_ignores(self): self.assertParses(" SET A, 0x30 ", [0x1, 0x0, 0x1f, 0x30]) self.assertParses("\t SET I, 10 ; hi", [0x1, 0x06, 0x2a]) self.assertEmpty("; hi comment") self.assertEmpty(" ;comment") self.assertEmpty("\t ") def test_labels(self): self.assertParses("SET PC, label", [0x1, 0x1c, 0x1f, "label"]) self.assertParses("SET A, label", [0x1, 0x00, 0x1f, "label"]) self.assertParses("JSR testsub", [0x0, 0x01, 0x1f, "testsub"]) def test_parse_text(self): lines = """ SET A, 0x30 ; SET [0x1000], 0x20 ; wooh , comment SUB A, [0x1000] IFN A, 0x10 """.split("\n") self.assertEqual(self.parser.parse_tree(lines), [0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d]) def test_label_definition(self): instruction = self.parser.parse(":start set A, 0x30") self.assertIn(("start", instruction), self.parser.labels) instruction = self.parser.parse("set A, 0x30") self.assertEquals(instruction, [0x7c01, 0x0030]) def test_tricky_labels(self): instruction = self.parser.parse_tree([":set set set set"]) # should be the same as set 0, 0. self.assertEquals(instruction, [0x7df1, 0, 0]) def test_parse_text_with_labels(self): lines = """ SET A, 0x30 ; SET [0x1000], 0x20 ; wooh , comment SUB A, [0x1000] IFN A, 0x10 :crash SET PC, crash """.split("\n") self.assertEqual(self.parser.parse_tree(lines), [0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d, 0x7dc1, 0x0008]) def test_dat(self): assembly = "dat 0x30" self.assertEqual(self.parser.parse(assembly), [0x0030]) def test_dat_multiple(self): assembly = "dat 0x30, 0x48" self.assertEqual(self.parser.parse(assembly), [0x0030, 0x048]) assembly = "dat 0x30,0x48" self.assertEqual(self.parser.parse(assembly), [0x0030, 0x048]) assembly = "dat 0x30 0x48, 1" self.assertEqual(self.parser.parse(assembly), [0x0030, 0x048, 1]) def test_dat_text(self): assembly = ["dat 0x30, 0x48"] self.assertEqual(self.parser.parse_tree(assembly), [0x0030, 0x048]) def test_dat_label(self): assembly = ["dat 0x30, label"] self.assertEqual(self.parser.parse_tree(assembly), [0x0030, "label"]) def test_dat_string(self): assembly = ["dat \"ab\""] self.assertEqual(self.parser.parse_tree(assembly), [ord("a"), ord("b"),]) assembly = ["dat \"a\", 0"] self.assertEqual(self.parser.parse_tree(assembly), [ord("a"), 0]) assembly = ["dat 0, \"b\""] self.assertEqual(self.parser.parse_tree(assembly), [0, ord("b")]) assembly = ["dat 0, 'b'"] self.assertEqual(self.parser.parse_tree(assembly), [0, ord("b")]) def test_dat_string_quotes(self): assembly = [r'dat "a\""'] self.assertEqual(self.parser.parse_tree(assembly), [ord("a"), ord('"'),]) def test_data_label(self): assembly = [':data dat data'] self.assertEqual(self.parser.parse_tree(assembly), [0]) @unittest.expectedFailure def test_dat_string_commas(self): assembly = [r'dat "a,b"'] self.assertEqual(self.parser.parse_tree(assembly), [ord("a"), ord(","), ord('b'),]) @unittest.expectedFailure def test_dat_string_spaces(self): assembly = [r'dat "a b"'] self.assertEqual(self.parser.parse_tree(assembly), [ord("a"), ord(" "), ord('b'),]) @unittest.expectedFailure def test_label_plus_literal(self): lines = ":start set PC, start + 0xffff" self.assertEqual(self.parser.parse_tree([lines]), [0x7dc1, 0xffff]) def test_label_pointer(self): lines = ":start set PC, [start]" self.assertEqual(self.parser.parse_tree([lines]), [0x79c1, 0x0000]) @unittest.expectedFailure def test_label_plus_literal_pointer(self): lines = ":start set PC, [start + 0xffff]" self.assertEqual(self.parser.parse_tree([lines]), [0x79c1, 0xffff]) def test_label_plus_register(self): lines = ":start set PC, [start + A]" self.assertEqual(self.parser.parse_tree([lines]), [0x41c1, 0x0000]) def test_parse_lots_of_text(self): "Make sure the parser doesn't choke." lines = """ ; Try some basic stuff SET A, 0x30 ; 7c01 0030 SET [0x1000], 0x20 ; 7de1 1000 0020 SUB A, [0x1000] ; 7803 1000 IFN A, 0x10 ; c00d SET PC, crash ; 7dc1 001a [*] ; Do a loopy thing SET I, 10 ; a861 SET A, 0x2000 ; 7c01 2000 :loop SET [0x2000+I], [A] ; 2161 2000 SUB I, 1 ; 8463 IFN I, 0 ; 806d SET PC, loop ; 7dc1 000d [*] ; Call a subroutine SET X, 0x4 ; 9031 JSR testsub ; 7c10 0018 [*] SET PC, crash ; 7dc1 001a [*] :testsub SHL X, 4 ; 9037 SET PC, POP ; 61c1 ; Hang forever. X should now be 0x40 if everything went right. :crash SET PC, crash ; 7dc1 001a [*] """.split("\n") self.parser.parse_tree(lines)