mirror of
https://github.com/mnaberez/py65.git
synced 2025-01-01 11:29:32 +00:00
Show specific error messages when assembly fails
This commit is contained in:
parent
11a66ec69c
commit
ad31ed40a7
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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})
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user