Download tests/test_assembler.py from AEUPH/hdcstorage: direct link, hf CLI and curl.
- Browser
- Download file 4.93 kB
-
https://huggingface.co/AEUPH/hdcstorage/resolve/main/tests/test_assembler.py
- Command line
-
hf download hf://AEUPH/hdcstorage/tests/test_assembler.py
-
curl -L -o test_assembler.py https://huggingface.co/AEUPH/hdcstorage/resolve/main/tests/test_assembler.py
4.93 kB
| """Tests for the .hdcasm compiler.""" | |
| import os | |
| import sys | |
| import unittest | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from hdc.assembler import AsmError, assemble, roundtrip_report, split_operands # noqa: E402 | |
| D = 2000 | |
| class TestLabels(unittest.TestCase): | |
| def test_forward_and_backward(self): | |
| src = """ | |
| jmp done | |
| loop: | |
| nop | |
| jmp loop | |
| done: | |
| halt | |
| """ | |
| prog = assemble(src, d=D) | |
| self.assertEqual(prog.labels["loop"], 1) | |
| self.assertEqual(prog.labels["done"], 3) | |
| self.assertEqual(prog.listing[0].tgt, 3) | |
| self.assertEqual(prog.listing[2].tgt, 1) | |
| def test_numeric_target(self): | |
| prog = assemble("jmp @2\nnop\nhalt", d=D) | |
| self.assertEqual(prog.listing[0].tgt, 2) | |
| def test_duplicate_label_rejected(self): | |
| with self.assertRaises(AsmError): | |
| assemble("loop:\n nop\nloop:\n nop", d=D) | |
| def test_undefined_label_rejected(self): | |
| with self.assertRaises(AsmError): | |
| assemble("jmp nowhere", d=D) | |
| def test_label_on_directive_line(self): | |
| prog = assemble('here: .str greeting "hello"\n ini: nop\n halt', d=D) | |
| self.assertEqual(prog.labels["ini"], 0) | |
| self.assertEqual(len(prog.instrs), 2) | |
| class TestDirectives(unittest.TestCase): | |
| SRC = """ | |
| .name out | |
| .data tbl 42 | |
| .str hello "hi there" | |
| ldi R0, 1 | |
| store out, R0 | |
| prints "hi there" | |
| halt | |
| """ | |
| def test_data_directory_populates_image(self): | |
| prog = assemble(self.SRC, d=D) | |
| self.assertEqual(prog.data["tbl"], "int:42") | |
| self.assertEqual(prog.data["hello"], "str:hi there") | |
| self.assertEqual(prog.cell_names, ["hello", "out", "tbl"]) | |
| self.assertIn("hi there", prog.strings) | |
| self.assertIn(42, prog.literals) | |
| self.assertEqual(len(prog.instrs), 4) | |
| def test_install_writes_cells(self): | |
| from hdc.memory import HDCStorage | |
| prog = assemble(self.SRC, d=D) | |
| store = HDCStorage(d=D) | |
| names = prog.install(store) | |
| self.assertEqual(names, ["code/0", "code/1", "code/2", "code/3"]) | |
| for name in names: | |
| self.assertIn(name, store) | |
| self.assertNotEqual(store.read(name), 0) | |
| self.assertIn("out", store) | |
| self.assertIn("tbl", store) | |
| def test_unknown_directive_rejected(self): | |
| with self.assertRaises(AsmError): | |
| assemble(".frobnicate x", d=D) | |
| class TestRoundTrip(unittest.TestCase): | |
| SRC = """ | |
| .str hello "hdc storage" | |
| .data acc 0 | |
| start: | |
| ldi R0, 5 | |
| ldi R1, 37 | |
| add R2, R0, R1 | |
| out R2 | |
| bind R3, R0, R1 | |
| sim R4, R3, R0 | |
| out R4 | |
| prints hello | |
| store acc, R2 | |
| load R5, acc | |
| out R5 | |
| halt | |
| """ | |
| def test_every_cell_decodes_to_its_source_opcode(self): | |
| prog = assemble(self.SRC, d=D) | |
| report = roundtrip_report(prog) | |
| n = len(prog.instrs) | |
| self.assertIn("decode-back check: %d/%d cells round-trip" % (n, n), report) | |
| for i, line in enumerate(prog.source): | |
| opcode = line.text.split()[0].upper() | |
| self.assertEqual(prog.listing[i].op, opcode, msg="cell %d" % i) | |
| self.assertGreater(prog.listing[i].confidence, 0.15) | |
| def test_source_lines_are_instruction_lines_only(self): | |
| prog = assemble(self.SRC, d=D) | |
| self.assertEqual(len(prog.source), len(prog.instrs)) | |
| def test_listing_text_contains_confidence(self): | |
| prog = assemble(self.SRC, d=D) | |
| text = prog.listing_text() | |
| self.assertIn("conf", text) | |
| self.assertIn("start:", text) | |
| class TestErrors(unittest.TestCase): | |
| def test_wrong_operand_count(self): | |
| with self.assertRaises(AsmError): | |
| assemble("add R0, R1", d=D) | |
| def test_unknown_opcode(self): | |
| with self.assertRaises(AsmError): | |
| assemble("frob R0", d=D) | |
| def test_bad_register(self): | |
| with self.assertRaises(AsmError): | |
| assemble("ldi R99, 1", d=D) | |
| def test_bad_literal(self): | |
| with self.assertRaises(AsmError): | |
| assemble("ldi R0, banana", d=D) | |
| def test_unquoted_string(self): | |
| with self.assertRaises(AsmError): | |
| assemble("prints hello", d=D) | |
| class TestTokenizer(unittest.TestCase): | |
| def test_commas_inside_quotes_survive(self): | |
| self.assertEqual( | |
| split_operands('"a, b", R0'), ['"a, b"', "R0"] | |
| ) | |
| def test_empty(self): | |
| self.assertEqual(split_operands(" "), []) | |
| def test_comments_stripped(self): | |
| prog = assemble("ldi R0, 5 ; set five\n halt # done", d=D) | |
| self.assertEqual(len(prog.instrs), 2) | |
| self.assertEqual(prog.listing[0].imm, 5) | |
| if __name__ == "__main__": | |
| unittest.main() | |