diff --git a/.gitignore b/.gitignore index 2c6ddfd..6559e83 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ bundles dist **/*.egg-info .vscode +.venv diff --git a/adafruit_pioasm.py b/adafruit_pioasm.py index 96fb8dd..07137fe 100644 --- a/adafruit_pioasm.py +++ b/adafruit_pioasm.py @@ -103,7 +103,12 @@ def assemble(text_program): raise SyntaxError(f"Invalid jmp target {repr(target)}") if len(instruction) > 2: - assembled[-1] |= CONDITIONS.index(instruction[1]) << 5 + try: + assembled[-1] |= CONDITIONS.index(instruction[1]) << 5 + except ValueError as exc: + raise ValueError( + f"Invalid jmp condition '{instruction[1]}'" + ) from exc elif instruction[0] == "wait": # instr delay p sr index @@ -151,7 +156,10 @@ def assemble(text_program): source = instruction[-1] source_split = mov_splitter(source) if len(source_split) == 1: - assembled[-1] |= MOV_SOURCES.index(source) + try: + assembled[-1] |= MOV_SOURCES.index(source) + except ValueError as exc: + raise ValueError(f"Invalid mov source '{source}'") from exc else: assembled[-1] |= MOV_SOURCES.index(source_split[1]) if source[:1] == "!": @@ -183,7 +191,10 @@ def assemble(text_program): elif instruction[0] == "set": # instr delay dst data assembled.append(0b111_00000_000_00000) - assembled[-1] |= SET_DESTINATIONS.index(instruction[1]) << 5 + try: + assembled[-1] |= SET_DESTINATIONS.index(instruction[1]) << 5 + except ValueError as exc: + raise ValueError(f"Invalid set destination '{instruction[1]}'") from exc value = int(instruction[-1]) if not 0 <= value <= 31: raise RuntimeError("Set value out of range") diff --git a/tests/testpioasm.py b/tests/testpioasm.py index a15d01c..3ef3be5 100644 --- a/tests/testpioasm.py +++ b/tests/testpioasm.py @@ -29,8 +29,11 @@ def assertAssemblesTo(self, source, expected): f"Assembling {source!r}: Expected {expected_bin}, got {actual_bin}", ) - def assertAssemblyFails(self, source): - self.assertRaises(RuntimeError, adafruit_pioasm.assemble, source) + def assertAssemblyFails(self, source, match=None, errtype=RuntimeError): + if match: + self.assertRaisesRegex(errtype, match, adafruit_pioasm.assemble, source) + else: + self.assertRaises(errtype, adafruit_pioasm.assemble, source) def testNonsense(self): self.assertAssemblyFails("nope") @@ -52,6 +55,18 @@ def testSidesetOpt(self): ) self.assertAssemblesTo(".side_set 1 opt\nnop [1]", [0b101_00001_010_00_010]) + def testMov(self): + # non happy path + self.assertAssemblyFails( + "mov x, blah", match="Invalid mov source 'blah'", errtype=ValueError + ) + + def testSet(self): + # non happy path + self.assertAssemblyFails( + "set isr, 1", match="Invalid set destination 'isr'", errtype=ValueError + ) + def testJmp(self): self.assertAssemblesTo("l:\njmp l", [0b000_00000_000_00000]) self.assertAssemblesTo("l:\njmp 7", [0b000_00000_000_00111]) @@ -63,6 +78,10 @@ def testJmp(self): self.assertAssemblesTo("jmp x!=y, l\nl:", [0b000_00000_101_00001]) self.assertAssemblesTo("jmp pin, l\nl:", [0b000_00000_110_00001]) self.assertAssemblesTo("jmp !osre, l\nl:", [0b000_00000_111_00001]) + # non happy path + self.assertAssemblyFails( + "jmp x--., l\nl:", match="Invalid jmp condition 'x--.'", errtype=ValueError + ) def testWait(self): self.assertAssemblesTo("wait 0 gpio 0", [0b001_00000_0_00_00000])