mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-25 23:49:17 +00:00
Introducing a new pseudo-opcode is rarely an elegant solution.
This commit is contained in:
parent
dbbd99ffe5
commit
b7b28830d7
@ -5,6 +5,7 @@ History of SixtyPical
|
||||
----
|
||||
|
||||
* 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
|
||||
---
|
||||
|
@ -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
|
||||
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`
|
||||
|
@ -64,6 +64,14 @@ class Parser(object):
|
||||
if not isinstance(self.symbols[name].model.type, ExecutableType):
|
||||
raise SyntaxError('Illegal call of non-executable "%s"' % name)
|
||||
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)
|
||||
|
||||
@ -286,6 +294,15 @@ class Parser(object):
|
||||
self.scanner.expect(',')
|
||||
dest = self.indlocexpr()
|
||||
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"):
|
||||
self.scanner.expect("interrupts")
|
||||
self.scanner.expect("off")
|
||||
|
@ -356,6 +356,28 @@ A vector can name itself in its inputs, outputs, and trashes.
|
||||
| }
|
||||
= 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.
|
||||
|
||||
| routine foo {
|
||||
|
Loading…
Reference in New Issue
Block a user