1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-06-07 22:29:27 +00:00

Remove need for forward keyword in forward reference in copy.

This commit is contained in:
Chris Pressey 2018-02-12 15:59:20 +00:00
parent 08ec0e46a3
commit f6fa1ec7d2
6 changed files with 67 additions and 39 deletions

View File

@ -10,8 +10,9 @@ History of SixtyPical
* Implements the "union rule for trashes" when analyzing `if` blocks.
* Even if we `goto` another routine, we can't trash an output.
* `static` storage locations local to routines can now be defined within routines.
* Small grammar change that obviates the need for parentheses in the type expression
`vector (routine ...) table`.
* Small grammar changes that obviate:
* the need for parentheses in the type expression `vector (routine ...) table`#
* the need for `forward` in forward references in source of `copy` instruction
* Fixed bug where `trash` was not marking the location as being virtually altered.
0.11

View File

@ -67,7 +67,6 @@ is probably NP-complete. But doing it adeuqately is probably not that hard.
### And at some point...
* `const`s that can be used in defining the size of tables, etc.
* Remove the need for `forward` (lots of backpatching)
* Tests, and implementation, ensuring a routine can be assigned to a vector of "wider" type
* Check that the buffer being read or written to through pointer, appears in approporiate inputs or outputs set.
(Associate each pointer with the buffer it points into.)

View File

@ -249,7 +249,7 @@ routine init_game
repeat {
copy pos, actor_pos + y
copy word 40, actor_delta + y
copy forward enemy_logic, actor_logic + y
copy enemy_logic, actor_logic + y
st off, c
add pos, word 7
@ -261,7 +261,7 @@ routine init_game
ld y, 0
copy word 0, actor_pos + y
copy word 0, actor_delta + y
copy forward player_logic, actor_logic + y
copy player_logic, actor_logic + y
}
// ----------------------------------------------------------------
@ -401,7 +401,7 @@ define game_state_title_screen game_state_routine
if c {
call clear_screen
call init_game
copy forward game_state_play, dispatch_game_state
copy game_state_play, dispatch_game_state
}
goto save_cinv
@ -423,7 +423,7 @@ static byte save_x : 0
if c {
// Player died! Want no dead! Break out of the loop (this is a bit awkward.)
call clear_screen
copy forward game_state_game_over, dispatch_game_state
copy game_state_game_over, dispatch_game_state
ld x, 15
} else {
ld x, save_x

View File

@ -30,12 +30,18 @@ class Parser(object):
self.symbols[token] = SymEntry(None, LocationRef(TYPE_BIT, token))
self.backpatch_instrs = []
def lookup(self, name):
def soft_lookup(self, name):
if name in self.current_statics:
return self.current_statics[name].model
if name not in self.symbols:
if name in self.symbols:
return self.symbols[name].model
return None
def lookup(self, name):
model = self.soft_lookup(name)
if model is None:
raise SyntaxError('Undefined symbol "%s"' % name)
return self.symbols[name].model
return model
# --- grammar productions
@ -270,7 +276,7 @@ class Parser(object):
accum.append(self.locexpr())
return accum
def locexpr(self):
def locexpr(self, forward=False):
if self.scanner.token in ('on', 'off'):
loc = ConstantRef(TYPE_BIT, 1 if self.scanner.token == 'on' else 0)
self.scanner.scan()
@ -285,15 +291,21 @@ class Parser(object):
loc = ConstantRef(TYPE_WORD, int(self.scanner.token))
self.scanner.scan()
return loc
elif forward:
name = self.scanner.token
self.scanner.scan()
loc = self.soft_lookup(name)
if loc is not None:
return loc
else:
return name
else:
loc = self.lookup(self.scanner.token)
self.scanner.scan()
return loc
def indlocexpr(self):
if self.scanner.consume('forward'):
return self.label()
elif self.scanner.consume('['):
def indlocexpr(self, forward=False):
if self.scanner.consume('['):
loc = self.locexpr()
self.scanner.expect(']')
self.scanner.expect('+')
@ -303,11 +315,12 @@ class Parser(object):
loc = self.locexpr()
return AddressRef(loc)
else:
loc = self.locexpr()
index = None
if self.scanner.consume('+'):
index = self.locexpr()
loc = IndexedRef(loc, index)
loc = self.locexpr(forward=forward)
if not isinstance(loc, basestring):
index = None
if self.scanner.consume('+'):
index = self.locexpr()
loc = IndexedRef(loc, index)
return loc
def statics(self):
@ -392,7 +405,7 @@ class Parser(object):
elif self.scanner.token in ("copy",):
opcode = self.scanner.token
self.scanner.scan()
src = self.indlocexpr()
src = self.indlocexpr(forward=True)
self.scanner.expect(',')
dest = self.indlocexpr()
instr = Instr(opcode=opcode, dest=dest, src=src)

View File

@ -529,6 +529,36 @@ Copy routine to vector, inside an `interrupts off` block.
= $081A INX
= $081B RTS
Copy routine (by forward reference) to vector.
| vector routine
| inputs x
| outputs x
| trashes z, n
| bar
|
| routine main
| outputs bar
| trashes a, n, z
| {
| copy foo, bar
| }
|
| routine foo
| inputs x
| outputs x
| trashes z, n
| {
| inc x
| }
= $080D LDA #$18
= $080F STA $081A
= $0812 LDA #$08
= $0814 STA $081B
= $0817 RTS
= $0818 INX
= $0819 RTS
Copy word to word table and back, with both `x` and `y` as indexes.
| word one

View File

@ -408,8 +408,9 @@ 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*, it must be marked as such with the keyword `forward`.
A routine can be copied into a vector before the routine appears in the program.
This is known as a "forward reference". You are only allowed to make forward
references in the source of a `copy` instruction.
| vector routine
| inputs cinv, a
@ -425,22 +426,6 @@ A routine can be copied into a vector before the routine appears in the program,
| routine foo {
| ld a, 0
| }
? SyntaxError: Undefined symbol
| vector routine
| inputs cinv, a
| outputs cinv, x
| trashes a, x, z, n
| cinv @ 788
| routine main {
| with interrupts off {
| copy forward foo, cinv
| }
| call cinv
| }
| routine foo {
| ld a, 0
| }
= ok
goto.