1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-08-10 06:24:56 +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 the joystick (i.e. bring it up to par with the original demo game that was written
for SixtyPical) 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 ### Allow branches to diverge in what they touch
For example, if the routine inputs and outputs `foo`, and one branch of an `if` 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)) self.symbols[token] = SymEntry(None, LocationRef(TYPE_BYTE, token))
for token in ('c', 'z', 'n', 'v'): for token in ('c', 'z', 'n', 'v'):
self.symbols[token] = SymEntry(None, LocationRef(TYPE_BIT, token)) self.symbols[token] = SymEntry(None, LocationRef(TYPE_BIT, token))
self.backpatch_instrs = []
def lookup(self, name): def lookup(self, name):
if name not in self.symbols: if name not in self.symbols:
raise SyntaxError('Undefined symbol "%s"' % name) raise SyntaxError('Undefined symbol "%s"' % name)
return self.symbols[name].model 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 # --- grammar productions
def program(self): def program(self):
@@ -70,12 +50,21 @@ class Parser(object):
self.symbols[name] = SymEntry(routine, routine.location) self.symbols[name] = SymEntry(routine, routine.location)
routines.append(routine) routines.append(routine)
self.scanner.check_type('EOF') self.scanner.check_type('EOF')
# now backpatch the executable types. # now backpatch the executable types.
for defn in defns: for defn in defns:
defn.location.backpatch_vector_labels(lambda w: self.lookup(w)) defn.location.backpatch_vector_labels(lambda w: self.lookup(w))
for routine in routines: for routine in routines:
routine.location.backpatch_vector_labels(lambda w: self.lookup(w)) 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) return Program(defns=defns, routines=routines)
def defn(self): def defn(self):
@@ -287,8 +276,9 @@ class Parser(object):
self.scanner.scan() self.scanner.scan()
name = self.scanner.token name = self.scanner.token
self.scanner.scan() self.scanner.scan()
# this will be backpatched instr = Instr(opcode=opcode, location=name, dest=None, src=None)
return Instr(opcode=opcode, location=name, dest=None, src=None) self.backpatch_instrs.append(instr)
return instr
elif self.scanner.token in ("copy",): elif self.scanner.token in ("copy",):
opcode = self.scanner.token opcode = self.scanner.token
self.scanner.scan() self.scanner.scan()