mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-06-07 22:29:27 +00:00
word types, with syntax and analysis thereof
This commit is contained in:
parent
007c81acad
commit
fc8c85e670
|
@ -159,6 +159,13 @@ class Analyzer(object):
|
|||
self.has_encountered_goto = False
|
||||
self.routines = {}
|
||||
|
||||
def assert_type(self, type, *locations):
|
||||
for location in locations:
|
||||
if location.type != type:
|
||||
raise TypeMismatchError('%s in %s' %
|
||||
(location.name, self.current_routine.name)
|
||||
)
|
||||
|
||||
def analyze_program(self, program):
|
||||
assert isinstance(program, Program)
|
||||
self.routines = {r.location: r for r in program.routines}
|
||||
|
@ -202,9 +209,13 @@ class Analyzer(object):
|
|||
if src.type == TYPE_BYTE_TABLE and dest.type == TYPE_BYTE:
|
||||
pass
|
||||
else:
|
||||
raise TypeMismatchError((src, dest))
|
||||
raise TypeMismatchError('%s and %s in %s' %
|
||||
(src.name, dest.name, self.current_routine.name)
|
||||
)
|
||||
elif src.type != dest.type:
|
||||
raise TypeMismatchError((src, dest))
|
||||
raise TypeMismatchError('%s and %s in %s' %
|
||||
(src.name, dest.name, self.current_routine.name)
|
||||
)
|
||||
context.assert_meaningful(src)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N)
|
||||
elif opcode == 'st':
|
||||
|
@ -214,22 +225,29 @@ class Analyzer(object):
|
|||
else:
|
||||
raise TypeMismatchError((src, dest))
|
||||
elif src.type != dest.type:
|
||||
raise TypeMismatchError((src, dest))
|
||||
raise TypeMismatchError('%s and %s in %s' %
|
||||
(src.name, dest.name, self.current_routine.name)
|
||||
)
|
||||
context.assert_meaningful(src)
|
||||
context.set_written(dest)
|
||||
elif opcode in ('add', 'sub'):
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.assert_meaningful(src, dest, FLAG_C)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C, FLAG_V)
|
||||
elif opcode in ('inc', 'dec'):
|
||||
self.assert_type(TYPE_BYTE, dest)
|
||||
context.assert_meaningful(dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N)
|
||||
elif opcode == 'cmp':
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.assert_meaningful(src, dest)
|
||||
context.set_written(FLAG_Z, FLAG_N, FLAG_C)
|
||||
elif opcode in ('and', 'or', 'xor'):
|
||||
self.assert_type(TYPE_BYTE, src, dest)
|
||||
context.assert_meaningful(src, dest)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N)
|
||||
elif opcode in ('shl', 'shr'):
|
||||
self.assert_type(TYPE_BYTE, dest)
|
||||
context.assert_meaningful(dest, FLAG_C)
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C)
|
||||
elif opcode == 'call':
|
||||
|
|
|
@ -17,6 +17,8 @@ class Type(object):
|
|||
TYPE_BIT = Type('bit')
|
||||
TYPE_BYTE = Type('byte')
|
||||
TYPE_BYTE_TABLE = Type('byte table')
|
||||
TYPE_WORD = Type('word')
|
||||
TYPE_WORD_TABLE = Type('word table')
|
||||
|
||||
|
||||
class ExecutableType(Type):
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from sixtypical.ast import Program, Defn, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE,
|
||||
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
|
||||
RoutineType, VectorType, ExecutableType,
|
||||
LocationRef, ConstantRef
|
||||
)
|
||||
|
@ -32,7 +32,7 @@ class Parser(object):
|
|||
def program(self):
|
||||
defns = []
|
||||
routines = []
|
||||
while self.scanner.on('byte') or self.scanner.on('vector'):
|
||||
while self.scanner.on('byte', 'word', 'vector'):
|
||||
defn = self.defn()
|
||||
name = defn.name
|
||||
if name in self.symbols:
|
||||
|
@ -50,14 +50,18 @@ class Parser(object):
|
|||
return Program(defns=defns, routines=routines)
|
||||
|
||||
def defn(self):
|
||||
type = TYPE_BYTE
|
||||
type = None
|
||||
if self.scanner.consume('byte'):
|
||||
type = TYPE_BYTE
|
||||
if self.scanner.consume('table'):
|
||||
type = TYPE_BYTE_TABLE
|
||||
elif self.scanner.consume('word'):
|
||||
type = TYPE_WORD
|
||||
if self.scanner.consume('table'):
|
||||
type = TYPE_WORD_TABLE
|
||||
else:
|
||||
self.scanner.expect('vector')
|
||||
type = 'vector'
|
||||
type = 'vector' # will be resolved to a Type below
|
||||
self.scanner.check_type('identifier')
|
||||
name = self.scanner.token
|
||||
self.scanner.scan()
|
||||
|
|
|
@ -55,8 +55,8 @@ class Scanner(object):
|
|||
raise SyntaxError("Expected '%s', but found '%s'" %
|
||||
(token, self.token))
|
||||
|
||||
def on(self, token):
|
||||
return self.token == token
|
||||
def on(self, *tokens):
|
||||
return self.token in tokens
|
||||
|
||||
def on_type(self, type):
|
||||
return self.type == type
|
||||
|
|
|
@ -148,6 +148,18 @@ Can't `ld` to a memory location that doesn't appear in (outputs ∪ trashes).
|
|||
| }
|
||||
? ForbiddenWriteError: z in main
|
||||
|
||||
Can't `ld` a `word` type.
|
||||
|
||||
| word foo
|
||||
|
|
||||
| routine main
|
||||
| inputs foo
|
||||
| trashes a, n, z
|
||||
| {
|
||||
| ld a, foo
|
||||
| }
|
||||
? TypeMismatchError: foo and a in main
|
||||
|
||||
### st ###
|
||||
|
||||
Can't `st` from a memory location that isn't initialized.
|
||||
|
@ -301,6 +313,19 @@ Reading from a table, you must use an index, and vice-versa.
|
|||
| }
|
||||
= ok
|
||||
|
||||
Can't `st` a `word` type.
|
||||
|
||||
| word foo
|
||||
|
|
||||
| routine main
|
||||
| outputs foo
|
||||
| trashes a, n, z
|
||||
| {
|
||||
| ld a, 0
|
||||
| st a, foo
|
||||
| }
|
||||
? TypeMismatchError: a and foo in main
|
||||
|
||||
### add ###
|
||||
|
||||
Can't `add` from or to a memory location that isn't initialized.
|
||||
|
@ -424,6 +449,19 @@ Location must be initialized and writeable.
|
|||
| }
|
||||
= ok
|
||||
|
||||
Can't `inc` a `word` type.
|
||||
|
||||
| word foo
|
||||
|
|
||||
| routine main
|
||||
| inputs foo
|
||||
| outputs foo
|
||||
| trashes z, n
|
||||
| {
|
||||
| inc foo
|
||||
| }
|
||||
? TypeMismatchError: foo in main
|
||||
|
||||
### dec ###
|
||||
|
||||
Location must be initialized and writeable.
|
||||
|
@ -453,6 +491,19 @@ Location must be initialized and writeable.
|
|||
| }
|
||||
= ok
|
||||
|
||||
Can't `dec` a `word` type.
|
||||
|
||||
| word foo
|
||||
|
|
||||
| routine main
|
||||
| inputs foo
|
||||
| outputs foo
|
||||
| trashes z, n
|
||||
| {
|
||||
| dec foo
|
||||
| }
|
||||
? TypeMismatchError: foo in main
|
||||
|
||||
### cmp ###
|
||||
|
||||
Some rudimentary tests for cmp.
|
||||
|
@ -1048,6 +1099,64 @@ Unless of course you subsequently initialize them.
|
|||
| }
|
||||
= ok
|
||||
|
||||
Can `copy` from a `byte` to a `byte`.
|
||||
|
||||
| byte source : 0
|
||||
| byte dest
|
||||
|
|
||||
| routine main
|
||||
| inputs source
|
||||
| outputs dest
|
||||
| trashes a, z, n
|
||||
| {
|
||||
| copy source, dest
|
||||
| }
|
||||
= ok
|
||||
|
||||
Can `copy` from a `word` to a `word`.
|
||||
|
||||
| word source : 0
|
||||
| word dest
|
||||
|
|
||||
| routine main
|
||||
| inputs source
|
||||
| outputs dest
|
||||
| trashes a, z, n
|
||||
| {
|
||||
| copy source, dest
|
||||
| }
|
||||
= ok
|
||||
|
||||
Can't `copy` from a `byte` to a `word`.
|
||||
|
||||
| byte source : 0
|
||||
| word dest
|
||||
|
|
||||
| routine main
|
||||
| inputs source
|
||||
| outputs dest
|
||||
| trashes a, z, n
|
||||
| {
|
||||
| copy source, dest
|
||||
| }
|
||||
? TypeMismatchError
|
||||
|
||||
Can't `copy` from a `word` to a `byte`.
|
||||
|
||||
| word source : 0
|
||||
| byte dest
|
||||
|
|
||||
| routine main
|
||||
| inputs source
|
||||
| outputs dest
|
||||
| trashes a, z, n
|
||||
| {
|
||||
| copy source, dest
|
||||
| }
|
||||
? TypeMismatchError
|
||||
|
||||
### routines ###
|
||||
|
||||
Routines are constants. You need not, and in fact cannot, specify a constant
|
||||
as an input to, an output of, or as a trashed value of a routine.
|
||||
|
||||
|
|
|
@ -143,6 +143,27 @@ Initialized memory locations.
|
|||
| }
|
||||
= ok
|
||||
|
||||
User-defined locations of other types.
|
||||
|
||||
| byte table screen @ 1024
|
||||
| word r1
|
||||
| word r2 @ 60000
|
||||
| word r3 : 2000
|
||||
|
|
||||
| routine main {
|
||||
| }
|
||||
= ok
|
||||
|
||||
Initialized memory locations.
|
||||
|
||||
| byte lives : 3
|
||||
|
|
||||
| routine main {
|
||||
| ld a, lives
|
||||
| st a, lives
|
||||
| }
|
||||
= ok
|
||||
|
||||
Cannot have both initial value and explicit address.
|
||||
|
||||
| byte screen : 3 @ 1024
|
||||
|
|
Loading…
Reference in New Issue
Block a user