Vector and routine types are constructors with constraints now.
Chris Pressey
9 years ago
32 | 32 | |
33 | 33 | For 0.6: |
34 | 34 | |
35 | * declared `inputs` `outputs` `trashes` on the `vector` type. | |
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 | |
36 | 37 | * `goto` (tail call) a routine or a vector. |
37 | 38 | * A more involved demo for the C64 — one that sets up an interrupt. |
38 | 39 |
1 | 1 | |
2 | 2 | from sixtypical.ast import Program, Routine, Block, Instr |
3 | 3 | from sixtypical.model import ( |
4 | TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_ROUTINE, TYPE_VECTOR, | |
4 | TYPE_BYTE, TYPE_BYTE_TABLE, | |
5 | RoutineType, VectorType, | |
5 | 6 | ConstantRef, LocationRef, |
6 | 7 | REG_A, FLAG_Z, FLAG_N, FLAG_V, FLAG_C |
7 | 8 | ) |
223 | 224 | elif opcode == 'copy': |
224 | 225 | if src.type == dest.type: |
225 | 226 | pass |
226 | elif src.type == TYPE_ROUTINE and dest.type == TYPE_VECTOR: | |
227 | elif isinstance(src.type, RoutineType) and isinstance(dest.type, VectorType): | |
227 | 228 | pass |
228 | 229 | else: |
229 | 230 | raise TypeMismatchError((src, dest)) |
2 | 2 | from sixtypical.ast import Program, Routine, Block, Instr |
3 | 3 | from sixtypical.model import ( |
4 | 4 | ConstantRef, LocationRef, |
5 | TYPE_BIT, TYPE_ROUTINE, TYPE_VECTOR, | |
5 | TYPE_BIT, | |
6 | RoutineType, VectorType, | |
6 | 7 | REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C |
7 | 8 | ) |
8 | 9 | from sixtypical.emitter import Byte, Label, Offset |
241 | 242 | self.compile_block(instr.block) |
242 | 243 | self.emitter.emit(CLI()) |
243 | 244 | elif opcode == 'copy': |
244 | if src.type in (TYPE_ROUTINE, TYPE_VECTOR) and dest.type == TYPE_VECTOR: | |
245 | if isinstance(src.type, (RoutineType, VectorType)) and \ | |
246 | isinstance(dest.type, VectorType): | |
245 | 247 | src_label = self.labels[src.name] |
246 | 248 | dest_label = self.labels[dest.name] |
247 | 249 | self.emitter.emit(LDA(Absolute(src_label))) |
16 | 16 | TYPE_BIT = Type('bit') |
17 | 17 | TYPE_BYTE = Type('byte') |
18 | 18 | TYPE_BYTE_TABLE = Type('byte table') |
19 | TYPE_ROUTINE = Type('routine') | |
20 | TYPE_VECTOR = Type('vector') # the mem loc contains an address of a routine | |
19 | ||
20 | ||
21 | class InteractionConstrainedType(Type): | |
22 | """Used for routines and vectors.""" | |
23 | def __init__(self, name, inputs=None, outputs=None, trashes=None): | |
24 | self.name = name | |
25 | self.inputs = inputs or [] | |
26 | self.outputs = outputs or [] | |
27 | self.trashes = trashes or [] | |
28 | ||
29 | def __repr__(self): | |
30 | return 'RoutineType(%r, inputs=%r, outputs=%r, trashes=%r)' % ( | |
31 | self.name, self.inputs, self.outputs, self.trashes | |
32 | ) | |
33 | ||
34 | def __eq__(self, other): | |
35 | return isinstance(other, RoutineType) and ( | |
36 | other.name == self.name and | |
37 | other.inputs == self.inputs and | |
38 | other.outputs == self.outputs and | |
39 | other.trashes == self.trashes | |
40 | ) | |
41 | ||
42 | def __hash__(self): | |
43 | return hash(self.name) ^ hash(self.inputs) ^ hash(self.outputs) ^ hash(self.trashes) | |
44 | ||
45 | ||
46 | class RoutineType(InteractionConstrainedType): | |
47 | """This memory location contains the code for a routine.""" | |
48 | def __init__(self, **kwargs): | |
49 | super(RoutineType, self).__init__('routine', **kwargs) | |
50 | ||
51 | ||
52 | class VectorType(InteractionConstrainedType): | |
53 | """This memory location contains the address of a routine.""" | |
54 | def __init__(self, **kwargs): | |
55 | super(VectorType, self).__init__('vector', **kwargs) | |
21 | 56 | |
22 | 57 | |
23 | 58 | class Ref(object): |
3 | 3 | |
4 | 4 | from sixtypical.ast import Program, Defn, Routine, Block, Instr |
5 | 5 | from sixtypical.model import ( |
6 | TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_ROUTINE, TYPE_VECTOR, | |
6 | TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, | |
7 | RoutineType, VectorType, | |
7 | 8 | LocationRef, ConstantRef |
8 | 9 | ) |
9 | 10 | |
114 | 115 | name = routine.name |
115 | 116 | if name in self.symbols: |
116 | 117 | raise SyntaxError(name) |
117 | self.symbols[name] = SymEntry(routine, LocationRef(TYPE_ROUTINE, name)) | |
118 | ref = LocationRef( | |
119 | RoutineType(inputs=routine.inputs, | |
120 | outputs=routine.outputs, | |
121 | trashes=routine.trashes | |
122 | ), name | |
123 | ) | |
124 | self.symbols[name] = SymEntry(routine, ref) | |
118 | 125 | routines.append(routine) |
119 | 126 | self.scanner.check_type('EOF') |
120 | 127 | return Program(defns=defns, routines=routines) |
127 | 134 | type = TYPE_BYTE_TABLE |
128 | 135 | else: |
129 | 136 | self.scanner.expect('vector') |
130 | type = TYPE_VECTOR | |
137 | type = 'vector' | |
131 | 138 | self.scanner.check_type('identifier') |
132 | 139 | name = self.scanner.token |
133 | 140 | self.scanner.scan() |
134 | 141 | |
135 | 142 | (inputs, outputs, trashes) = self.constraints() |
136 | if type != TYPE_VECTOR and (inputs or outputs or trashes): | |
143 | if type == 'vector': | |
144 | type = VectorType(inputs=inputs, outputs=outputs, trashes=trashes) | |
145 | elif inputs or outputs or trashes: | |
137 | 146 | raise SyntaxError("Cannot apply constraints to non-vector type") |
138 | 147 | |
139 | 148 | addr = None |
259 | 268 | self.scanner.scan() |
260 | 269 | if name not in self.symbols: |
261 | 270 | raise SyntaxError('Undefined routine "%s"' % name) |
262 | if self.symbols[name].model.type != TYPE_ROUTINE: | |
271 | if not isinstance(self.symbols[name].model.type, RoutineType): | |
263 | 272 | raise SyntaxError('Illegal call of non-routine "%s"' % name) |
264 | 273 | return Instr(opcode=opcode, name=name, dest=None, src=None) |
265 | 274 | elif self.scanner.token in ("copy",): |