git @ Cat's Eye Technologies SixtyPical / 9d6ca0b
Low and high address operators, parsing and execution thereof. Chris Pressey 5 years ago
9 changed file(s) with 122 addition(s) and 31 deletion(s). Raw diff Collapse all Expand all
4444 For 0.7:
4545
4646 * `low` and `high` address operators (turn `word` type into `byte`.)
47 * `word table` type.
4847
4948 For 0.8:
5049
50 * `word table` type.
51 * `vector table` type.
5152 * zero-page memory locations.
5253 * indirect addressing.
5354
5455 For 0.9
5556
56 * save registers on stack or in memory (the preserves them = not trashed)
57 * save registers on stack or in memory (this preserves them = not trashed)
5758
5859 At some point...
5960
394394 -------
395395
396396 Program ::= {Defn} {Routine}.
397 Defn ::= Type Ident<new> [Constraints] ["@" WordConst].
397 Defn ::= Type Ident<new> [Constraints] (":" Literal | "@" LitWord).
398398 Type ::= "byte" ["table"] | "vector"
399399 Constrnt::= ["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs].
400 Routine ::= "routine" Ident<new> Constraints (Block | "@" WordConst).
400 Routine ::= "routine" Ident<new> Constraints (Block | "@" LitWord).
401401 LocExprs::= LocExpr {"," LocExpr}.
402 LocExpr ::= Register | Flag | LitByte | Ident.
402 LocExpr ::= Register | Flag | Literal | ("<" | ">") Ident.
403403 Register::= "a" | "x" | "y".
404404 Flag ::= "c" | "z" | "n" | "v".
405 Literal ::= LitByte | LitWord.
405406 LitByte ::= "0" ... "255".
406407 LitWord ::= "0" ... "65535".
407408 Block ::= "{" {Instr} "}".
2424 pass
2525
2626
27 class DecLoc(AST):
28 pass
29
30
3127 class Block(AST):
3228 pass
3329
11
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
4 ConstantRef, LocationRef,
4 ConstantRef, LocationRef, PartRef,
55 REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
66 )
77
2020 return ref.value
2121 elif isinstance(ref, LocationRef):
2222 return self._store[ref.name]
23 elif isinstance(ref, PartRef):
24 value = self.get(ref.ref)
25 if ref.height == 0:
26 return value & 255
27 elif ref.height == 1:
28 return (value >> 8) & 255
29 else:
30 raise NotImplementedError
2331 else:
2432 raise ValueError(ref)
2533
2634 def set(self, ref, value):
35 if isinstance(ref, PartRef):
36 old = self.get(ref.ref)
37 if ref.height == 0:
38 value = (old & (255 << 8)) | value
39 elif ref.height == 1:
40 value = (value << 8) | (old & 255)
41 else:
42 raise NotImplementedError
43 ref = ref.ref
2744 assert isinstance(ref, LocationRef)
2845 self._store[ref.name] = value
2946
8989 return isinstance(self.type, RoutineType)
9090
9191
92 class PartRef(Ref):
93 """For 'low byte of' location and 'high byte of' location modifiers.
94
95 height=0 = low byte, height=1 = high byte.
96
97 """
98 def __init__(self, ref, height):
99 assert isinstance(ref, Ref)
100 assert ref.type == TYPE_WORD
101 self.ref = ref
102 self.height = height
103 self.type = TYPE_BYTE
104
105 def __eq__(self, other):
106 return isinstance(other, PartRef) and (
107 other.height == self.height and other.ref == self.ref
108 )
109
110 def __hash__(self):
111 return hash(self.ref) ^ hash(self.height) ^ hash(self.type)
112
113 def __repr__(self):
114 return '%s(%r, %r)' % (self.__class__.__name__, self.ref, self.height)
115
116 def is_constant(self):
117 return self.ref.is_constant()
118
119
92120 class ConstantRef(Ref):
93121 def __init__(self, type, value):
94122 self.type = type
33 from sixtypical.model import (
44 TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE,
55 RoutineType, VectorType, ExecutableType,
6 LocationRef, ConstantRef
6 LocationRef, ConstantRef, PartRef
77 )
88 from sixtypical.scanner import Scanner
99
141141 self.scanner.scan()
142142 return loc
143143 else:
144 op = None
145 if self.scanner.consume('<'):
146 op = '<'
147 elif self.scanner.consume('>'):
148 op = '>'
144149 loc = self.lookup(self.scanner.token)
150 if op == '<':
151 loc = PartRef(loc, 0)
152 elif op == '>':
153 loc = PartRef(loc, 1)
145154 self.scanner.scan()
146155 return loc
147156
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
416416 = y: 5
417417 = z: 0
418418
419 Copy word to word.
420
421 | word foo : 2000
422 | word bar
423 |
424 | routine main {
425 | copy foo, bar
426 | }
427 = a: 0
428 = bar: 2000
429 = c: 0
430 = foo: 2000
431 = n: 0
432 = v: 0
433 = x: 0
434 = y: 0
435 = z: 0
436
437 Load and store low byte, high byte of word.
438
439 | word foo : 511
440 |
441 | routine main {
442 | ld x, <foo
443 | ld y, >foo
444 | ld a, 2
445 | st a, <foo
446 | ld a, 1
447 | st a, >foo
448 | }
449 = a: 1
450 = c: 0
451 = foo: 258
452 = n: 0
453 = v: 0
454 = x: 255
455 = y: 1
456 = z: 0
457
419458 Indirect call.
420459
421460 | vector foo outputs x trashes z, n
142142 | }
143143 = ok
144144
145 Cannot have both initial value and explicit address.
146
147 | byte screen : 3 @ 1024
148 |
149 | routine main {
150 | ld a, lives
151 | st a, lives
152 | }
153 ? SyntaxError
154
145155 User-defined locations of other types.
146156
147157 | byte table screen @ 1024
153163 | }
154164 = ok
155165
156 Initialized memory locations.
157
158 | byte lives : 3
159 |
160 | routine main {
161 | ld a, lives
162 | st a, lives
163 | }
164 = ok
165
166 Cannot have both initial value and explicit address.
167
168 | byte screen : 3 @ 1024
169 |
170 | routine main {
171 | ld a, lives
172 | st a, lives
173 | }
174 ? SyntaxError
166 Referencing low and high byte of a word.
167
168 | word r1
169 |
170 | routine main {
171 | ld x, <r1
172 | ld y, >r1
173 | }
174 = ok
175175
176176 Can't access an undeclared memory location.
177177