1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-27 13:29:03 +00:00

Introducing a new pseudo-opcode is rarely an elegant solution.

This commit is contained in:
Chris Pressey 2017-12-12 14:09:17 +00:00
parent dbbd99ffe5
commit b7b28830d7
4 changed files with 40 additions and 5 deletions

View File

@ -5,6 +5,7 @@ History of SixtyPical
---- ----
* Can `call` and `goto` routines that are defined further down in the source code. * Can `call` and `goto` routines that are defined further down in the source code.
* `assign`, a form of `copy` that can copy (to a vector) a routine that is defined further down.
0.9 0.9
--- ---

View File

@ -46,11 +46,6 @@ 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

@ -64,6 +64,14 @@ class Parser(object):
if not isinstance(self.symbols[name].model.type, ExecutableType): if not isinstance(self.symbols[name].model.type, ExecutableType):
raise SyntaxError('Illegal call of non-executable "%s"' % name) raise SyntaxError('Illegal call of non-executable "%s"' % name)
instr.location = self.symbols[name].model instr.location = self.symbols[name].model
if instr.opcode in ('assign',):
name = instr.src
if name not in self.symbols:
raise SyntaxError('Undefined routine "%s"' % name)
if not isinstance(self.symbols[name].model.type, ExecutableType):
raise SyntaxError('Illegal assign of non-executable "%s"' % name)
instr.src = self.symbols[name].model
instr.opcode = 'copy'
return Program(defns=defns, routines=routines) return Program(defns=defns, routines=routines)
@ -286,6 +294,15 @@ class Parser(object):
self.scanner.expect(',') self.scanner.expect(',')
dest = self.indlocexpr() dest = self.indlocexpr()
return Instr(opcode=opcode, dest=dest, src=src) return Instr(opcode=opcode, dest=dest, src=src)
elif self.scanner.token == 'assign':
opcode = self.scanner.token
self.scanner.scan()
src = self.label()
self.scanner.expect(',')
dest = self.indlocexpr()
instr = Instr(opcode=opcode, dest=dest, src=src)
self.backpatch_instrs.append(instr)
return instr
elif self.scanner.consume("with"): elif self.scanner.consume("with"):
self.scanner.expect("interrupts") self.scanner.expect("interrupts")
self.scanner.expect("off") self.scanner.expect("off")

View File

@ -356,6 +356,28 @@ A vector can name itself in its inputs, outputs, and trashes.
| } | }
= ok = ok
A routine can be copied into a vector before the routine appears in the program.
*However*, in order to do this currently, one needs to use the special opcode
form `assign`, which is equivalent to `copy` except that the routine need not
have already appeared in the program.
| vector cinv
| inputs cinv, a
| outputs cinv, x
| trashes a, x, z, n
| @ 788
|
| routine main {
| with interrupts off {
| assign foo, cinv
| }
| call cinv
| }
| routine foo {
| ld a, 0
| }
= ok
goto. goto.
| routine foo { | routine foo {