1
0
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:
Chris Pressey 2016-06-16 11:10:43 -05:00
parent e2daa33dc5
commit 9d6ca0b2b4
9 changed files with 117 additions and 26 deletions

View File

@ -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...

View File

@ -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} "}".

View File

@ -25,10 +25,6 @@ class Routine(AST):
pass
class DecLoc(AST):
pass
class Block(AST):
pass

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {