mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-22 01:32:13 +00:00
Check that the constraints on a routine match those of vector.
This commit is contained in:
parent
3010435add
commit
7d56705530
@ -5,6 +5,8 @@ History of SixtyPical
|
||||
-------
|
||||
|
||||
* Added `routine` and `vector` types, and `copy` instruction.
|
||||
* Both routines and vectors can declare `inputs`, `outputs`, and `trashes`,
|
||||
and these must be compatible to assign a routine or vector to a vector.
|
||||
|
||||
0.5
|
||||
---
|
||||
|
@ -33,10 +33,9 @@ TODO
|
||||
|
||||
For 0.6:
|
||||
|
||||
* declared `inputs` `outputs` `trashes` on the `vector` type...
|
||||
* we need to get these 3 things onto the type, and also onto routine types
|
||||
* `call` vector (generates an indirect JMP.)
|
||||
* `goto` (tail call) a routine or a vector.
|
||||
* A more involved demo for the C64 — one that sets up an interrupt.
|
||||
* A more involved demo for the C64 — one that sets up an interrupt?
|
||||
|
||||
For 0.7:
|
||||
|
||||
|
20
eg/bad-vector.60p
Normal file
20
eg/bad-vector.60p
Normal file
@ -0,0 +1,20 @@
|
||||
vector vec
|
||||
inputs y
|
||||
outputs y
|
||||
trashes z, n
|
||||
|
||||
routine foo
|
||||
inputs x
|
||||
outputs x
|
||||
trashes z, n
|
||||
{
|
||||
inc x
|
||||
}
|
||||
|
||||
routine main
|
||||
inputs foo
|
||||
outputs vec
|
||||
trashes a, z, n
|
||||
{
|
||||
copy foo, vec
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
from sixtypical.ast import Program, Routine, Block, Instr
|
||||
from sixtypical.model import (
|
||||
TYPE_BYTE, TYPE_BYTE_TABLE,
|
||||
RoutineType, VectorType,
|
||||
RoutineType, VectorType, ExecutableType,
|
||||
ConstantRef, LocationRef,
|
||||
REG_A, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
|
||||
)
|
||||
@ -37,6 +37,10 @@ class TypeMismatchError(StaticAnalysisError):
|
||||
pass
|
||||
|
||||
|
||||
class IncompatibleConstraintsError(StaticAnalysisError):
|
||||
pass
|
||||
|
||||
|
||||
class Context():
|
||||
"""
|
||||
A location is touched if it was changed (or even potentially
|
||||
@ -209,6 +213,8 @@ def analyze_instr(instr, context, routines):
|
||||
if instr.block2 is not None:
|
||||
analyze_block(instr.block2, context2, routines)
|
||||
# TODO may we need to deal with touched separately here too?
|
||||
# probably not; if it wasn't meaningful in the first place, it
|
||||
# doesn't really matter if you modified it or not, coming out.
|
||||
for ref in context1.each_meaningful():
|
||||
context2.assert_meaningful(ref, exception_class=InconsistentInitializationError)
|
||||
for ref in context2.each_meaningful():
|
||||
@ -225,12 +231,26 @@ def analyze_instr(instr, context, routines):
|
||||
|
||||
# NB I *think* that's enough... but it might not be?
|
||||
elif opcode == 'copy':
|
||||
# check that their types are basically compatible
|
||||
if src.type == dest.type:
|
||||
pass
|
||||
elif isinstance(src.type, RoutineType) and isinstance(dest.type, VectorType):
|
||||
elif isinstance(src.type, ExecutableType) and \
|
||||
isinstance(dest.type, VectorType):
|
||||
pass
|
||||
else:
|
||||
raise TypeMismatchError((src, dest))
|
||||
|
||||
# if dealing with routines and vectors,
|
||||
# check that they're not incompatible
|
||||
if isinstance(src.type, ExecutableType) and \
|
||||
isinstance(dest.type, VectorType):
|
||||
if not (src.type.inputs <= dest.type.inputs):
|
||||
raise IncompatibleConstraintsError(src.type.inputs - dest.type.inputs)
|
||||
if not (src.type.outputs <= dest.type.outputs):
|
||||
raise IncompatibleConstraintsError(src.type.outputs - dest.type.outputs)
|
||||
if not (src.type.trashes <= dest.type.trashes):
|
||||
raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
|
||||
|
||||
context.assert_meaningful(src)
|
||||
context.set_written(dest)
|
||||
context.set_touched(REG_A, FLAG_Z, FLAG_N)
|
||||
|
@ -19,13 +19,13 @@ TYPE_BYTE = Type('byte')
|
||||
TYPE_BYTE_TABLE = Type('byte table')
|
||||
|
||||
|
||||
class InteractionConstrainedType(Type):
|
||||
class ExecutableType(Type):
|
||||
"""Used for routines and vectors."""
|
||||
def __init__(self, name, inputs=None, outputs=None, trashes=None):
|
||||
self.name = name
|
||||
self.inputs = inputs or []
|
||||
self.outputs = outputs or []
|
||||
self.trashes = trashes or []
|
||||
self.inputs = inputs or set()
|
||||
self.outputs = outputs or set()
|
||||
self.trashes = trashes or set()
|
||||
|
||||
def __repr__(self):
|
||||
return 'RoutineType(%r, inputs=%r, outputs=%r, trashes=%r)' % (
|
||||
@ -44,13 +44,13 @@ class InteractionConstrainedType(Type):
|
||||
return hash(self.name) ^ hash(self.inputs) ^ hash(self.outputs) ^ hash(self.trashes)
|
||||
|
||||
|
||||
class RoutineType(InteractionConstrainedType):
|
||||
class RoutineType(ExecutableType):
|
||||
"""This memory location contains the code for a routine."""
|
||||
def __init__(self, **kwargs):
|
||||
super(RoutineType, self).__init__('routine', **kwargs)
|
||||
|
||||
|
||||
class VectorType(InteractionConstrainedType):
|
||||
class VectorType(ExecutableType):
|
||||
"""This memory location contains the address of a routine."""
|
||||
def __init__(self, **kwargs):
|
||||
super(VectorType, self).__init__('vector', **kwargs)
|
||||
|
@ -149,15 +149,15 @@ class Parser(object):
|
||||
return Defn(name=name, addr=addr, location=location)
|
||||
|
||||
def constraints(self):
|
||||
inputs = []
|
||||
outputs = []
|
||||
trashes = []
|
||||
inputs = set()
|
||||
outputs = set()
|
||||
trashes = set()
|
||||
if self.scanner.consume('inputs'):
|
||||
inputs = self.locexprs()
|
||||
inputs = set(self.locexprs())
|
||||
if self.scanner.consume('outputs'):
|
||||
outputs = self.locexprs()
|
||||
outputs = set(self.locexprs())
|
||||
if self.scanner.consume('trashes'):
|
||||
trashes = self.locexprs()
|
||||
trashes = set(self.locexprs())
|
||||
return (inputs, outputs, trashes)
|
||||
|
||||
def routine(self):
|
||||
|
@ -1094,4 +1094,28 @@ But not if the vector is declared inappropriately.
|
||||
| {
|
||||
| copy foo, vec
|
||||
| }
|
||||
? IllegalWriteError
|
||||
? IncompatibleConstraintsError
|
||||
|
||||
Routines are read-only.
|
||||
|
||||
| vector vec
|
||||
| inputs x
|
||||
| outputs x
|
||||
| trashes z, n
|
||||
|
|
||||
| routine foo
|
||||
| inputs x
|
||||
| outputs x
|
||||
| trashes z, n
|
||||
| {
|
||||
| inc x
|
||||
| }
|
||||
|
|
||||
| routine main
|
||||
| inputs foo
|
||||
| outputs vec
|
||||
| trashes a, z, n
|
||||
| {
|
||||
| copy vec, foo
|
||||
| }
|
||||
? TypeMismatchError
|
||||
|
Loading…
Reference in New Issue
Block a user