1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-09 01:30:50 +00:00

Change how backpatching instructions is implemented.

This commit is contained in:
Chris Pressey 2017-12-12 13:54:35 +00:00
parent 19dd089a03
commit dbbd99ffe5
2 changed files with 19 additions and 24 deletions

View File

@ -46,6 +46,11 @@ Finish the little demo "game" where you can move a block around the screen with
the joystick (i.e. bring it up to par with the original demo game that was written
for SixtyPical)
### `copy` (to vectors) routines that are defined further down in the source code
We might have a graph of states that refer to each other and that want to `goto`
each other. Thus we need this. We have it for other things.
### Allow branches to diverge in what they touch
For example, if the routine inputs and outputs `foo`, and one branch of an `if`

View File

@ -23,33 +23,13 @@ class Parser(object):
self.symbols[token] = SymEntry(None, LocationRef(TYPE_BYTE, token))
for token in ('c', 'z', 'n', 'v'):
self.symbols[token] = SymEntry(None, LocationRef(TYPE_BIT, token))
self.backpatch_instrs = []
def lookup(self, name):
if name not in self.symbols:
raise SyntaxError('Undefined symbol "%s"' % name)
return self.symbols[name].model
def backpatch_call_labels(self, block):
"""Backpatches labels in call and goto instructions."""
if block is None:
return
for instr in block.instrs:
if instr.opcode == 'if':
self.backpatch_call_labels(instr.block1)
self.backpatch_call_labels(instr.block2)
elif instr.opcode == 'repeat':
self.backpatch_call_labels(instr.block)
elif instr.opcode == 'with-sei':
self.backpatch_call_labels(instr.block)
elif instr.opcode in ('call', 'goto'):
if isinstance(instr.location, basestring):
name = instr.location
if name not in self.symbols:
raise SyntaxError('Undefined routine "%s"' % name)
if not isinstance(self.symbols[name].model.type, ExecutableType):
raise SyntaxError('Illegal call of non-executable "%s"' % name)
instr.location = self.symbols[name].model
# --- grammar productions
def program(self):
@ -70,12 +50,21 @@ class Parser(object):
self.symbols[name] = SymEntry(routine, routine.location)
routines.append(routine)
self.scanner.check_type('EOF')
# now backpatch the executable types.
for defn in defns:
defn.location.backpatch_vector_labels(lambda w: self.lookup(w))
for routine in routines:
routine.location.backpatch_vector_labels(lambda w: self.lookup(w))
self.backpatch_call_labels(routine.block)
for instr in self.backpatch_instrs:
if instr.opcode in ('call', 'goto'):
name = instr.location
if name not in self.symbols:
raise SyntaxError('Undefined routine "%s"' % name)
if not isinstance(self.symbols[name].model.type, ExecutableType):
raise SyntaxError('Illegal call of non-executable "%s"' % name)
instr.location = self.symbols[name].model
return Program(defns=defns, routines=routines)
def defn(self):
@ -287,8 +276,9 @@ class Parser(object):
self.scanner.scan()
name = self.scanner.token
self.scanner.scan()
# this will be backpatched
return Instr(opcode=opcode, location=name, dest=None, src=None)
instr = Instr(opcode=opcode, location=name, dest=None, src=None)
self.backpatch_instrs.append(instr)
return instr
elif self.scanner.token in ("copy",):
opcode = self.scanner.token
self.scanner.scan()