mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-25 23:49:17 +00:00
Allow vectors to be decorated with inputs/outputs/trashes; test.
This commit is contained in:
parent
a12a44eadb
commit
f0b8942aa1
@ -33,10 +33,8 @@ TODO
|
|||||||
|
|
||||||
For 0.6:
|
For 0.6:
|
||||||
|
|
||||||
* `interrupt` routines.
|
* declared `inputs` `outputs` `trashes` on the `vector` type.
|
||||||
* `goto` (tail call).
|
* `goto` (tail call) a routine or a vector.
|
||||||
* `vector` type... with declared `inputs` `outputs` `trashes`?
|
|
||||||
* `copy` instruction... that can copy a constant to a user-def mem loc.
|
|
||||||
* A more involved demo for the C64 — one that sets up an interrupt.
|
* A more involved demo for the C64 — one that sets up an interrupt.
|
||||||
|
|
||||||
For 0.7:
|
For 0.7:
|
||||||
@ -48,8 +46,10 @@ For 0.7:
|
|||||||
|
|
||||||
At some point...
|
At some point...
|
||||||
|
|
||||||
|
* `interrupt` routines.
|
||||||
* add line number (or at least routine name) to error messages.
|
* add line number (or at least routine name) to error messages.
|
||||||
* 6502-mnemonic aliases (`sec`, `clc`)
|
* 6502-mnemonic aliases (`sec`, `clc`)
|
||||||
* other handy aliases (`eq` for `z`, etc.)
|
* other handy aliases (`eq` for `z`, etc.)
|
||||||
|
* have `copy` instruction able to copy a constant to a user-def mem loc, etc.
|
||||||
* add absolute addressing in shl/shr, absolute-indexed for add, sub, etc.
|
* add absolute addressing in shl/shr, absolute-indexed for add, sub, etc.
|
||||||
* check and disallow recursion.
|
* check and disallow recursion.
|
||||||
|
@ -83,6 +83,17 @@ A location in memory may be given explicitly on a user-defined memory location.
|
|||||||
|
|
||||||
byte table screen @ 1024
|
byte table screen @ 1024
|
||||||
|
|
||||||
|
A user-defined vector memory location is decorated with READS and WRITES lists
|
||||||
|
like a routine (see below), and it may only hold addresses of routines which
|
||||||
|
are compatible. (Meaning, the routine's inputs (resp. outputs, trashes)
|
||||||
|
must be a subset of the vector's inputs (resp. outputs, trashes.))
|
||||||
|
|
||||||
|
vector actor_logic
|
||||||
|
inputs a, score
|
||||||
|
outputs x
|
||||||
|
trashes y
|
||||||
|
@ $c000
|
||||||
|
|
||||||
Routines
|
Routines
|
||||||
--------
|
--------
|
||||||
|
|
||||||
@ -350,10 +361,10 @@ Grammar
|
|||||||
-------
|
-------
|
||||||
|
|
||||||
Program ::= {Defn} {Routine}.
|
Program ::= {Defn} {Routine}.
|
||||||
Defn ::= "byte" ["table"] NewIdent ["@" WordConst].
|
Defn ::= Type NewIdent [Constraints] ["@" WordConst].
|
||||||
Routine ::= "routine" NewIdent
|
Type ::= "byte" ["table"] | "vector"
|
||||||
["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs]
|
Constrnt::= ["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs].
|
||||||
(Block | "@" WordConst).
|
Routine ::= "routine" NewIdent Constraints (Block | "@" WordConst).
|
||||||
LocExprs::= LocExpr {"," LocExpr}.
|
LocExprs::= LocExpr {"," LocExpr}.
|
||||||
LocExpr ::= Register | Flag | LitByte | DefnIdent.
|
LocExpr ::= Register | Flag | LitByte | DefnIdent.
|
||||||
Register::= "a" | "x" | "y".
|
Register::= "a" | "x" | "y".
|
||||||
|
@ -132,17 +132,20 @@ class Parser(object):
|
|||||||
self.scanner.check_type('identifier')
|
self.scanner.check_type('identifier')
|
||||||
name = self.scanner.token
|
name = self.scanner.token
|
||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
|
|
||||||
|
(inputs, outputs, trashes) = self.constraints()
|
||||||
|
if type != TYPE_VECTOR and (inputs or outputs or trashes):
|
||||||
|
raise SyntaxError("Cannot apply constraints to non-vector type")
|
||||||
|
|
||||||
addr = None
|
addr = None
|
||||||
if self.scanner.consume('@'):
|
if self.scanner.consume('@'):
|
||||||
self.scanner.check_type('integer literal')
|
self.scanner.check_type('integer literal')
|
||||||
addr = int(self.scanner.token)
|
addr = int(self.scanner.token)
|
||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
return Defn(name=name, type=type, addr=addr)
|
return Defn(name=name, type=type, addr=addr,
|
||||||
|
inputs=inputs, outputs=outputs, trashes=trashes)
|
||||||
|
|
||||||
def routine(self):
|
def constraints(self):
|
||||||
self.scanner.expect('routine')
|
|
||||||
name = self.scanner.token
|
|
||||||
self.scanner.scan()
|
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = []
|
outputs = []
|
||||||
trashes = []
|
trashes = []
|
||||||
@ -152,6 +155,13 @@ class Parser(object):
|
|||||||
outputs = self.locexprs()
|
outputs = self.locexprs()
|
||||||
if self.scanner.consume('trashes'):
|
if self.scanner.consume('trashes'):
|
||||||
trashes = self.locexprs()
|
trashes = self.locexprs()
|
||||||
|
return (inputs, outputs, trashes)
|
||||||
|
|
||||||
|
def routine(self):
|
||||||
|
self.scanner.expect('routine')
|
||||||
|
name = self.scanner.token
|
||||||
|
self.scanner.scan()
|
||||||
|
(inputs, outputs, trashes) = self.constraints()
|
||||||
if self.scanner.consume('@'):
|
if self.scanner.consume('@'):
|
||||||
self.scanner.check_type('integer literal')
|
self.scanner.check_type('integer literal')
|
||||||
block = None
|
block = None
|
||||||
|
@ -989,7 +989,7 @@ Can't `copy` from a memory location that isn't initialized.
|
|||||||
| }
|
| }
|
||||||
? UninitializedAccessError: x
|
? UninitializedAccessError: x
|
||||||
|
|
||||||
Can't `st` to a memory location that doesn't appear in (outputs ∪ trashes).
|
Can't `copy` to a memory location that doesn't appear in (outputs ∪ trashes).
|
||||||
|
|
||||||
| byte lives
|
| byte lives
|
||||||
| routine main
|
| routine main
|
||||||
@ -1036,3 +1036,62 @@ a, z, and n are trashed, and must not be declared as outputs.
|
|||||||
| copy 0, lives
|
| copy 0, lives
|
||||||
| }
|
| }
|
||||||
? UninitializedOutputError: a
|
? UninitializedOutputError: a
|
||||||
|
|
||||||
|
Unless of course you subsequently initialize them.
|
||||||
|
|
||||||
|
| byte lives
|
||||||
|
| routine main
|
||||||
|
| outputs lives, a, z, n
|
||||||
|
| {
|
||||||
|
| copy 0, lives
|
||||||
|
| ld a, 0
|
||||||
|
| }
|
||||||
|
= ok
|
||||||
|
|
||||||
|
You can copy the address of a routine into a vector, if that vector is declared appropriately.
|
||||||
|
|
||||||
|
| vector vec
|
||||||
|
| inputs x
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
|
|
||||||
|
| routine foo
|
||||||
|
| inputs x
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
| {
|
||||||
|
| inc x
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| routine main
|
||||||
|
| inputs foo
|
||||||
|
| outputs vec
|
||||||
|
| trashes a, z, n
|
||||||
|
| {
|
||||||
|
| copy foo, vec
|
||||||
|
| }
|
||||||
|
= ok
|
||||||
|
|
||||||
|
But not if the vector is declared inappropriately.
|
||||||
|
|
||||||
|
| vector vec
|
||||||
|
| inputs y
|
||||||
|
| outputs y
|
||||||
|
| trashes z, n
|
||||||
|
|
|
||||||
|
| routine foo
|
||||||
|
| inputs x
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
| {
|
||||||
|
| inc x
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| routine main
|
||||||
|
| inputs foo
|
||||||
|
| outputs vec
|
||||||
|
| trashes a, z, n
|
||||||
|
| {
|
||||||
|
| copy foo, vec
|
||||||
|
| }
|
||||||
|
? IllegalWriteError
|
||||||
|
@ -218,6 +218,10 @@ Declaring a byte table memory location.
|
|||||||
Declaring a vector.
|
Declaring a vector.
|
||||||
|
|
||||||
| vector cinv
|
| vector cinv
|
||||||
|
| inputs a
|
||||||
|
| outputs x
|
||||||
|
| trashes a, x, z, n
|
||||||
|
| @ 788
|
||||||
|
|
|
|
||||||
| routine foo {
|
| routine foo {
|
||||||
| ld a, 0
|
| ld a, 0
|
||||||
@ -228,3 +232,15 @@ Declaring a vector.
|
|||||||
| }
|
| }
|
||||||
| }
|
| }
|
||||||
= ok
|
= ok
|
||||||
|
|
||||||
|
Only vectors can be decorated with constraints like that.
|
||||||
|
|
||||||
|
| byte cinv
|
||||||
|
| inputs a
|
||||||
|
| outputs x
|
||||||
|
| trashes a, x, z, n
|
||||||
|
| @ 788
|
||||||
|
|
|
||||||
|
| routine main {
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
Loading…
Reference in New Issue
Block a user