mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-06-02 03:41:28 +00:00
Low and high address operators, parsing and execution thereof.
This commit is contained in:
parent
e2daa33dc5
commit
9d6ca0b2b4
|
@ -45,16 +45,17 @@ TODO
|
|||
For 0.7:
|
||||
|
||||
* `low` and `high` address operators (turn `word` type into `byte`.)
|
||||
* `word table` type.
|
||||
|
||||
For 0.8:
|
||||
|
||||
* `word table` type.
|
||||
* `vector table` type.
|
||||
* zero-page memory locations.
|
||||
* indirect addressing.
|
||||
|
||||
For 0.9
|
||||
|
||||
* save registers on stack or in memory (the preserves them = not trashed)
|
||||
* save registers on stack or in memory (this preserves them = not trashed)
|
||||
|
||||
At some point...
|
||||
|
||||
|
|
|
@ -395,14 +395,15 @@ Grammar
|
|||
-------
|
||||
|
||||
Program ::= {Defn} {Routine}.
|
||||
Defn ::= Type Ident<new> [Constraints] ["@" WordConst].
|
||||
Defn ::= Type Ident<new> [Constraints] (":" Literal | "@" LitWord).
|
||||
Type ::= "byte" ["table"] | "vector"
|
||||
Constrnt::= ["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs].
|
||||
Routine ::= "routine" Ident<new> Constraints (Block | "@" WordConst).
|
||||
Routine ::= "routine" Ident<new> Constraints (Block | "@" LitWord).
|
||||
LocExprs::= LocExpr {"," LocExpr}.
|
||||
LocExpr ::= Register | Flag | LitByte | Ident.
|
||||
LocExpr ::= Register | Flag | Literal | ("<" | ">") Ident.
|
||||
Register::= "a" | "x" | "y".
|
||||
Flag ::= "c" | "z" | "n" | "v".
|
||||
Literal ::= LitByte | LitWord.
|
||||
LitByte ::= "0" ... "255".
|
||||
LitWord ::= "0" ... "65535".
|
||||
Block ::= "{" {Instr} "}".
|
||||
|
|
|
@ -25,10 +25,6 @@ class Routine(AST):
|
|||
pass
|
||||
|
||||
|
||||
class DecLoc(AST):
|
||||
pass
|
||||
|
||||
|
||||
class Block(AST):
|
||||
pass
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from sixtypical.ast import Program, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
ConstantRef, LocationRef,
|
||||
ConstantRef, LocationRef, PartRef,
|
||||
REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
|
||||
)
|
||||
|
||||
|
@ -21,10 +21,27 @@ class Context(object):
|
|||
return ref.value
|
||||
elif isinstance(ref, LocationRef):
|
||||
return self._store[ref.name]
|
||||
elif isinstance(ref, PartRef):
|
||||
value = self.get(ref.ref)
|
||||
if ref.height == 0:
|
||||
return value & 255
|
||||
elif ref.height == 1:
|
||||
return (value >> 8) & 255
|
||||
else:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
raise ValueError(ref)
|
||||
|
||||
def set(self, ref, value):
|
||||
if isinstance(ref, PartRef):
|
||||
old = self.get(ref.ref)
|
||||
if ref.height == 0:
|
||||
value = (old & (255 << 8)) | value
|
||||
elif ref.height == 1:
|
||||
value = (value << 8) | (old & 255)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
ref = ref.ref
|
||||
assert isinstance(ref, LocationRef)
|
||||
self._store[ref.name] = value
|
||||
|
||||
|
|
|
@ -90,6 +90,34 @@ class LocationRef(Ref):
|
|||
return isinstance(self.type, RoutineType)
|
||||
|
||||
|
||||
class PartRef(Ref):
|
||||
"""For 'low byte of' location and 'high byte of' location modifiers.
|
||||
|
||||
height=0 = low byte, height=1 = high byte.
|
||||
|
||||
"""
|
||||
def __init__(self, ref, height):
|
||||
assert isinstance(ref, Ref)
|
||||
assert ref.type == TYPE_WORD
|
||||
self.ref = ref
|
||||
self.height = height
|
||||
self.type = TYPE_BYTE
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, PartRef) and (
|
||||
other.height == self.height and other.ref == self.ref
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.ref) ^ hash(self.height) ^ hash(self.type)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r)' % (self.__class__.__name__, self.ref, self.height)
|
||||
|
||||
def is_constant(self):
|
||||
return self.ref.is_constant()
|
||||
|
||||
|
||||
class ConstantRef(Ref):
|
||||
def __init__(self, type, value):
|
||||
self.type = type
|
||||
|
|
|
@ -4,7 +4,7 @@ from sixtypical.ast import Program, Defn, Routine, Block, Instr
|
|||
from sixtypical.model import (
|
||||
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
|
||||
RoutineType, VectorType, ExecutableType,
|
||||
LocationRef, ConstantRef
|
||||
LocationRef, ConstantRef, PartRef
|
||||
)
|
||||
from sixtypical.scanner import Scanner
|
||||
|
||||
|
@ -142,7 +142,16 @@ class Parser(object):
|
|||
self.scanner.scan()
|
||||
return loc
|
||||
else:
|
||||
op = None
|
||||
if self.scanner.consume('<'):
|
||||
op = '<'
|
||||
elif self.scanner.consume('>'):
|
||||
op = '>'
|
||||
loc = self.lookup(self.scanner.token)
|
||||
if op == '<':
|
||||
loc = PartRef(loc, 0)
|
||||
elif op == '>':
|
||||
loc = PartRef(loc, 1)
|
||||
self.scanner.scan()
|
||||
return loc
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class Scanner(object):
|
|||
self.token = None
|
||||
self.type = 'EOF'
|
||||
return
|
||||
if self.scan_pattern(r'\,|\@|\+|\:|\{|\}', 'operator'):
|
||||
if self.scan_pattern(r'\,|\@|\+|\:|\<|\>|\{|\}', 'operator'):
|
||||
return
|
||||
if self.scan_pattern(r'\d+', 'integer literal'):
|
||||
return
|
||||
|
|
|
@ -417,6 +417,45 @@ after copy executes.
|
|||
= y: 5
|
||||
= z: 0
|
||||
|
||||
Copy word to word.
|
||||
|
||||
| word foo : 2000
|
||||
| word bar
|
||||
|
|
||||
| routine main {
|
||||
| copy foo, bar
|
||||
| }
|
||||
= a: 0
|
||||
= bar: 2000
|
||||
= c: 0
|
||||
= foo: 2000
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 0
|
||||
= y: 0
|
||||
= z: 0
|
||||
|
||||
Load and store low byte, high byte of word.
|
||||
|
||||
| word foo : 511
|
||||
|
|
||||
| routine main {
|
||||
| ld x, <foo
|
||||
| ld y, >foo
|
||||
| ld a, 2
|
||||
| st a, <foo
|
||||
| ld a, 1
|
||||
| st a, >foo
|
||||
| }
|
||||
= a: 1
|
||||
= c: 0
|
||||
= foo: 258
|
||||
= n: 0
|
||||
= v: 0
|
||||
= x: 255
|
||||
= y: 1
|
||||
= z: 0
|
||||
|
||||
Indirect call.
|
||||
|
||||
| vector foo outputs x trashes z, n
|
||||
|
|
|
@ -143,6 +143,16 @@ Initialized memory locations.
|
|||
| }
|
||||
= ok
|
||||
|
||||
Cannot have both initial value and explicit address.
|
||||
|
||||
| byte screen : 3 @ 1024
|
||||
|
|
||||
| routine main {
|
||||
| ld a, lives
|
||||
| st a, lives
|
||||
| }
|
||||
? SyntaxError
|
||||
|
||||
User-defined locations of other types.
|
||||
|
||||
| byte table screen @ 1024
|
||||
|
@ -154,26 +164,16 @@ User-defined locations of other types.
|
|||
| }
|
||||
= ok
|
||||
|
||||
Initialized memory locations.
|
||||
Referencing low and high byte of a word.
|
||||
|
||||
| byte lives : 3
|
||||
| word r1
|
||||
|
|
||||
| routine main {
|
||||
| ld a, lives
|
||||
| st a, lives
|
||||
| ld x, <r1
|
||||
| ld y, >r1
|
||||
| }
|
||||
= ok
|
||||
|
||||
Cannot have both initial value and explicit address.
|
||||
|
||||
| byte screen : 3 @ 1024
|
||||
|
|
||||
| routine main {
|
||||
| ld a, lives
|
||||
| st a, lives
|
||||
| }
|
||||
? SyntaxError
|
||||
|
||||
Can't access an undeclared memory location.
|
||||
|
||||
| routine main {
|
||||
|
|
Loading…
Reference in New Issue
Block a user