Spec and syntax for vectors and copy instruction.
Chris Pressey
7 years ago
50 | 50 | * 6502-mnemonic aliases (`sec`, `clc`) |
51 | 51 | * other handy aliases (`eq` for `z`, etc.) |
52 | 52 | * add absolute addressing in shl/shr, absolute-indexed for add, sub, etc. |
53 | * check and disallow recursion. |
0 | 0 | SixtyPical |
1 | 1 | ========== |
2 | 2 | |
3 | This document describes the SixtyPical programming language version 0.5, | |
3 | This document describes the SixtyPical programming language version 0.6-PRE, | |
4 | 4 | both its execution aspect and its static analysis aspect (even though |
5 | 5 | these are, technically speaking, separate concepts.) |
6 | 6 | |
13 | 13 | Types |
14 | 14 | ----- |
15 | 15 | |
16 | There are three TYPES in SixtyPical: | |
16 | There are five TYPES in SixtyPical: | |
17 | 17 | |
18 | 18 | * bit (2 possible values) |
19 | 19 | * byte (256 possible values) |
20 | 20 | * byte table (256 entries, each holding a byte) |
21 | * routine (code stored somewhere in memory, read-only) | |
22 | * vector (address of a routine) | |
21 | 23 | |
22 | 24 | Memory locations |
23 | 25 | ---------------- |
71 | 73 | ### User-defined ### |
72 | 74 | |
73 | 75 | There may be any number of user-defined memory locations. They are defined |
74 | by giving the type, which must be `byte`, and the name. | |
76 | by giving the type, which must be `byte`, `byte table`, or `vector`, and the | |
77 | name. | |
75 | 78 | |
76 | 79 | byte pos |
77 | 80 | |
78 | 81 | A location in memory may be given explicitly on a user-defined memory location. |
79 | 82 | |
80 | byte screen @ 1024 | |
83 | byte table screen @ 1024 | |
81 | 84 | |
82 | 85 | Routines |
83 | 86 | -------- |
324 | 327 | } until z |
325 | 328 | |
326 | 329 | "until" is optional, but if omitted, must be replaced with "forever". |
330 | ||
331 | ### copy ### | |
332 | ||
333 | copy <src-memory-location>, <dest-memory-location> | |
334 | ||
335 | Reads from src and writes to dest. Differs from `st` in that is able to | |
336 | copy more general types of data (for example, vectors,) and it sets the | |
337 | `z` and `n` flags and trashes the `a` register. | |
338 | ||
339 | * It is illegal if dest is read-only. | |
340 | * It is illegal if dest does not occur in the WRITES lists of the current | |
341 | routine. | |
342 | * It is illegal if src is not of same type as dest. | |
343 | * It is illegal if src is uninitialized. | |
344 | ||
345 | After execution, dest is considered initialized, as are `z` and `n`, while | |
346 | `a` is considered uninitialized. | |
327 | 347 | |
328 | 348 | Grammar |
329 | 349 | ------- |
355 | 375 | | "call" RoutineIdent |
356 | 376 | | "if" ["not"] LocExpr Block ["else" Block] |
357 | 377 | | "repeat" Block ("until" ["not"] LocExpr | "forever") |
378 | | "copy" LocExpr "," LocExpr ["+" LocExpr] | |
358 | 379 | . |
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 | 21 | |
20 | 22 | |
21 | 23 | 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, | |
6 | TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_ROUTINE, TYPE_VECTOR, | |
7 | 7 | LocationRef, ConstantRef |
8 | 8 | ) |
9 | 9 | |
102 | 102 | def program(self): |
103 | 103 | defns = [] |
104 | 104 | routines = [] |
105 | while self.scanner.on('byte'): | |
105 | while self.scanner.on('byte') or self.scanner.on('vector'): | |
106 | 106 | defn = self.defn() |
107 | 107 | name = defn.name |
108 | 108 | if name in self.symbols: |
114 | 114 | name = routine.name |
115 | 115 | if name in self.symbols: |
116 | 116 | raise SyntaxError(name) |
117 | self.symbols[name] = SymEntry(routine, None) | |
117 | self.symbols[name] = SymEntry(routine, LocationRef(TYPE_ROUTINE, name)) | |
118 | 118 | routines.append(routine) |
119 | 119 | self.scanner.check_type('EOF') |
120 | 120 | return Program(defns=defns, routines=routines) |
121 | 121 | |
122 | 122 | def defn(self): |
123 | 123 | type = TYPE_BYTE |
124 | self.scanner.expect('byte') | |
125 | if self.scanner.consume('table'): | |
126 | type = TYPE_BYTE_TABLE | |
124 | if self.scanner.consume('byte'): | |
125 | type = TYPE_BYTE | |
126 | if self.scanner.consume('table'): | |
127 | type = TYPE_BYTE_TABLE | |
128 | else: | |
129 | self.scanner.expect('vector') | |
130 | type = TYPE_VECTOR | |
127 | 131 | self.scanner.check_type('identifier') |
128 | 132 | name = self.scanner.token |
129 | 133 | self.scanner.scan() |
245 | 249 | self.scanner.scan() |
246 | 250 | # TODO: check that is has been defined |
247 | 251 | return Instr(opcode=opcode, name=name, dest=None, src=None) |
252 | elif self.scanner.token in ("copy",): | |
253 | opcode = self.scanner.token | |
254 | self.scanner.scan() | |
255 | src = self.locexpr() | |
256 | self.scanner.expect(',') | |
257 | dest = self.locexpr() | |
258 | return Instr(opcode=opcode, dest=dest, src=src) | |
248 | 259 | else: |
249 | 260 | raise ValueError('bad opcode "%s"' % self.scanner.token) |