git @ Cat's Eye Technologies SixtyPical / 32389e4
Require that the program does ^buf to get at the address of buf. Chris Pressey 4 years ago
9 changed file(s) with 72 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
66 trashes a, z, n, ptr
77 {
88 ld y, 0
9 copy buf, ptr
9 copy ^buf, ptr
1010 copy 123, [ptr] + y
1111 }
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
44 TYPE_BYTE, TYPE_BYTE_TABLE, BufferType, PointerType, VectorType, ExecutableType,
5 ConstantRef, LocationRef, IndirectRef,
5 ConstantRef, LocationRef, IndirectRef, AddressRef,
66 REG_A, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
77 )
88
112112 def assert_meaningful(self, *refs, **kwargs):
113113 exception_class = kwargs.get('exception_class', UnmeaningfulReadError)
114114 for ref in refs:
115 if isinstance(ref, ConstantRef) or ref in self.routines:
115 if ref.is_constant() or ref in self.routines:
116116 pass
117117 elif isinstance(ref, LocationRef):
118118 if ref not in self._meaningful:
292292 context.assert_meaningful(src)
293293
294294 elif opcode == 'copy':
295 # check that their types are compatible
295 # 1. check that their types are compatible
296296
297297 if isinstance(dest, IndirectRef):
298298 if src.type == TYPE_BYTE and isinstance(dest.ref.type, PointerType):
299299 pass
300300 else:
301301 raise TypeMismatchError((src, dest))
302 elif src.type == dest.type:
303 pass
304 elif isinstance(src.type, ExecutableType) and \
305 isinstance(dest.type, VectorType):
306 pass
307 elif isinstance(src.type, BufferType) and \
308 isinstance(dest.type, PointerType):
309 pass
302 elif isinstance(src, AddressRef):
303 if isinstance(src.ref.type, BufferType) and isinstance(dest.type, PointerType):
304 pass
305 else:
306 raise TypeMismatchError((src, dest))
307
308 elif isinstance(src, (LocationRef, ConstantRef)) and isinstance(dest, LocationRef):
309 if src.type == dest.type:
310 pass
311 elif isinstance(src.type, ExecutableType) and \
312 isinstance(dest.type, VectorType):
313 # if dealing with routines and vectors,
314 # check that they're not incompatible
315 if not (src.type.inputs <= dest.type.inputs):
316 raise IncompatibleConstraintsError(src.type.inputs - dest.type.inputs)
317 if not (src.type.outputs <= dest.type.outputs):
318 raise IncompatibleConstraintsError(src.type.outputs - dest.type.outputs)
319 if not (src.type.trashes <= dest.type.trashes):
320 raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
321 else:
322 raise TypeMismatchError((src, dest))
310323 else:
311324 raise TypeMismatchError((src, dest))
312325
313 # if dealing with routines and vectors,
314 # check that they're not incompatible
315 if isinstance(src.type, ExecutableType) and \
316 isinstance(dest.type, VectorType):
317 if not (src.type.inputs <= dest.type.inputs):
318 raise IncompatibleConstraintsError(src.type.inputs - dest.type.inputs)
319 if not (src.type.outputs <= dest.type.outputs):
320 raise IncompatibleConstraintsError(src.type.outputs - dest.type.outputs)
321 if not (src.type.trashes <= dest.type.trashes):
322 raise IncompatibleConstraintsError(src.type.trashes - dest.type.trashes)
326 # 2. check that the context is meaningful
323327
324328 if isinstance(dest, IndirectRef):
325329 context.assert_meaningful(src, REG_Y)
11
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
4 ConstantRef, IndirectRef,
4 ConstantRef, LocationRef, IndirectRef, AddressRef,
55 TYPE_BIT, TYPE_BYTE, TYPE_WORD, BufferType, PointerType, RoutineType, VectorType,
66 REG_A, REG_X, REG_Y, FLAG_C
77 )
283283 raise NotImplementedError((src, dest))
284284 else:
285285 raise NotImplementedError((src, dest))
286 elif isinstance(src, AddressRef) and isinstance(dest, LocationRef) and \
287 isinstance(src.ref.type, BufferType) and isinstance(dest.type, PointerType):
288 src_label = self.labels[src.ref.name]
289 dest_label = self.labels[dest.name]
290 self.emitter.emit(LDA(Immediate(HighAddressByte(src_label))))
291 self.emitter.emit(STA(ZeroPage(dest_label)))
292 self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
293 self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
294 elif not isinstance(src, (ConstantRef, LocationRef)) or not isinstance(dest, LocationRef):
295 raise NotImplementedError((src, dest))
286296 elif src.type == TYPE_BYTE and dest.type == TYPE_BYTE:
287297 if isinstance(src, ConstantRef):
288298 raise NotImplementedError
307317 self.emitter.emit(STA(Absolute(dest_label)))
308318 self.emitter.emit(LDA(Absolute(Offset(src_label, 1))))
309319 self.emitter.emit(STA(Absolute(Offset(dest_label, 1))))
310 elif isinstance(src.type, BufferType) and isinstance(dest.type, PointerType):
311 # TODO: this maybe should not be the 'copy' opcode at all that means this
312 src_label = self.labels[src.name]
313 dest_label = self.labels[dest.name]
314 self.emitter.emit(LDA(Immediate(HighAddressByte(src_label))))
315 self.emitter.emit(STA(ZeroPage(dest_label)))
316 self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
317 self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
318320 elif isinstance(src.type, VectorType) and isinstance(dest.type, VectorType):
319321 src_label = self.labels[src.name]
320322 dest_label = self.labels[dest.name]
108108 return self.ref == other.ref
109109
110110 def __hash__(self):
111 return hash(hash('[]') ^ hash(self.ref))
111 return hash(self.__class__.name) ^ hash(self.ref)
112112
113113 def __repr__(self):
114114 return '%s(%r)' % (self.__class__.__name__, self.ref)
119119
120120 def is_constant(self):
121121 return False
122
123
124 class AddressRef(Ref):
125 def __init__(self, ref):
126 self.ref = ref
127
128 def __eq__(self, other):
129 return self.ref == other.ref
130
131 def __hash__(self):
132 return hash(self.__class__.name) ^ hash(self.ref)
133
134 def __repr__(self):
135 return '%s(%r)' % (self.__class__.__name__, self.ref)
136
137 @property
138 def name(self):
139 return '^{}'.format(self.ref.name)
140
141 def is_constant(self):
142 return True
122143
123144
124145 class PartRef(Ref):
33 from sixtypical.model import (
44 TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
55 RoutineType, VectorType, ExecutableType, BufferType, PointerType,
6 LocationRef, ConstantRef, IndirectRef,
6 LocationRef, ConstantRef, IndirectRef, AddressRef,
77 )
88 from sixtypical.scanner import Scanner
99
170170 self.scanner.expect('+')
171171 self.scanner.expect('y')
172172 return IndirectRef(loc)
173 elif self.scanner.consume('^'):
174 loc = self.locexpr()
175 return AddressRef(loc)
173176 else:
174177 return self.locexpr()
175178
2828 self.token = None
2929 self.type = 'EOF'
3030 return
31 if self.scan_pattern(r'\,|\@|\+|\:|\<|\>|\{|\}|\[|\]', 'operator'):
31 if self.scan_pattern(r'\,|\@|\+|\:|\<|\>|\{|\}|\[|\]|\^', 'operator'):
3232 return
3333 if self.scan_pattern(r'\d+', 'integer literal'):
3434 return
11751175
11761176 Buffers and pointers.
11771177
1178 Note that `copy buf, ptr` should probably be `copy ^buf, ptr` and `^buf` should not
1179 be considered "reading" buf and should not require it in `inputs` for that reason.
1178 Note that `^buf` is not considered "reading" buf, so does not require it in `inputs`.
1179 TODO: It *should* require it in `outputs`.
11801180
11811181 | buffer[2048] buf
11821182 | pointer ptr
11831183 |
11841184 | routine main
1185 | inputs buf
1186 | outputs buf, y
1185 | outputs y
11871186 | trashes a, z, n, ptr
11881187 | {
11891188 | ld y, 0
1190 | copy buf, ptr
1189 | copy ^buf, ptr
11911190 | copy 123, [ptr] + y
11921191 | }
11931192 = ok
11981197 | pointer ptr
11991198 |
12001199 | routine main
1201 | inputs buf
1202 | outputs buf
12031200 | trashes a, z, n, ptr
12041201 | {
1205 | copy buf, ptr
1202 | copy ^buf, ptr
12061203 | copy 123, [ptr] + y
12071204 | }
12081205 ? UnmeaningfulReadError
352352 | trashes a, z, n, ptr
353353 | {
354354 | ld y, 0
355 | copy buf, ptr
355 | copy ^buf, ptr
356356 | }
357357 = 00c0a000a90b85fea9c085ff60
358358
362362 | pointer ptr @ 254
363363 |
364364 | routine main
365 | inputs buf
366365 | outputs buf, y
367366 | trashes a, z, n, ptr
368367 | {
369368 | ld y, 0
370 | copy buf, ptr
369 | copy ^buf, ptr
371370 | copy 123, [ptr] + y
372371 | }
373372 = 00c0a000a90f85fea9c085ffa97b91fe60
327327 | pointer ptr
328328 |
329329 | routine main {
330 | copy buf, ptr
330 | copy ^buf, ptr
331331 | copy 123, [ptr] + y
332332 | }
333333 = ok