git @ Cat's Eye Technologies SixtyPical / 7d56705
Check that the constraints on a routine match those of vector. Chris Pressey 6 years ago
7 changed file(s) with 83 addition(s) and 18 deletion(s). Raw diff Collapse all Expand all
44 -------
55
66 * Added `routine` and `vector` types, and `copy` instruction.
7 * Both routines and vectors can declare `inputs`, `outputs`, and `trashes`,
8 and these must be compatible to assign a routine or vector to a vector.
79
810 0.5
911 ---
3232
3333 For 0.6:
3434
35 * declared `inputs` `outputs` `trashes` on the `vector` type...
36 * we need to get these 3 things onto the type, and also onto routine types
35 * `call` vector (generates an indirect JMP.)
3736 * `goto` (tail call) a routine or a vector.
38 * A more involved demo for the C64 — one that sets up an interrupt.
37 * A more involved demo for the C64 — one that sets up an interrupt?
3938
4039 For 0.7:
4140
0 vector vec
1 inputs y
2 outputs y
3 trashes z, n
4
5 routine foo
6 inputs x
7 outputs x
8 trashes z, n
9 {
10 inc x
11 }
12
13 routine main
14 inputs foo
15 outputs vec
16 trashes a, z, n
17 {
18 copy foo, vec
19 }
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
44 TYPE_BYTE, TYPE_BYTE_TABLE,
5 RoutineType, VectorType,
5 RoutineType, VectorType, ExecutableType,
66 ConstantRef, LocationRef,
77 REG_A, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
88 )
3333
3434
3535 class TypeMismatchError(StaticAnalysisError):
36 pass
37
38
39 class IncompatibleConstraintsError(StaticAnalysisError):
3640 pass
3741
3842
208212 if instr.block2 is not None:
209213 analyze_block(instr.block2, context2, routines)
210214 # TODO may we need to deal with touched separately here too?
215 # probably not; if it wasn't meaningful in the first place, it
216 # doesn't really matter if you modified it or not, coming out.
211217 for ref in context1.each_meaningful():
212218 context2.assert_meaningful(ref, exception_class=InconsistentInitializationError)
213219 for ref in context2.each_meaningful():
224230
225231 # NB I *think* that's enough... but it might not be?
226232 elif opcode == 'copy':
233 # check that their types are basically compatible
227234 if src.type == dest.type:
228235 pass
229 elif isinstance(src.type, RoutineType) and isinstance(dest.type, VectorType):
236 elif isinstance(src.type, ExecutableType) and \
237 isinstance(dest.type, VectorType):
230238 pass
231239 else:
232240 raise TypeMismatchError((src, dest))
241
242 # if dealing with routines and vectors,
243 # check that they're not incompatible
244 if isinstance(src.type, ExecutableType) and \
245 isinstance(dest.type, VectorType):
246 if not (src.type.inputs <= dest.type.inputs):
247 raise IncompatibleConstraintsError(src.type.inputs - dest.type.inputs)
248 if not (src.type.outputs <= dest.type.outputs):
249 raise IncompatibleConstraintsError(src.type.outputs - dest.type.outputs)
250 if not (src.type.trashes <= dest.type.trashes):
251 raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
252
233253 context.assert_meaningful(src)
234254 context.set_written(dest)
235255 context.set_touched(REG_A, FLAG_Z, FLAG_N)
1818 TYPE_BYTE_TABLE = Type('byte table')
1919
2020
21 class InteractionConstrainedType(Type):
21 class ExecutableType(Type):
2222 """Used for routines and vectors."""
2323 def __init__(self, name, inputs=None, outputs=None, trashes=None):
2424 self.name = name
25 self.inputs = inputs or []
26 self.outputs = outputs or []
27 self.trashes = trashes or []
25 self.inputs = inputs or set()
26 self.outputs = outputs or set()
27 self.trashes = trashes or set()
2828
2929 def __repr__(self):
3030 return 'RoutineType(%r, inputs=%r, outputs=%r, trashes=%r)' % (
4343 return hash(self.name) ^ hash(self.inputs) ^ hash(self.outputs) ^ hash(self.trashes)
4444
4545
46 class RoutineType(InteractionConstrainedType):
46 class RoutineType(ExecutableType):
4747 """This memory location contains the code for a routine."""
4848 def __init__(self, **kwargs):
4949 super(RoutineType, self).__init__('routine', **kwargs)
5050
5151
52 class VectorType(InteractionConstrainedType):
52 class VectorType(ExecutableType):
5353 """This memory location contains the address of a routine."""
5454 def __init__(self, **kwargs):
5555 super(VectorType, self).__init__('vector', **kwargs)
148148 return Defn(name=name, addr=addr, location=location)
149149
150150 def constraints(self):
151 inputs = []
152 outputs = []
153 trashes = []
151 inputs = set()
152 outputs = set()
153 trashes = set()
154154 if self.scanner.consume('inputs'):
155 inputs = self.locexprs()
155 inputs = set(self.locexprs())
156156 if self.scanner.consume('outputs'):
157 outputs = self.locexprs()
157 outputs = set(self.locexprs())
158158 if self.scanner.consume('trashes'):
159 trashes = self.locexprs()
159 trashes = set(self.locexprs())
160160 return (inputs, outputs, trashes)
161161
162162 def routine(self):
10931093 | {
10941094 | copy foo, vec
10951095 | }
1096 ? IllegalWriteError
1096 ? IncompatibleConstraintsError
1097
1098 Routines are read-only.
1099
1100 | vector vec
1101 | inputs x
1102 | outputs x
1103 | trashes z, n
1104 |
1105 | routine foo
1106 | inputs x
1107 | outputs x
1108 | trashes z, n
1109 | {
1110 | inc x
1111 | }
1112 |
1113 | routine main
1114 | inputs foo
1115 | outputs vec
1116 | trashes a, z, n
1117 | {
1118 | copy vec, foo
1119 | }
1120 ? TypeMismatchError