git @ Cat's Eye Technologies SixtyPical / 2dc4dd9
Parse indirect calls, but break evaluator. Chris Pressey 6 years ago
10 changed file(s) with 113 addition(s) and 69 deletion(s). Raw diff Collapse all Expand all
109109 }
110110
111111 Routines may call only routines previously defined in the program source.
112 Thus, recursive routines are not allowed.
112 Thus, directly recursive routines are not allowed. (However, routines may
113 also call routines via vectors, which are dynamically assigned. In this
114 case, there is, for the time being, no check for recursive calls.)
113115
114116 For a SixtyPical program to be run, there must be one routine called `main`.
115117 This routine is executed when the program is run.
284286
285287 ### call ###
286288
287 call <routine-name>
289 call <executable-name>
290
291 Transfers execution to the given executable, whether that is a previously-
292 defined routine, or a vector location which contains the address of a routine
293 which will be called indirectly.
288294
289295 Just before the call,
290296
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
44 TYPE_BYTE, TYPE_BYTE_TABLE,
5 RoutineType, VectorType, ExecutableType,
5 VectorType, ExecutableType,
66 ConstantRef, LocationRef,
77 REG_A, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
88 )
11
22 from sixtypical.ast import Program, Routine, Block, Instr
33 from sixtypical.model import (
4 ConstantRef, LocationRef,
4 ConstantRef,
55 TYPE_BIT,
66 RoutineType, VectorType,
7 REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C
7 REG_A, REG_X, REG_Y, FLAG_C
88 )
99 from sixtypical.emitter import Byte, Label, Offset
1010 from sixtypical.gen6502 import (
88 class Byte(Emittable):
99 def __init__(self, value):
1010 if value < -127 or value > 255:
11 raise IndexError(thing)
11 raise IndexError(value)
1212 if value < 0:
1313 value += 256
1414 self.value = value
2222 raise ValueError(ref)
2323
2424 def set(self, ref, value):
25 assert isinstance(ref, LocationRef)
26 self._store[ref.name] = value
25 # bleah
26 if isinstance(ref, LocationRef):
27 self._store[ref.name] = value
28 else:
29 self._store[ref] = value
2730
2831
2932 def eval_program(program):
3033 assert isinstance(program, Program)
31 routines = {r.name: r for r in program.routines}
3234 context = Context()
3335 for ref in (REG_A, REG_X, REG_Y, FLAG_Z, FLAG_N, FLAG_V, FLAG_C):
3436 context.set(ref, 0)
35 eval_routine(routines['main'], context, routines)
37 for routine in program.routines:
38 context.set(routine.name, routine)
39 eval_routine(context['main'], context)
3640 return context
3741
3842
39 def eval_routine(routine, context, routines):
43 def eval_routine(routine, context):
4044 assert isinstance(routine, Routine)
41 eval_block(routine.block, context, routines)
45 eval_block(routine.block, context)
4246
4347
44 def eval_block(block, context, routines):
48 def eval_block(block, context):
4549 assert isinstance(block, Block)
4650 for i in block.instrs:
47 eval_instr(i, context, routines)
51 eval_instr(i, context)
4852
4953
50 def eval_instr(instr, context, routines):
54 def eval_instr(instr, context):
5155 assert isinstance(instr, Instr)
5256 opcode = instr.opcode
5357 dest = instr.dest
141145 context.set(FLAG_N, 1 if result & 128 else 0)
142146 context.set(dest, result)
143147 elif opcode == 'call':
144 eval_routine(routines[instr.name], context, routines)
148 eval_routine(context[instr.name], context)
145149 elif opcode == 'if':
146150 val = context.get(src)
147151 test = (val != 0) if not instr.inverted else (val == 0)
148152 if test:
149 eval_block(instr.block1, context, routines)
153 eval_block(instr.block1, context)
150154 elif instr.block2:
151 eval_block(instr.block2, context, routines)
155 eval_block(instr.block2, context)
152156 elif opcode == 'repeat':
153 eval_block(instr.block, context, routines)
157 eval_block(instr.block, context)
154158 while context.get(src) == 0:
155 eval_block(instr.block, context, routines)
159 eval_block(instr.block, context)
156160 elif opcode == 'copy':
157161 context.set(dest, context.get(src))
158162 # these are trashed; so could be anything really
00 """Emittables for 6502 machine code."""
11
2 from sixtypical.emitter import Emittable, Byte, Word, Label, Offset
2 from sixtypical.emitter import Emittable, Byte, Label, Offset
33
44
55 class AddressingMode(Emittable):
5757 pass
5858
5959
60 class Indirect(AddressingMode):
61 def __init__(self, value):
62 assert isinstance(value, Label)
63 self.value = value
64
65 def size(self):
66 return 2
67
68 def serialize(self, addr=None):
69 return self.value.serialize()
70
71
6072 class Relative(AddressingMode):
6173 def __init__(self, value):
6274 assert isinstance(value, Label)
6981 return self.value.serialize_relative_to(addr)
7082
7183
72 class Opcode(Emittable):
84 class Instruction(Emittable):
7385 def __init__(self, operand=None):
7486 self.operand = operand or Implied()
7587
8698 return "%s(%r)" % (self.__class__.__name__, self.operand)
8799
88100
89 class ADC(Opcode):
101 class ADC(Instruction):
90102 opcodes = {
91103 Immediate: 0x69,
92104 Absolute: 0x6d,
95107 }
96108
97109
98 class AND(Opcode):
110 class AND(Instruction):
99111 opcodes = {
100112 Immediate: 0x29,
101113 Absolute: 0x2d,
104116 }
105117
106118
107 class BCC(Opcode):
119 class BCC(Instruction):
108120 opcodes = {
109121 Relative: 0x90,
110122 }
111123
112124
113 class BCS(Opcode):
125 class BCS(Instruction):
114126 opcodes = {
115127 Relative: 0xb0,
116128 }
117129
118130
119 class BEQ(Opcode):
131 class BEQ(Instruction):
120132 opcodes = {
121133 Relative: 0xf0,
122134 }
123135
124136
125 class BNE(Opcode):
137 class BNE(Instruction):
126138 opcodes = {
127139 Relative: 0xd0,
128140 }
129141
130142
131 class CLC(Opcode):
143 class CLC(Instruction):
132144 opcodes = {
133145 Implied: 0x18
134146 }
135147
136148
137 class CLI(Opcode):
149 class CLI(Instruction):
138150 opcodes = {
139151 Implied: 0x58,
140152 }
141153
142154
143 class CMP(Opcode):
155 class CMP(Instruction):
144156 opcodes = {
145157 Immediate: 0xc9,
146158 Absolute: 0xcd,
149161 }
150162
151163
152 class CPX(Opcode):
164 class CPX(Instruction):
153165 opcodes = {
154166 Immediate: 0xe0,
155167 Absolute: 0xec,
156168 }
157169
158170
159 class CPY(Opcode):
171 class CPY(Instruction):
160172 opcodes = {
161173 Immediate: 0xc0,
162174 Absolute: 0xcc,
163175 }
164176
165177
166 class DEC(Opcode):
178 class DEC(Instruction):
167179 opcodes = {
168180 Absolute: 0xce,
169181 }
170182
171183
172 class DEX(Opcode):
184 class DEX(Instruction):
173185 opcodes = {
174186 Implied: 0xca,
175187 }
176188
177189
178 class DEY(Opcode):
190 class DEY(Instruction):
179191 opcodes = {
180192 Implied: 0x88,
181193 }
182194
183195
184 class EOR(Opcode):
196 class EOR(Instruction):
185197 opcodes = {
186198 Immediate: 0x49,
187199 Absolute: 0x4d,
190202 }
191203
192204
193 class INC(Opcode):
205 class INC(Instruction):
194206 opcodes = {
195207 Absolute: 0xee,
196208 AbsoluteX: 0xfe,
197209 }
198210
199211
200 class INX(Opcode):
212 class INX(Instruction):
201213 opcodes = {
202214 Implied: 0xe8,
203215 }
204216
205217
206 class INY(Opcode):
218 class INY(Instruction):
207219 opcodes = {
208220 Implied: 0xc8,
209221 }
210222
211223
212 class JMP(Opcode):
224 class JMP(Instruction):
213225 opcodes = {
214226 Absolute: 0x4c,
215 }
216
217
218 class JSR(Opcode):
227 Indirect: 0x6c,
228 }
229
230
231 class JSR(Instruction):
219232 opcodes = {
220233 Absolute: 0x20,
221234 }
222235
223236
224 class LDA(Opcode):
237 class LDA(Instruction):
225238 opcodes = {
226239 Immediate: 0xa9,
227240 Absolute: 0xad,
230243 }
231244
232245
233 class LDX(Opcode):
246 class LDX(Instruction):
234247 opcodes = {
235248 Immediate: 0xa2,
236249 Absolute: 0xae,
238251 }
239252
240253
241 class LDY(Opcode):
254 class LDY(Instruction):
242255 opcodes = {
243256 Immediate: 0xa0,
244257 Absolute: 0xac,
246259 }
247260
248261
249 class ORA(Opcode):
262 class ORA(Instruction):
250263 opcodes = {
251264 Immediate: 0x09,
252265 Absolute: 0x0d,
255268 }
256269
257270
258 class ROL(Opcode):
271 class ROL(Instruction):
259272 opcodes = {
260273 Implied: 0x2a, # Accumulator
261274 Absolute: 0x2e,
263276 }
264277
265278
266 class ROR(Opcode):
279 class ROR(Instruction):
267280 opcodes = {
268281 Implied: 0x6a, # Accumulator
269282 Absolute: 0x6e,
271284 }
272285
273286
274 class RTS(Opcode):
287 class RTS(Instruction):
275288 opcodes = {
276289 Implied: 0x60,
277290 }
278291
279292
280 class SBC(Opcode):
293 class SBC(Instruction):
281294 opcodes = {
282295 Immediate: 0xe9,
283296 Absolute: 0xed,
286299 }
287300
288301
289 class SEC(Opcode):
302 class SEC(Instruction):
290303 opcodes = {
291304 Implied: 0x38,
292305 }
293306
294307
295 class SEI(Opcode):
308 class SEI(Instruction):
296309 opcodes = {
297310 Implied: 0x78,
298311 }
299312
300313
301 class STA(Opcode):
314 class STA(Instruction):
302315 opcodes = {
303316 Absolute: 0x8d,
304317 AbsoluteX: 0x9d,
306319 }
307320
308321
309 class STX(Opcode):
322 class STX(Instruction):
310323 opcodes = {
311324 Absolute: 0x8e,
312325 }
313326
314327
315 class STY(Opcode):
328 class STY(Instruction):
316329 opcodes = {
317330 Absolute: 0x8c,
318331 }
319332
320333
321 class TAX(Opcode):
334 class TAX(Instruction):
322335 opcodes = {
323336 Implied: 0xaa,
324337 }
325338
326339
327 class TAY(Opcode):
340 class TAY(Instruction):
328341 opcodes = {
329342 Implied: 0xa8,
330343 }
331344
332345
333 class TXA(Opcode):
346 class TXA(Instruction):
334347 opcodes = {
335348 Implied: 0x8a,
336349 }
337350
338351
339 class TYA(Opcode):
352 class TYA(Instruction):
340353 opcodes = {
341354 Implied: 0x98,
342355 }
8585 self.type = type
8686 self.value = value
8787
88 def __repr__(self):
89 return 'ConstantRef(%r)' % self.value
90
9188 def __eq__(self, other):
9289 return isinstance(other, ConstantRef) and (
9390 other.type == self.type and other.value == self.value
44 from sixtypical.ast import Program, Defn, Routine, Block, Instr
55 from sixtypical.model import (
66 TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE,
7 RoutineType, VectorType,
7 RoutineType, VectorType, ExecutableType,
88 LocationRef, ConstantRef
99 )
1010
266266 self.scanner.scan()
267267 if name not in self.symbols:
268268 raise SyntaxError('Undefined routine "%s"' % name)
269 if not isinstance(self.symbols[name].model.type, RoutineType):
270 raise SyntaxError('Illegal call of non-routine "%s"' % name)
269 if not isinstance(self.symbols[name].model.type, ExecutableType):
270 raise SyntaxError('Illegal call of non-executable "%s"' % name)
271271 return Instr(opcode=opcode, name=name, dest=None, src=None)
272272 elif self.scanner.token in ("copy",):
273273 opcode = self.scanner.token
399399 = x: 5
400400 = y: 5
401401 = z: 0
402
403 Indirect call.
404
405 | vector foo outputs x trashes z, n
406 |
407 | routine bar outputs x trashes z, n {
408 | ld x, 200
409 | }
410 |
411 | routine main {
412 | copy bar, foo
413 | call foo
414 | }
415 = a: 0
416 = c: 0
417 = n: 1
418 = v: 0
419 = x: 200
420 = y: 0
421 = z: 0
22
33 This is a test suite, written in [Falderal][] format, for the syntax of
44 the Sixtypical language, disgregarding execution, static analysis, etc.
5
6 Note that these example programs are intended to be syntactically correct,
7 but not necessarily sensible programs.
58
69 [Falderal]: http://catseye.tc/node/Falderal
710
214217 | }
215218 = ok
216219
217 Declaring a vector.
220 Declaring and calling a vector.
218221
219222 | vector cinv
220223 | inputs a
229232 | with interrupts off {
230233 | copy foo, cinv
231234 | }
235 | call cinv
232236 | }
233237 = ok
234238