mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-25 23:49:17 +00:00
Kind-of not-pretty syntax refactor to support adding typedefs.
This commit is contained in:
parent
15072eff52
commit
0be721667a
@ -3,7 +3,7 @@
|
||||
from sixtypical.ast import Program, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
TYPE_BYTE, TYPE_WORD,
|
||||
TableType, BufferType, PointerType, VectorType, ExecutableType, RoutineType,
|
||||
TableType, BufferType, PointerType, VectorType, RoutineType,
|
||||
ConstantRef, LocationRef, IndirectRef, IndexedRef, AddressRef,
|
||||
REG_A, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
|
||||
)
|
||||
@ -303,6 +303,8 @@ class Analyzer(object):
|
||||
context.set_written(dest, FLAG_Z, FLAG_N, FLAG_C)
|
||||
elif opcode == 'call':
|
||||
type = instr.location.type
|
||||
if isinstance(type, VectorType):
|
||||
type = type.of_type
|
||||
for ref in type.inputs:
|
||||
context.assert_meaningful(ref)
|
||||
for ref in type.outputs:
|
||||
@ -366,8 +368,11 @@ class Analyzer(object):
|
||||
elif isinstance(src, (LocationRef, ConstantRef)) and isinstance(dest, IndexedRef):
|
||||
if src.type == TYPE_WORD and TableType.is_a_table_type(dest.ref.type, TYPE_WORD):
|
||||
pass
|
||||
elif (isinstance(src.type, ExecutableType) and isinstance(dest.ref.type, TableType) and
|
||||
ExecutableType.executable_types_compatible(src.type, dest.ref.type.of_type)):
|
||||
elif (isinstance(src.type, VectorType) and isinstance(dest.ref.type, TableType) and
|
||||
RoutineType.executable_types_compatible(src.type.of_type, dest.ref.type.of_type)):
|
||||
pass
|
||||
elif (isinstance(src.type, RoutineType) and isinstance(dest.ref.type, TableType) and
|
||||
RoutineType.executable_types_compatible(src.type, dest.ref.type.of_type)):
|
||||
pass
|
||||
else:
|
||||
raise TypeMismatchError((src, dest))
|
||||
@ -376,7 +381,7 @@ class Analyzer(object):
|
||||
if TableType.is_a_table_type(src.ref.type, TYPE_WORD) and dest.type == TYPE_WORD:
|
||||
pass
|
||||
elif (isinstance(src.ref.type, TableType) and isinstance(dest.type, VectorType) and
|
||||
ExecutableType.executable_types_compatible(src.ref.type.of_type, dest.type)):
|
||||
RoutineType.executable_types_compatible(src.ref.type.of_type, dest.type.of_type)):
|
||||
pass
|
||||
else:
|
||||
raise TypeMismatchError((src, dest))
|
||||
@ -384,10 +389,10 @@ class Analyzer(object):
|
||||
elif isinstance(src, (LocationRef, ConstantRef)) and isinstance(dest, LocationRef):
|
||||
if src.type == dest.type:
|
||||
pass
|
||||
elif isinstance(src.type, ExecutableType) and isinstance(dest.type, VectorType):
|
||||
self.assert_affected_within('inputs', src.type.inputs, dest.type.inputs)
|
||||
self.assert_affected_within('outputs', src.type.outputs, dest.type.outputs)
|
||||
self.assert_affected_within('trashes', src.type.trashes, dest.type.trashes)
|
||||
elif isinstance(src.type, RoutineType) and isinstance(dest.type, VectorType):
|
||||
self.assert_affected_within('inputs', src.type.inputs, dest.type.of_type.inputs)
|
||||
self.assert_affected_within('outputs', src.type.outputs, dest.type.of_type.outputs)
|
||||
self.assert_affected_within('trashes', src.type.trashes, dest.type.of_type.trashes)
|
||||
else:
|
||||
raise TypeMismatchError((src, dest))
|
||||
else:
|
||||
@ -434,10 +439,12 @@ class Analyzer(object):
|
||||
location = instr.location
|
||||
type_ = location.type
|
||||
|
||||
if not isinstance(type_, ExecutableType):
|
||||
if not isinstance(type_, (RoutineType, VectorType)):
|
||||
raise TypeMismatchError(location)
|
||||
|
||||
# assert that the dest routine's inputs are all initialized
|
||||
if isinstance(type_, VectorType):
|
||||
type_ = type_.of_type
|
||||
for ref in type_.inputs:
|
||||
context.assert_meaningful(ref)
|
||||
|
||||
|
@ -17,16 +17,27 @@ class Type(object):
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
def backpatch_constraint_labels(self, resolver):
|
||||
if isinstance(self, TableType):
|
||||
self.of_type.backpatch_constraint_labels(resolver)
|
||||
elif isinstance(self, VectorType):
|
||||
self.of_type.backpatch_constraint_labels(resolver)
|
||||
elif isinstance(self, RoutineType):
|
||||
self.inputs = set([resolver(w) for w in self.inputs])
|
||||
self.outputs = set([resolver(w) for w in self.outputs])
|
||||
self.trashes = set([resolver(w) for w in self.trashes])
|
||||
|
||||
|
||||
TYPE_BIT = Type('bit')
|
||||
TYPE_BYTE = Type('byte')
|
||||
TYPE_WORD = Type('word')
|
||||
|
||||
|
||||
class ExecutableType(Type):
|
||||
"""Used for routines and vectors."""
|
||||
def __init__(self, name, inputs=None, outputs=None, trashes=None):
|
||||
self.name = name
|
||||
|
||||
class RoutineType(Type):
|
||||
"""This memory location contains the code for a routine."""
|
||||
def __init__(self, inputs=None, outputs=None, trashes=None):
|
||||
self.name = 'routine'
|
||||
self.inputs = inputs or set()
|
||||
self.outputs = outputs or set()
|
||||
self.trashes = trashes or set()
|
||||
@ -37,7 +48,7 @@ class ExecutableType(Type):
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, ExecutableType) and (
|
||||
return isinstance(other, RoutineType) and (
|
||||
other.name == self.name and
|
||||
other.inputs == self.inputs and
|
||||
other.outputs == self.outputs and
|
||||
@ -50,7 +61,11 @@ class ExecutableType(Type):
|
||||
@classmethod
|
||||
def executable_types_compatible(cls_, src, dest):
|
||||
"""Returns True iff a value of type `src` can be assigned to a storage location of type `dest`."""
|
||||
if isinstance(src, ExecutableType) and isinstance(dest, VectorType):
|
||||
if isinstance(src, VectorType):
|
||||
src = src.of_type
|
||||
if isinstance(dest, VectorType):
|
||||
dest = dest.of_type
|
||||
if isinstance(src, RoutineType) and isinstance(dest, RoutineType):
|
||||
# TODO: I'm sure we can replace some of these with subset-containment, but that requires thought
|
||||
return (
|
||||
src.inputs == dest.inputs and
|
||||
@ -61,16 +76,22 @@ class ExecutableType(Type):
|
||||
return False
|
||||
|
||||
|
||||
class RoutineType(ExecutableType):
|
||||
"""This memory location contains the code for a routine."""
|
||||
def __init__(self, **kwargs):
|
||||
super(RoutineType, self).__init__('routine', **kwargs)
|
||||
class VectorType(Type):
|
||||
"""This memory location contains the address of some other type (currently, only RoutineType)."""
|
||||
def __init__(self, of_type):
|
||||
self.name = 'vector'
|
||||
self.of_type = of_type
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r)' % (
|
||||
self.__class__.__name__, self.of_type
|
||||
)
|
||||
|
||||
class VectorType(ExecutableType):
|
||||
"""This memory location contains the address of a routine."""
|
||||
def __init__(self, **kwargs):
|
||||
super(VectorType, self).__init__('vector', **kwargs)
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name and self.of_type == other.of_type
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name) ^ hash(self.of_type)
|
||||
|
||||
|
||||
class TableType(Type):
|
||||
@ -135,18 +156,6 @@ class LocationRef(Ref):
|
||||
def is_constant(self):
|
||||
return isinstance(self.type, RoutineType)
|
||||
|
||||
def backpatch_vector_labels(self, resolver):
|
||||
if isinstance(self.type, ExecutableType):
|
||||
t = self.type
|
||||
t.inputs = set([resolver(w) for w in t.inputs])
|
||||
t.outputs = set([resolver(w) for w in t.outputs])
|
||||
t.trashes = set([resolver(w) for w in t.trashes])
|
||||
if isinstance(self.type, TableType) and isinstance(self.type.of_type, ExecutableType):
|
||||
t = self.type.of_type
|
||||
t.inputs = set([resolver(w) for w in t.inputs])
|
||||
t.outputs = set([resolver(w) for w in t.outputs])
|
||||
t.trashes = set([resolver(w) for w in t.trashes])
|
||||
|
||||
@classmethod
|
||||
def format_set(cls, location_refs):
|
||||
return '{%s}' % ', '.join([str(loc) for loc in sorted(location_refs)])
|
||||
|
@ -3,7 +3,7 @@
|
||||
from sixtypical.ast import Program, Defn, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
TYPE_BIT, TYPE_BYTE, TYPE_WORD,
|
||||
RoutineType, VectorType, ExecutableType, TableType, BufferType, PointerType,
|
||||
RoutineType, VectorType, TableType, BufferType, PointerType,
|
||||
LocationRef, ConstantRef, IndirectRef, IndexedRef, AddressRef,
|
||||
)
|
||||
from sixtypical.scanner import Scanner
|
||||
@ -35,16 +35,20 @@ class Parser(object):
|
||||
def program(self):
|
||||
defns = []
|
||||
routines = []
|
||||
while self.scanner.on('byte', 'word', 'vector', 'buffer', 'pointer'):
|
||||
while self.scanner.on('byte', 'word', 'table', 'vector', 'buffer', 'pointer'): # 'routine',
|
||||
defn = self.defn()
|
||||
name = defn.name
|
||||
if name in self.symbols:
|
||||
raise SyntaxError('Symbol "%s" already declared' % name)
|
||||
self.symbols[name] = SymEntry(defn, defn.location)
|
||||
defns.append(defn)
|
||||
while self.scanner.on('routine'):
|
||||
routine = self.routine()
|
||||
name = routine.name
|
||||
while self.scanner.on('define', 'routine'):
|
||||
if self.scanner.consume('define'):
|
||||
name = self.scanner.token
|
||||
self.scanner.scan()
|
||||
else:
|
||||
routine = self.legacy_routine()
|
||||
name = routine.name
|
||||
if name in self.symbols:
|
||||
raise SyntaxError('Symbol "%s" already declared' % name)
|
||||
self.symbols[name] = SymEntry(routine, routine.location)
|
||||
@ -53,29 +57,30 @@ class Parser(object):
|
||||
|
||||
# now backpatch the executable types.
|
||||
for defn in defns:
|
||||
defn.location.backpatch_vector_labels(lambda w: self.lookup(w))
|
||||
defn.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
||||
for routine in routines:
|
||||
routine.location.backpatch_vector_labels(lambda w: self.lookup(w))
|
||||
routine.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
||||
for instr in self.backpatch_instrs:
|
||||
if instr.opcode in ('call', 'goto'):
|
||||
name = instr.location
|
||||
if name not in self.symbols:
|
||||
raise SyntaxError('Undefined routine "%s"' % name)
|
||||
if not isinstance(self.symbols[name].model.type, ExecutableType):
|
||||
if not isinstance(self.symbols[name].model.type, (RoutineType, VectorType)):
|
||||
raise SyntaxError('Illegal call of non-executable "%s"' % name)
|
||||
instr.location = self.symbols[name].model
|
||||
if instr.opcode in ('copy',) and isinstance(instr.src, basestring):
|
||||
name = instr.src
|
||||
if name not in self.symbols:
|
||||
raise SyntaxError('Undefined routine "%s"' % name)
|
||||
if not isinstance(self.symbols[name].model.type, ExecutableType):
|
||||
if not isinstance(self.symbols[name].model.type, (RoutineType, VectorType)):
|
||||
raise SyntaxError('Illegal copy of non-executable "%s"' % name)
|
||||
instr.src = self.symbols[name].model
|
||||
|
||||
return Program(defns=defns, routines=routines)
|
||||
|
||||
def defn(self):
|
||||
type_, name = self.defn_type_and_name()
|
||||
type_ = self.defn_type()
|
||||
name = self.defn_name()
|
||||
|
||||
initial = None
|
||||
if self.scanner.consume(':'):
|
||||
@ -107,39 +112,28 @@ class Parser(object):
|
||||
self.scanner.expect(']')
|
||||
return size
|
||||
|
||||
def defn_type_and_name(self):
|
||||
def defn_type(self):
|
||||
if self.scanner.consume('byte'):
|
||||
type_ = TYPE_BYTE
|
||||
if self.scanner.consume('table'):
|
||||
size = self.defn_size()
|
||||
type_ = TableType(type_, size)
|
||||
name = self.defn_name()
|
||||
return type_, name
|
||||
return TYPE_BYTE
|
||||
elif self.scanner.consume('word'):
|
||||
type_ = TYPE_WORD
|
||||
if self.scanner.consume('table'):
|
||||
size = self.defn_size()
|
||||
type_ = TableType(type_, size)
|
||||
name = self.defn_name()
|
||||
return type_, name
|
||||
return TYPE_WORD
|
||||
elif self.scanner.consume('table'):
|
||||
size = self.defn_size()
|
||||
type_ = self.defn_type()
|
||||
return TableType(type_, size)
|
||||
elif self.scanner.consume('vector'):
|
||||
size = None
|
||||
if self.scanner.consume('table'):
|
||||
size = self.defn_size()
|
||||
name = self.defn_name()
|
||||
type_ = self.defn_type()
|
||||
# TODO: assert that it's a routine type
|
||||
return VectorType(type_)
|
||||
elif self.scanner.consume('routine'):
|
||||
(inputs, outputs, trashes) = self.constraints()
|
||||
type_ = VectorType(inputs=inputs, outputs=outputs, trashes=trashes)
|
||||
if size is not None:
|
||||
type_ = TableType(type_, size)
|
||||
return type_, name
|
||||
return RoutineType(inputs=inputs, outputs=outputs, trashes=trashes)
|
||||
elif self.scanner.consume('buffer'):
|
||||
size = self.defn_size()
|
||||
name = self.defn_name()
|
||||
return BufferType(size), name
|
||||
return BufferType(size)
|
||||
else:
|
||||
self.scanner.expect('pointer')
|
||||
name = self.defn_name()
|
||||
return PointerType(), name
|
||||
return PointerType()
|
||||
|
||||
def defn_name(self):
|
||||
self.scanner.check_type('identifier')
|
||||
@ -159,11 +153,12 @@ class Parser(object):
|
||||
trashes = set(self.labels())
|
||||
return (inputs, outputs, trashes)
|
||||
|
||||
def routine(self):
|
||||
def legacy_routine(self):
|
||||
self.scanner.expect('routine')
|
||||
name = self.scanner.token
|
||||
self.scanner.scan()
|
||||
(inputs, outputs, trashes) = self.constraints()
|
||||
type_ = RoutineType(inputs=inputs, outputs=outputs, trashes=trashes)
|
||||
if self.scanner.consume('@'):
|
||||
self.scanner.check_type('integer literal')
|
||||
block = None
|
||||
@ -172,10 +167,26 @@ class Parser(object):
|
||||
else:
|
||||
block = self.block()
|
||||
addr = None
|
||||
location = LocationRef(
|
||||
RoutineType(inputs=inputs, outputs=outputs, trashes=trashes),
|
||||
name
|
||||
location = LocationRef(type_, name)
|
||||
return Routine(
|
||||
name=name, block=block, addr=addr,
|
||||
location=location
|
||||
)
|
||||
|
||||
def routine(self):
|
||||
name = self.scanner.token
|
||||
self.scanner.scan()
|
||||
type_ = self.defn_type()
|
||||
# TODO assert that it's a routine
|
||||
if self.scanner.consume('@'):
|
||||
self.scanner.check_type('integer literal')
|
||||
block = None
|
||||
addr = int(self.scanner.token)
|
||||
self.scanner.scan()
|
||||
else:
|
||||
block = self.block()
|
||||
addr = None
|
||||
location = LocationRef(type_, name)
|
||||
return Routine(
|
||||
name=name, block=block, addr=addr,
|
||||
location=location
|
||||
|
@ -243,7 +243,7 @@ Can't `st` a `word` type.
|
||||
Storing to a table, you must use an index.
|
||||
|
||||
| byte one
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs one
|
||||
@ -256,7 +256,7 @@ Storing to a table, you must use an index.
|
||||
= ok
|
||||
|
||||
| byte one
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs many
|
||||
@ -269,7 +269,7 @@ Storing to a table, you must use an index.
|
||||
? TypeMismatchError
|
||||
|
||||
| byte one
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs one
|
||||
@ -282,7 +282,7 @@ Storing to a table, you must use an index.
|
||||
? TypeMismatchError
|
||||
|
||||
| byte one
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs many
|
||||
@ -297,7 +297,7 @@ Storing to a table, you must use an index.
|
||||
The index must be initialized.
|
||||
|
||||
| byte one
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs many
|
||||
@ -334,7 +334,7 @@ Reading from a table, you must use an index.
|
||||
| }
|
||||
? TypeMismatchError
|
||||
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs many
|
||||
@ -347,7 +347,7 @@ Reading from a table, you must use an index.
|
||||
| }
|
||||
? TypeMismatchError
|
||||
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs many
|
||||
@ -360,7 +360,7 @@ Reading from a table, you must use an index.
|
||||
| }
|
||||
= ok
|
||||
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| inputs many
|
||||
@ -374,7 +374,7 @@ Reading from a table, you must use an index.
|
||||
|
||||
The index must be initialized.
|
||||
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| inputs many
|
||||
@ -388,7 +388,7 @@ The index must be initialized.
|
||||
Copying to and from a word table.
|
||||
|
||||
| word one
|
||||
| word table[256] many
|
||||
| table[256] word many
|
||||
|
|
||||
| routine main
|
||||
| inputs one, many
|
||||
@ -402,7 +402,7 @@ Copying to and from a word table.
|
||||
= ok
|
||||
|
||||
| word one
|
||||
| word table[256] many
|
||||
| table[256] word many
|
||||
|
|
||||
| routine main
|
||||
| inputs one, many
|
||||
@ -415,7 +415,7 @@ Copying to and from a word table.
|
||||
? TypeMismatchError
|
||||
|
||||
| word one
|
||||
| word table[256] many
|
||||
| table[256] word many
|
||||
|
|
||||
| routine main
|
||||
| inputs one, many
|
||||
@ -429,7 +429,7 @@ Copying to and from a word table.
|
||||
|
||||
You can also copy a literal word to a word table.
|
||||
|
||||
| word table[256] many
|
||||
| table[256] word many
|
||||
|
|
||||
| routine main
|
||||
| inputs many
|
||||
@ -1593,10 +1593,11 @@ Read through a pointer.
|
||||
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.
|
||||
|
||||
| vector vec
|
||||
| vector routine
|
||||
| inputs x
|
||||
| outputs x
|
||||
| trashes z, n
|
||||
| vec
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -1615,10 +1616,11 @@ as an input to, an output of, or as a trashed value of a routine.
|
||||
| }
|
||||
? ConstantConstraintError: foo in main
|
||||
|
||||
| vector vec
|
||||
| vector routine
|
||||
| inputs x
|
||||
| outputs x
|
||||
| trashes z, n
|
||||
| vec
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -1636,10 +1638,11 @@ as an input to, an output of, or as a trashed value of a routine.
|
||||
| }
|
||||
? ConstantConstraintError: foo in main
|
||||
|
||||
| vector vec
|
||||
| vector routine
|
||||
| inputs x
|
||||
| outputs x
|
||||
| trashes z, n
|
||||
| vec
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -1660,10 +1663,11 @@ as an input to, an output of, or as a trashed value of a routine.
|
||||
You can copy the address of a routine into a vector, if that vector is
|
||||
declared appropriately.
|
||||
|
||||
| vector vec
|
||||
| vector routine
|
||||
| inputs x
|
||||
| outputs x
|
||||
| trashes z, n
|
||||
| vec
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -1683,10 +1687,11 @@ declared appropriately.
|
||||
|
||||
But not if the vector is declared inappropriately.
|
||||
|
||||
| vector vec
|
||||
| vector routine
|
||||
| inputs y
|
||||
| outputs y
|
||||
| trashes z, n
|
||||
| vec
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -1707,10 +1712,11 @@ But not if the vector is declared inappropriately.
|
||||
"Appropriately" means, if the routine affects no more than what is named
|
||||
in the input/output sets of the vector.
|
||||
|
||||
| vector vec
|
||||
| vector routine
|
||||
| inputs a, x
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| vec
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -1730,10 +1736,11 @@ in the input/output sets of the vector.
|
||||
|
||||
Routines are read-only.
|
||||
|
||||
| vector vec
|
||||
| vector routine
|
||||
| inputs x
|
||||
| outputs x
|
||||
| trashes z, n
|
||||
| vec
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -1753,7 +1760,9 @@ Routines are read-only.
|
||||
|
||||
Indirect call.
|
||||
|
||||
| vector foo outputs x trashes z, n
|
||||
| vector routine
|
||||
| outputs x trashes z, n
|
||||
| foo
|
||||
|
|
||||
| routine bar outputs x trashes z, n {
|
||||
| ld x, 200
|
||||
@ -1767,7 +1776,7 @@ Indirect call.
|
||||
|
||||
Calling the vector does indeed trash the things the vector says it does.
|
||||
|
||||
| vector foo trashes x, z, n
|
||||
| vector routine trashes x, z, n foo
|
||||
|
|
||||
| routine bar trashes x, z, n {
|
||||
| ld x, 200
|
||||
@ -1867,7 +1876,7 @@ Can `goto` a routine that outputs or trashes less than the current routine.
|
||||
|
||||
Indirect goto.
|
||||
|
||||
| vector foo outputs x trashes a, z, n
|
||||
| vector routine outputs x trashes a, z, n foo
|
||||
|
|
||||
| routine bar outputs x trashes a, z, n {
|
||||
| ld x, 200
|
||||
@ -1882,8 +1891,9 @@ Indirect goto.
|
||||
Jumping through the vector does indeed trash, or output, the things the
|
||||
vector says it does.
|
||||
|
||||
| vector foo
|
||||
| vector routine
|
||||
| trashes a, x, z, n
|
||||
| foo
|
||||
|
|
||||
| routine bar
|
||||
| trashes a, x, z, n {
|
||||
@ -1905,9 +1915,9 @@ vector says it does.
|
||||
| }
|
||||
? UnmeaningfulReadError: x in main
|
||||
|
||||
| vector foo
|
||||
| vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| trashes a, z, n foo
|
||||
|
|
||||
| routine bar
|
||||
| outputs x
|
||||
@ -1935,12 +1945,14 @@ vector says it does.
|
||||
|
||||
A vector can be copied into a vector table.
|
||||
|
||||
| vector one
|
||||
| vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| vector table[256] many
|
||||
| one
|
||||
| table[256] vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| many
|
||||
|
|
||||
| routine bar outputs x trashes a, z, n {
|
||||
| ld x, 200
|
||||
@ -1959,12 +1971,14 @@ A vector can be copied into a vector table.
|
||||
|
||||
A vector can be copied out of a vector table.
|
||||
|
||||
| vector one
|
||||
| vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| vector table[256] many
|
||||
| one
|
||||
| table[256] vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| many
|
||||
|
|
||||
| routine bar outputs x trashes a, z, n {
|
||||
| ld x, 200
|
||||
@ -1983,9 +1997,10 @@ A vector can be copied out of a vector table.
|
||||
|
||||
A routine can be copied into a vector table.
|
||||
|
||||
| vector table[256] many
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| table[256] vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| many
|
||||
|
|
||||
| routine bar outputs x trashes a, z, n {
|
||||
| ld x, 200
|
||||
@ -2003,9 +2018,10 @@ A routine can be copied into a vector table.
|
||||
|
||||
A vector in a vector table cannot be directly called.
|
||||
|
||||
| vector table[256] many
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| table[256] vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| many
|
||||
|
|
||||
| routine bar outputs x trashes a, z, n {
|
||||
| ld x, 200
|
||||
|
@ -139,7 +139,7 @@ Word memory locations with explicit address, initial value.
|
||||
|
||||
Initialized byte table. Bytes allocated, but beyond the string, are 0's.
|
||||
|
||||
| byte table[8] message : "WHAT?"
|
||||
| table[8] byte message : "WHAT?"
|
||||
|
|
||||
| routine main
|
||||
| inputs message
|
||||
@ -352,7 +352,7 @@ The body of `repeat forever` can be empty.
|
||||
Indexed access.
|
||||
|
||||
| byte one
|
||||
| byte table[256] many
|
||||
| table[256] byte many
|
||||
|
|
||||
| routine main
|
||||
| outputs many
|
||||
@ -371,8 +371,8 @@ Indexed access.
|
||||
|
||||
Byte tables take up 256 bytes in memory.
|
||||
|
||||
| byte table[256] tab1
|
||||
| byte table[256] tab2
|
||||
| table[256] byte tab1
|
||||
| table[256] byte tab2
|
||||
|
|
||||
| routine main
|
||||
| inputs tab1
|
||||
@ -458,7 +458,7 @@ Copy literal word to word.
|
||||
|
||||
You can also copy a literal word to a word table.
|
||||
|
||||
| word table[256] many
|
||||
| table[256] word many
|
||||
|
|
||||
| routine main
|
||||
| inputs many
|
||||
@ -477,8 +477,8 @@ You can also copy a literal word to a word table.
|
||||
|
||||
Copy vector to vector.
|
||||
|
||||
| vector bar
|
||||
| vector baz
|
||||
| vector routine bar
|
||||
| vector routine baz
|
||||
|
|
||||
| routine main
|
||||
| inputs baz
|
||||
@ -495,7 +495,7 @@ Copy vector to vector.
|
||||
|
||||
Copy routine to vector, inside an `interrupts off` block.
|
||||
|
||||
| vector bar
|
||||
| vector routine bar
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
@ -527,7 +527,7 @@ Copy routine to vector, inside an `interrupts off` block.
|
||||
Copy word to word table and back, with both `x` and `y` as indexes.
|
||||
|
||||
| word one
|
||||
| word table[256] many
|
||||
| table[256] word many
|
||||
|
|
||||
| routine main
|
||||
| inputs one, many
|
||||
@ -568,7 +568,7 @@ Copy word to word table and back, with both `x` and `y` as indexes.
|
||||
|
||||
Indirect call.
|
||||
|
||||
| vector foo outputs x trashes z, n
|
||||
| vector routine outputs x trashes z, n foo
|
||||
|
|
||||
| routine bar outputs x trashes z, n {
|
||||
| ld x, 200
|
||||
@ -608,12 +608,14 @@ goto.
|
||||
|
||||
Copying to and from a vector table.
|
||||
|
||||
| vector one
|
||||
| vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| vector table[256] many
|
||||
| one
|
||||
| table[256] vector routine
|
||||
| outputs x
|
||||
| trashes a, z, n
|
||||
| many
|
||||
|
|
||||
| routine bar outputs x trashes a, z, n {
|
||||
| ld x, 200
|
||||
|
@ -135,10 +135,7 @@ User-defined memory addresses of different types.
|
||||
|
||||
| byte byt
|
||||
| word wor
|
||||
| vector vec trashes a
|
||||
| byte table[256] tab
|
||||
| word table[256] wtab
|
||||
| vector table[256] vtab trashes a
|
||||
| vector routine trashes a vec
|
||||
| buffer[2048] buf
|
||||
| pointer ptr
|
||||
|
|
||||
@ -146,6 +143,16 @@ User-defined memory addresses of different types.
|
||||
| }
|
||||
= ok
|
||||
|
||||
Tables of different types.
|
||||
|
||||
| table[256] byte tab
|
||||
| table[256] word wtab
|
||||
| table[256] vector routine trashes a vtab
|
||||
|
|
||||
| routine main {
|
||||
| }
|
||||
= ok
|
||||
|
||||
Explicit memory address.
|
||||
|
||||
| byte screen @ 1024
|
||||
@ -178,7 +185,7 @@ Cannot have both initial value and explicit address.
|
||||
|
||||
User-defined locations of other types.
|
||||
|
||||
| byte table[256] screen @ 1024
|
||||
| table[256] byte screen @ 1024
|
||||
| word r1
|
||||
| word r2 @ 60000
|
||||
| word r3 : 2000
|
||||
@ -189,7 +196,7 @@ User-defined locations of other types.
|
||||
|
||||
Initialized byte table.
|
||||
|
||||
| byte table[28] message : "WHAT DO YOU WANT TO DO NEXT?"
|
||||
| table[28] byte message : "WHAT DO YOU WANT TO DO NEXT?"
|
||||
|
|
||||
| routine main {
|
||||
| }
|
||||
@ -291,7 +298,7 @@ Can't define two routines with the same name.
|
||||
|
||||
Declaring byte and word table memory location.
|
||||
|
||||
| byte table[256] tab
|
||||
| table[256] byte tab
|
||||
|
|
||||
| routine main {
|
||||
| ld x, 0
|
||||
@ -302,7 +309,7 @@ Declaring byte and word table memory location.
|
||||
= ok
|
||||
|
||||
| word one
|
||||
| word table[256] many
|
||||
| table[256] word many
|
||||
|
|
||||
| routine main {
|
||||
| ld x, 0
|
||||
@ -314,11 +321,11 @@ Declaring byte and word table memory location.
|
||||
|
||||
Declaring and calling a vector.
|
||||
|
||||
| vector cinv
|
||||
| vector routine
|
||||
| inputs a
|
||||
| outputs x
|
||||
| trashes a, x, z, n
|
||||
| @ 788
|
||||
| cinv @ 788
|
||||
|
|
||||
| routine foo {
|
||||
| ld a, 0
|
||||
@ -345,11 +352,11 @@ Only vectors can be decorated with constraints like that.
|
||||
|
||||
Constraints set may only contain labels.
|
||||
|
||||
| vector cinv
|
||||
| vector routine
|
||||
| inputs a
|
||||
| outputs 200
|
||||
| trashes a, x, z, n
|
||||
| @ 788
|
||||
| cinv @ 788
|
||||
|
|
||||
| routine foo {
|
||||
| ld a, 0
|
||||
@ -364,11 +371,11 @@ Constraints set may only contain labels.
|
||||
|
||||
A vector can name itself in its inputs, outputs, and trashes.
|
||||
|
||||
| vector cinv
|
||||
| vector routine
|
||||
| inputs cinv, a
|
||||
| outputs cinv, x
|
||||
| trashes a, x, z, n
|
||||
| @ 788
|
||||
| cinv @ 788
|
||||
|
|
||||
| routine foo {
|
||||
| ld a, 0
|
||||
@ -384,11 +391,11 @@ A vector can name itself in its inputs, outputs, and trashes.
|
||||
A routine can be copied into a vector before the routine appears in the program,
|
||||
*however*, it must be marked as such with the keyword `forward`.
|
||||
|
||||
| vector cinv
|
||||
| vector routine
|
||||
| inputs cinv, a
|
||||
| outputs cinv, x
|
||||
| trashes a, x, z, n
|
||||
| @ 788
|
||||
| cinv @ 788
|
||||
| routine main {
|
||||
| with interrupts off {
|
||||
| copy foo, cinv
|
||||
@ -400,11 +407,11 @@ A routine can be copied into a vector before the routine appears in the program,
|
||||
| }
|
||||
? SyntaxError: Undefined symbol
|
||||
|
||||
| vector cinv
|
||||
| vector routine
|
||||
| inputs cinv, a
|
||||
| outputs cinv, x
|
||||
| trashes a, x, z, n
|
||||
| @ 788
|
||||
| cinv @ 788
|
||||
| routine main {
|
||||
| with interrupts off {
|
||||
| copy forward foo, cinv
|
||||
@ -434,7 +441,7 @@ goto.
|
||||
| }
|
||||
= ok
|
||||
|
||||
| vector foo
|
||||
| vector routine foo
|
||||
|
|
||||
| routine main {
|
||||
| goto foo
|
||||
|
Loading…
Reference in New Issue
Block a user