1
0
mirror of https://github.com/mnaberez/py65.git synced 2024-06-06 20:29:34 +00:00

Show specific error messages when assembly fails

This commit is contained in:
Mike Naberezny 2012-11-18 17:34:48 -08:00
parent 11a66ec69c
commit ad31ed40a7
5 changed files with 56 additions and 40 deletions

View File

@ -1,5 +1,8 @@
0.14 *Next Release*
- Assembling now detects syntax errors, overflows, and bad labels
separately and shows specific error messages.
0.13 (2012-11-15)
- Fixed a bug where negative numbers could be entered

View File

@ -268,28 +268,30 @@ class Monitor(cmd.Cmd):
return self.help_EOF()
def do_assemble(self, args):
split = args.split(None, 1)
if len(split) != 2:
splitted = args.split(None, 1)
if len(splitted) != 2:
return self._interactive_assemble(args)
start, statement = split
statement = splitted[1]
try:
start = self._address_parser.number(start)
except KeyError:
self._output("Bad label: %s" % start)
return
start = self._address_parser.number(splitted[0])
bytes = self._assembler.assemble(statement, start)
bytes = self._assembler.assemble(statement, start)
if bytes is None:
self._output("Assemble failed: %s" % statement)
else:
end = start + len(bytes)
self._mpu.memory[start:end] = bytes
self.do_disassemble((self.addrFmt+":"+self.addrFmt) % (start, end))
except KeyError:
self._output("Bad label: %s" % args)
except OverflowError:
self._output("Overflow error: %s" % args)
except SyntaxError:
self._output("Syntax error: %s" % statement)
def help_assemble(self):
self._output("assemble <address> <statement>")
self._output("Assemble a statement at the address.")
self._output("assemble <address> <statement>\t"
"Assemble a statement at the address.")
self._output("assemble <address>\t\t"
"Start interactive assembly at the address.")
def _interactive_assemble(self, args):
if args == '':
@ -298,35 +300,38 @@ class Monitor(cmd.Cmd):
try:
start = self._address_parser.number(args)
except KeyError:
self._output("Bad label: %s" % start)
self._output("Bad label: %s" % args)
return
assembling = True
while assembling:
while True:
prompt = "\r$" + ( self.addrFmt % start ) + " " + (" " * (1 + self.byteWidth/4) * 3)
line = console.line_input(prompt,
stdin=self.stdin, stdout=self.stdout)
if not line:
if not line.strip():
self.stdout.write("\n")
return
# assemble into memory
bytes = self._assembler.assemble(line, pc=start)
if bytes is None:
self.stdout.write("\r$" + (self.addrFmt % start) + " ???\n")
continue
end = start + len(bytes)
self._mpu.memory[start:end] = bytes
try:
bytes = self._assembler.assemble(line, pc=start)
# print disassembly
bytes, disasm = self._disassembler.instruction_at(start)
disassembly = self._format_disassembly(start, bytes, disasm)
self.stdout.write("\r" + (' ' * (len(prompt+line) + 5) ) + "\r")
self.stdout.write(disassembly + "\n")
end = start + len(bytes)
self._mpu.memory[start:end] = bytes
start += bytes
# print disassembly
bytes, disasm = self._disassembler.instruction_at(start)
disassembly = self._format_disassembly(start, bytes, disasm)
self.stdout.write("\r" + (' ' * (len(prompt+line) + 5) ) + "\r")
self.stdout.write(disassembly + "\n")
start += bytes
except KeyError:
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Label\n")
except OverflowError:
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Overflow\n")
except SyntaxError:
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Syntax\n")
def do_disassemble(self, args):
split = shlex.split(args)

View File

@ -114,15 +114,23 @@ class MonitorTests(unittest.TestCase):
mon.do_assemble('nonexistant rts')
out = stdout.getvalue()
self.assertEqual("Bad label: nonexistant\n", out)
self.assertEqual("Bad label: nonexistant rts\n", out)
def test_do_assemble_shows_bad_statement_error(self):
def test_do_assemble_shows_bad_syntax_error(self):
stdout = StringIO()
mon = Monitor(stdout=stdout)
mon.do_assemble('c000 foo')
out = stdout.getvalue()
self.assertEqual("Assemble failed: foo\n", out)
self.assertEqual("Syntax error: foo\n", out)
def test_do_assemble_shows_overflow_error(self):
stdout = StringIO()
mon = Monitor(stdout=stdout)
mon.do_assemble('c000 lda #$fff')
out = stdout.getvalue()
self.assertEqual("Overflow error: c000 lda #$fff\n", out)
def test_do_assemble_passes_addr_for_relative_branch_calc(self):
stdout = StringIO()
@ -138,7 +146,7 @@ class MonitorTests(unittest.TestCase):
mon.do_assemble("-1 lda #$ab")
out = stdout.getvalue()
self.assertEqual("$0000 a9 ab LDA #$ab\n", out)
self.assertEqual("Overflow error: -1 lda #$ab\n", out)
def test_help_assemble(self):
stdout = StringIO()

View File

@ -108,18 +108,18 @@ class AddressParserTests(unittest.TestCase):
def test_number_constrains_address_at_zero_or_above(self):
parser = AddressParser()
self.assertEqual(0x0000, parser.number('-1'))
self.assertRaises(OverflowError, parser.number, '-1')
def test_number_constrains_address_at_maxwidth_16(self):
parser = AddressParser()
parser.labels = {'foo': 0xFFFF}
self.assertEqual(0xFFFF, parser.number('foo+5'))
self.assertRaises(OverflowError, parser.number, 'foo+5')
def test_number_constrains_address_at_maxwidth_24(self):
parser = AddressParser()
parser.maxwidth = 24
parser.labels = {'foo': 0xFFFFFF}
self.assertEqual(0xFFFFFF, parser.number('foo+5'))
self.assertRaises(OverflowError, parser.number, 'foo+5')
def test_label_for_returns_label(self):
parser = AddressParser(labels={'chrout':0xFFD2})

View File

@ -93,7 +93,7 @@ class AddressParser(object):
return (start, end)
def _constrain(self, address):
"""Constrains a number to be within the address range"""
address = max(address, 0)
address = min(address, self._maxaddr)
'''Raises OverflowError if the address is illegal'''
if address < 0 or address > self._maxaddr:
raise OverflowError(address)
return address