From f6fa1ec7d29f1c267cacaaccc092dc668d91f7fe Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Mon, 12 Feb 2018 15:59:20 +0000 Subject: [PATCH] Remove need for `forward` keyword in forward reference in `copy`. --- HISTORY.md | 5 ++-- README.md | 1 - eg/proto-game.60p | 8 +++---- src/sixtypical/parser.py | 41 ++++++++++++++++++++++----------- tests/SixtyPical Compilation.md | 30 ++++++++++++++++++++++++ tests/SixtyPical Syntax.md | 21 +++-------------- 6 files changed, 67 insertions(+), 39 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7810c0e..4bed032 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -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 diff --git a/README.md b/README.md index 578656e..38aca04 100644 --- a/README.md +++ b/README.md @@ -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.) diff --git a/eg/proto-game.60p b/eg/proto-game.60p index b644eeb..7ce80de 100644 --- a/eg/proto-game.60p +++ b/eg/proto-game.60p @@ -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 diff --git a/src/sixtypical/parser.py b/src/sixtypical/parser.py index ce327db..d7f5cd4 100644 --- a/src/sixtypical/parser.py +++ b/src/sixtypical/parser.py @@ -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) diff --git a/tests/SixtyPical Compilation.md b/tests/SixtyPical Compilation.md index ca4102a..831b94e 100644 --- a/tests/SixtyPical Compilation.md +++ b/tests/SixtyPical Compilation.md @@ -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 diff --git a/tests/SixtyPical Syntax.md b/tests/SixtyPical Syntax.md index c217c41..1a3b5b4 100644 --- a/tests/SixtyPical Syntax.md +++ b/tests/SixtyPical Syntax.md @@ -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.