git @ Cat's Eye Technologies SixtyPical / 548905d
Initialized byte tables need not have all 256 bytes initialized. Chris Pressey 3 years ago
12 changed file(s) with 93 addition(s) and 320 deletion(s). Raw diff Collapse all Expand all
00 History of SixtyPical
11 =====================
2
3 0.11
4 ----
5
6 * Each table has a specified size now (although, bounds checking is not performed.)
7 * Initialized `byte table` values need not have all 256 bytes initialized.
28
39 0.10
410 ----
1117 * Subtract word (constant or memory location) from word memory location.
1218 * `trash` instruction explicitly indicates a value is no longer considered meaningful.
1319 * `copy []+y, a` can indirectly read a byte value into the `a` register.
20 * Initialized `byte table` memory locations.
1421 * Fixed bug which was preventing `if` branches to diverge in what they initialized,
1522 if it was already initialized when going into the `if`.
1623 * Fixed a bug which was making it crash when trying to analyze `repeat forever` loops.
00 SixtyPical
11 ==========
2
3 _Version 0.11. Work-in-progress, everything is subject to change._
24
35 SixtyPical is a very low-level programming language, similar to 6502 assembly,
46 with static analysis through abstract interpretation.
2022
2123 The reference implementation can execute, analyze, and compile SixtyPical
2224 programs to 6502 machine code.
23
24 SixtyPical is a work in progress. The current released version of SixtyPical
25 is 0.10.
2625
2726 Documentation
2827 -------------
8281 ### And at some point...
8382
8483 * Check that the buffer being read or written to through pointer, appears in approporiate inputs or outputs set.
85 * `byte table` and `word table` of sizes other than 256
8684 * always analyze before executing or compiling, unless told not to
8785 * `interrupt` routines -- to indicate that "the supervisor" has stored values on the stack, so we can trash them.
8886 * error messages that include the line number of the source code
00 SixtyPical
11 ==========
22
3 This document describes the SixtyPical programming language version 0.10,
3 This document describes the SixtyPical programming language version 0.11,
44 both its execution aspect and its static analysis aspect (even though
55 these are, technically speaking, separate concepts.)
66
2424
2525 There are also two *type constructors*:
2626
27 * T table (256 entries, each holding a value of type T, where T is either
28 `byte` or `word`)
27 * T table (up to 256 entries, each holding a value of type T, where T is
28 either `byte` or `word`)
2929 * buffer[N] (N entries; each entry is a byte; N is a power of 2, ≤ 64K)
3030
3131 Memory locations
88 byte vic_border @ 53280
99 byte vic_bg @ 53281
1010
11 byte table screen1 @ 1024
12 byte table screen2 @ 1274
13 byte table screen3 @ 1524
14 byte table screen4 @ 1774
15
16 byte table colormap1 @ 55296
17 byte table colormap2 @ 55546
18 byte table colormap3 @ 55796
19 byte table colormap4 @ 56046
11 byte table[256] screen1 @ 1024
12 byte table[256] screen2 @ 1274
13 byte table[256] screen3 @ 1524
14 byte table[256] screen4 @ 1774
15
16 byte table[256] colormap1 @ 55296
17 byte table[256] colormap2 @ 55546
18 byte table[256] colormap3 @ 55796
19 byte table[256] colormap4 @ 56046
2020
2121 buffer[2048] screen @ 1024
2222 byte joy2 @ $dc00
2727
2828 pointer ptr @ 254
2929
30 word table actor_pos
30 word table[256] actor_pos
3131 word pos
3232 word new_pos
3333
34 word table actor_delta
34 word table[256] actor_delta
3535 word delta
3636
3737 byte button_down : 0 // effectively static-local to check_button
38 byte table press_fire_msg: "PRESS`FIRE`TO`PLAY"
38 byte table[18] press_fire_msg: "PRESS`FIRE`TO`PLAY"
3939
4040 byte save_x
4141 word compare_target
11
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
4 TYPE_BYTE, TYPE_WORD, TYPE_BYTE_TABLE, TYPE_WORD_TABLE, BufferType, PointerType, VectorType, ExecutableType,
4 TYPE_BYTE, TYPE_WORD,
5 TableType, BufferType, PointerType, VectorType, ExecutableType,
56 ConstantRef, LocationRef, IndirectRef, IndexedRef, AddressRef,
67 REG_A, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
78 )
230231
231232 if opcode == 'ld':
232233 if instr.index:
233 if src.type == TYPE_BYTE_TABLE and dest.type == TYPE_BYTE:
234 if isinstance(src.type, TableType) and src.type.of_type == TYPE_BYTE and dest.type == TYPE_BYTE:
234235 pass
235236 else:
236237 raise TypeMismatchError('%s and %s in %s' %
244245 context.set_written(dest, FLAG_Z, FLAG_N)
245246 elif opcode == 'st':
246247 if instr.index:
247 if src.type == TYPE_BYTE and dest.type == TYPE_BYTE_TABLE:
248 if src.type == TYPE_BYTE and isinstance(dest.type, TableType) and dest.type.of_type == TYPE_BYTE:
248249 pass
249250 else:
250251 raise TypeMismatchError((src, dest))
360361 raise TypeMismatchError((src, dest))
361362
362363 elif isinstance(src, (LocationRef, ConstantRef)) and isinstance(dest, IndexedRef):
363 if src.type == TYPE_WORD and dest.ref.type == TYPE_WORD_TABLE:
364 if src.type == TYPE_WORD and isinstance(dest.ref.type, TableType) and dest.ref.type.of_type == TYPE_WORD:
364365 pass
365366 else:
366367 raise TypeMismatchError((src, dest))
367368
368369 elif isinstance(src, IndexedRef) and isinstance(dest, LocationRef):
369 if src.ref.type == TYPE_WORD_TABLE and dest.type == TYPE_WORD:
370 if isinstance(src.ref.type, TableType) and src.ref.type.of_type == TYPE_WORD and dest.type == TYPE_WORD:
370371 pass
371372 else:
372373 raise TypeMismatchError((src, dest))
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
44 ConstantRef, LocationRef, IndexedRef, IndirectRef, AddressRef,
5 TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE, BufferType, PointerType, RoutineType, VectorType,
5 TYPE_BIT, TYPE_BYTE, TYPE_WORD,
6 TableType, BufferType, PointerType, RoutineType, VectorType,
67 REG_A, REG_X, REG_Y, FLAG_C
78 )
89 from sixtypical.emitter import Byte, Word, Table, Label, Offset, LowAddressByte, HighAddressByte
2324 pass
2425
2526
27 def is_a_table_type(x, of_type):
28 return isinstance(x, TableType) and x.of_type == of_type
29
30
2631 class Compiler(object):
2732 def __init__(self, emitter):
2833 self.emitter = emitter
5358 length = 1
5459 elif type_ == TYPE_WORD or isinstance(type_, (PointerType, VectorType)):
5560 length = 2
56 elif type_ == TYPE_BYTE_TABLE:
57 length = 256
58 elif type_ == TYPE_WORD_TABLE:
59 length = 512
61 elif isinstance(type_, TableType):
62 length = type_.size * (1 if type_.of_type == TYPE_BYTE else 2)
6063 elif isinstance(type_, BufferType):
6164 length = type_.size
6265 if length is None:
8992 initial_data = Byte(defn.initial)
9093 elif type_ == TYPE_WORD:
9194 initial_data = Word(defn.initial)
92 elif type_ == TYPE_BYTE_TABLE:
93 initial_data = Table(defn.initial)
95 elif is_a_table_type(type_, TYPE_BYTE):
96 initial_data = Table(defn.initial, type_.size)
9497 else:
9598 raise NotImplementedError(type_)
9699 label.set_length(initial_data.size())
403406 self.emitter.emit(LDA(Immediate(LowAddressByte(src_label))))
404407 self.emitter.emit(STA(ZeroPage(Offset(dest_label, 1))))
405408 elif isinstance(src, LocationRef) and isinstance(dest, IndexedRef):
406 if src.type == TYPE_WORD and dest.ref.type == TYPE_WORD_TABLE:
409 if src.type == TYPE_WORD and is_a_table_type(dest.ref.type, TYPE_WORD):
407410 src_label = self.labels[src.name]
408411 dest_label = self.labels[dest.ref.name]
409412 self.emitter.emit(LDA(Absolute(src_label)))
413416 else:
414417 raise NotImplementedError
415418 elif isinstance(src, ConstantRef) and isinstance(dest, IndexedRef):
416 if src.type == TYPE_WORD and dest.ref.type == TYPE_WORD_TABLE:
419 if src.type == TYPE_WORD and is_a_table_type(dest.ref.type, TYPE_WORD):
417420 dest_label = self.labels[dest.ref.name]
418421 self.emitter.emit(LDA(Immediate(Byte(src.low_byte()))))
419422 self.emitter.emit(STA(self.addressing_mode_for_index(dest.index)(dest_label)))
422425 else:
423426 raise NotImplementedError
424427 elif isinstance(src, IndexedRef) and isinstance(dest, LocationRef):
425 if src.ref.type == TYPE_WORD_TABLE and dest.type == TYPE_WORD:
428 if is_a_table_type(src.ref.type, TYPE_WORD) and dest.type == TYPE_WORD:
426429 src_label = self.labels[src.ref.name]
427430 dest_label = self.labels[dest.name]
428431 self.emitter.emit(LDA(self.addressing_mode_for_index(src.index)(src_label)))
4747
4848
4949 class Table(Emittable):
50 def __init__(self, value):
50 def __init__(self, value, size):
5151 # TODO: range-checking
5252 self.value = value
53 self._size = size
5354
5455 def size(self):
55 return 256
56 return self._size
5657
5758 def serialize(self, addr=None):
5859 bytes = []
1919
2020 TYPE_BIT = Type('bit')
2121 TYPE_BYTE = Type('byte')
22 TYPE_BYTE_TABLE = Type('byte table')
2322 TYPE_WORD = Type('word')
24 TYPE_WORD_TABLE = Type('word table')
2523
2624
2725 class ExecutableType(Type):
5957 """This memory location contains the address of a routine."""
6058 def __init__(self, **kwargs):
6159 super(VectorType, self).__init__('vector', **kwargs)
60
61
62 class TableType(Type):
63 def __init__(self, of_type, size):
64 self.of_type = of_type
65 self.size = size
66 self.name = '{} table[{}]'.format(self.of_type.name, self.size)
6267
6368
6469 class BufferType(Type):
11
22 from sixtypical.ast import Program, Defn, Routine, Block, Instr
33 from sixtypical.model import (
4 TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
5 RoutineType, VectorType, ExecutableType, BufferType, PointerType,
4 TYPE_BIT, TYPE_BYTE, TYPE_WORD,
5 RoutineType, VectorType, ExecutableType, TableType, BufferType, PointerType,
66 LocationRef, ConstantRef, IndirectRef, IndexedRef, AddressRef,
77 )
88 from sixtypical.scanner import Scanner
8888
8989 initial = None
9090 if self.scanner.consume(':'):
91 if type_ == TYPE_BYTE_TABLE and self.scanner.on_type('string literal'):
91 if isinstance(type_, TableType) and self.scanner.on_type('string literal'):
9292 initial = self.scanner.token
9393 else:
9494 self.scanner.check_type('integer literal')
108108
109109 return Defn(name=name, addr=addr, initial=initial, location=location)
110110
111 def defn_size(self):
112 self.scanner.expect('[')
113 self.scanner.check_type('integer literal')
114 size = int(self.scanner.token)
115 self.scanner.scan()
116 self.scanner.expect(']')
117 return size
118
111119 def defn_type(self):
112120 if self.scanner.consume('byte'):
113121 if self.scanner.consume('table'):
114 return TYPE_BYTE_TABLE
122 size = self.defn_size()
123 return TableType(TYPE_BYTE, size)
115124 return TYPE_BYTE
116125 elif self.scanner.consume('word'):
117126 if self.scanner.consume('table'):
118 return TYPE_WORD_TABLE
127 size = self.defn_size()
128 return TableType(TYPE_WORD, size)
119129 return TYPE_WORD
120130 elif self.scanner.consume('vector'):
121131 return 'vector' # will be resolved to a Type by caller
122132 elif self.scanner.consume('buffer'):
123 self.scanner.expect('[')
124 self.scanner.check_type('integer literal')
125 size = int(self.scanner.token)
126 self.scanner.scan()
127 self.scanner.expect(']')
133 size = self.defn_size()
128134 return BufferType(size)
129135 else:
130136 self.scanner.expect('pointer')
242242 Storing to a table, you must use an index, and vice-versa.
243243
244244 | byte one
245 | byte table many
245 | byte table[256] many
246246 |
247247 | routine main
248248 | outputs one
255255 = ok
256256
257257 | byte one
258 | byte table many
258 | byte table[256] many
259259 |
260260 | routine main
261261 | outputs many
268268 ? TypeMismatchError
269269
270270 | byte one
271 | byte table many
271 | byte table[256] many
272272 |
273273 | routine main
274274 | outputs one
281281 ? TypeMismatchError
282282
283283 | byte one
284 | byte table many
284 | byte table[256] many
285285 |
286286 | routine main
287287 | outputs many
319319 | }
320320 ? TypeMismatchError
321321
322 | byte table many
322 | byte table[256] many
323323 |
324324 | routine main
325325 | outputs many
332332 | }
333333 ? TypeMismatchError
334334
335 | byte table many
335 | byte table[256] many
336336 |
337337 | routine main
338338 | outputs many
348348 Copying to and from a word table.
349349
350350 | word one
351 | word table many
351 | word table[256] many
352352 |
353353 | routine main
354354 | inputs one, many
362362 = ok
363363
364364 | word one
365 | word table many
365 | word table[256] many
366366 |
367367 | routine main
368368 | inputs one, many
375375 ? TypeMismatchError
376376
377377 | word one
378 | word table many
378 | word table[256] many
379379 |
380380 | routine main
381381 | inputs one, many
389389
390390 You can also copy a literal word to a word table.
391391
392 | word table many
392 | word table[256] many
393393 |
394394 | routine main
395395 | inputs many
136136 = $081A .byte $BB
137137 = $081B .byte $0B
138138
139 Initialized byte table.
140
141 | byte table message : "WHAT?"
139 Initialized byte table. Bytes allocated, but beyond the string, are 0's.
140
141 | byte table[8] message : "WHAT?"
142142 |
143143 | routine main
144144 | inputs message
157157 = $0818 BRK
158158 = $0819 BRK
159159 = $081A BRK
160 = $081B BRK
161 = $081C BRK
162 = $081D BRK
163 = $081E BRK
164 = $081F BRK
165 = $0820 BRK
166 = $0821 BRK
167 = $0822 BRK
168 = $0823 BRK
169 = $0824 BRK
170 = $0825 BRK
171 = $0826 BRK
172 = $0827 BRK
173 = $0828 BRK
174 = $0829 BRK
175 = $082A BRK
176 = $082B BRK
177 = $082C BRK
178 = $082D BRK
179 = $082E BRK
180 = $082F BRK
181 = $0830 BRK
182 = $0831 BRK
183 = $0832 BRK
184 = $0833 BRK
185 = $0834 BRK
186 = $0835 BRK
187 = $0836 BRK
188 = $0837 BRK
189 = $0838 BRK
190 = $0839 BRK
191 = $083A BRK
192 = $083B BRK
193 = $083C BRK
194 = $083D BRK
195 = $083E BRK
196 = $083F BRK
197 = $0840 BRK
198 = $0841 BRK
199 = $0842 BRK
200 = $0843 BRK
201 = $0844 BRK
202 = $0845 BRK
203 = $0846 BRK
204 = $0847 BRK
205 = $0848 BRK
206 = $0849 BRK
207 = $084A BRK
208 = $084B BRK
209 = $084C BRK
210 = $084D BRK
211 = $084E BRK
212 = $084F BRK
213 = $0850 BRK
214 = $0851 BRK
215 = $0852 BRK
216 = $0853 BRK
217 = $0854 BRK
218 = $0855 BRK
219 = $0856 BRK
220 = $0857 BRK
221 = $0858 BRK
222 = $0859 BRK
223 = $085A BRK
224 = $085B BRK
225 = $085C BRK
226 = $085D BRK
227 = $085E BRK
228 = $085F BRK
229 = $0860 BRK
230 = $0861 BRK
231 = $0862 BRK
232 = $0863 BRK
233 = $0864 BRK
234 = $0865 BRK
235 = $0866 BRK
236 = $0867 BRK
237 = $0868 BRK
238 = $0869 BRK
239 = $086A BRK
240 = $086B BRK
241 = $086C BRK
242 = $086D BRK
243 = $086E BRK
244 = $086F BRK
245 = $0870 BRK
246 = $0871 BRK
247 = $0872 BRK
248 = $0873 BRK
249 = $0874 BRK
250 = $0875 BRK
251 = $0876 BRK
252 = $0877 BRK
253 = $0878 BRK
254 = $0879 BRK
255 = $087A BRK
256 = $087B BRK
257 = $087C BRK
258 = $087D BRK
259 = $087E BRK
260 = $087F BRK
261 = $0880 BRK
262 = $0881 BRK
263 = $0882 BRK
264 = $0883 BRK
265 = $0884 BRK
266 = $0885 BRK
267 = $0886 BRK
268 = $0887 BRK
269 = $0888 BRK
270 = $0889 BRK
271 = $088A BRK
272 = $088B BRK
273 = $088C BRK
274 = $088D BRK
275 = $088E BRK
276 = $088F BRK
277 = $0890 BRK
278 = $0891 BRK
279 = $0892 BRK
280 = $0893 BRK
281 = $0894 BRK
282 = $0895 BRK
283 = $0896 BRK
284 = $0897 BRK
285 = $0898 BRK
286 = $0899 BRK
287 = $089A BRK
288 = $089B BRK
289 = $089C BRK
290 = $089D BRK
291 = $089E BRK
292 = $089F BRK
293 = $08A0 BRK
294 = $08A1 BRK
295 = $08A2 BRK
296 = $08A3 BRK
297 = $08A4 BRK
298 = $08A5 BRK
299 = $08A6 BRK
300 = $08A7 BRK
301 = $08A8 BRK
302 = $08A9 BRK
303 = $08AA BRK
304 = $08AB BRK
305 = $08AC BRK
306 = $08AD BRK
307 = $08AE BRK
308 = $08AF BRK
309 = $08B0 BRK
310 = $08B1 BRK
311 = $08B2 BRK
312 = $08B3 BRK
313 = $08B4 BRK
314 = $08B5 BRK
315 = $08B6 BRK
316 = $08B7 BRK
317 = $08B8 BRK
318 = $08B9 BRK
319 = $08BA BRK
320 = $08BB BRK
321 = $08BC BRK
322 = $08BD BRK
323 = $08BE BRK
324 = $08BF BRK
325 = $08C0 BRK
326 = $08C1 BRK
327 = $08C2 BRK
328 = $08C3 BRK
329 = $08C4 BRK
330 = $08C5 BRK
331 = $08C6 BRK
332 = $08C7 BRK
333 = $08C8 BRK
334 = $08C9 BRK
335 = $08CA BRK
336 = $08CB BRK
337 = $08CC BRK
338 = $08CD BRK
339 = $08CE BRK
340 = $08CF BRK
341 = $08D0 BRK
342 = $08D1 BRK
343 = $08D2 BRK
344 = $08D3 BRK
345 = $08D4 BRK
346 = $08D5 BRK
347 = $08D6 BRK
348 = $08D7 BRK
349 = $08D8 BRK
350 = $08D9 BRK
351 = $08DA BRK
352 = $08DB BRK
353 = $08DC BRK
354 = $08DD BRK
355 = $08DE BRK
356 = $08DF BRK
357 = $08E0 BRK
358 = $08E1 BRK
359 = $08E2 BRK
360 = $08E3 BRK
361 = $08E4 BRK
362 = $08E5 BRK
363 = $08E6 BRK
364 = $08E7 BRK
365 = $08E8 BRK
366 = $08E9 BRK
367 = $08EA BRK
368 = $08EB BRK
369 = $08EC BRK
370 = $08ED BRK
371 = $08EE BRK
372 = $08EF BRK
373 = $08F0 BRK
374 = $08F1 BRK
375 = $08F2 BRK
376 = $08F3 BRK
377 = $08F4 BRK
378 = $08F5 BRK
379 = $08F6 BRK
380 = $08F7 BRK
381 = $08F8 BRK
382 = $08F9 BRK
383 = $08FA BRK
384 = $08FB BRK
385 = $08FC BRK
386 = $08FD BRK
387 = $08FE BRK
388 = $08FF BRK
389 = $0900 BRK
390 = $0901 BRK
391 = $0902 BRK
392 = $0903 BRK
393 = $0904 BRK
394 = $0905 BRK
395 = $0906 BRK
396 = $0907 BRK
397 = $0908 BRK
398 = $0909 BRK
399 = $090A BRK
400 = $090B BRK
401 = $090C BRK
402 = $090D BRK
403 = $090E BRK
404 = $090F BRK
405 = $0910 BRK
406 = $0911 BRK
407 = $0912 BRK
408160
409161 Some instructions.
410162
599351 Indexed access.
600352
601353 | byte one
602 | byte table many
354 | byte table[256] many
603355 |
604356 | routine main
605357 | outputs many
618370
619371 Byte tables take up 256 bytes in memory.
620372
621 | byte table tab1
622 | byte table tab2
373 | byte table[256] tab1
374 | byte table[256] tab2
623375 |
624376 | routine main
625377 | inputs tab1
705457
706458 You can also copy a literal word to a word table.
707459
708 | word table many
460 | word table[256] many
709461 |
710462 | routine main
711463 | inputs many
774526 Copy word to word table and back, with both `x` and `y` as indexes.
775527
776528 | word one
777 | word table many
529 | word table[256] many
778530 |
779531 | routine main
780532 | inputs one, many
135135 | byte byt
136136 | word wor
137137 | vector vec
138 | byte table tab
139 | word table wtab
138 | byte table[256] tab
139 | word table[256] wtab
140140 | buffer[2048] buf
141141 | pointer ptr
142142 |
176176
177177 User-defined locations of other types.
178178
179 | byte table screen @ 1024
179 | byte table[256] screen @ 1024
180180 | word r1
181181 | word r2 @ 60000
182182 | word r3 : 2000
187187
188188 Initialized byte table.
189189
190 | byte table message : "WHAT DO YOU WANT TO DO NEXT?"
190 | byte table[28] message : "WHAT DO YOU WANT TO DO NEXT?"
191191 |
192192 | routine main {
193193 | }
289289
290290 Declaring byte and word table memory location.
291291
292 | byte table tab
292 | byte table[256] tab
293293 |
294294 | routine main {
295295 | ld x, 0
300300 = ok
301301
302302 | word one
303 | word table many
303 | word table[256] many
304304 |
305305 | routine main {
306306 | ld x, 0