1
0
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:
Chris Pressey 2016-06-16 11:08:57 -05:00
parent 007c81acad
commit fc8c85e670
6 changed files with 163 additions and 9 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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