17 | 17 |
return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model)
|
18 | 18 |
|
19 | 19 |
|
|
20 |
class ForwardReference(object):
|
|
21 |
def __init__(self, name):
|
|
22 |
self.name = name
|
|
23 |
|
|
24 |
def __repr__(self):
|
|
25 |
return "%s(%r)" % (self.__class__.__name__, self.name)
|
|
26 |
|
|
27 |
|
20 | 28 |
class ParsingContext(object):
|
21 | 29 |
def __init__(self):
|
22 | 30 |
self.symbols = {} # token -> SymEntry
|
|
44 | 52 |
def __init__(self, context, text, filename):
|
45 | 53 |
self.context = context
|
46 | 54 |
self.scanner = Scanner(text, filename)
|
47 | |
self.backpatch_instrs = []
|
48 | 55 |
|
49 | 56 |
def syntax_error(self, msg):
|
50 | 57 |
self.scanner.syntax_error(msg)
|
|
101 | 108 |
defn.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
102 | 109 |
for routine in routines:
|
103 | 110 |
routine.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
104 | |
for instr in self.backpatch_instrs:
|
105 | |
if instr.opcode in ('call', 'goto'):
|
106 | |
name = instr.location
|
107 | |
model = self.lookup(name)
|
108 | |
if not isinstance(model.type, (RoutineType, VectorType)):
|
109 | |
self.syntax_error('Illegal call of non-executable "%s"' % name)
|
110 | |
instr.location = model
|
111 | |
if instr.opcode in ('copy',) and isinstance(instr.src, str):
|
112 | |
name = instr.src
|
113 | |
model = self.lookup(name)
|
114 | |
if not isinstance(model.type, (RoutineType, VectorType)):
|
115 | |
self.syntax_error('Illegal copy of non-executable "%s"' % name)
|
116 | |
instr.src = model
|
117 | |
|
118 | |
return Program(self.scanner.line_number, defns=defns, routines=routines)
|
|
111 |
|
|
112 |
program = Program(self.scanner.line_number, defns=defns, routines=routines)
|
|
113 |
|
|
114 |
for node in program.all_children():
|
|
115 |
if isinstance(node, SingleOp):
|
|
116 |
instr = node
|
|
117 |
if instr.opcode in ('call', 'goto'):
|
|
118 |
forward_reference = instr.location
|
|
119 |
name = forward_reference.name
|
|
120 |
model = self.lookup(name)
|
|
121 |
if not isinstance(model.type, (RoutineType, VectorType)):
|
|
122 |
self.syntax_error('Illegal call of non-executable "%s"' % name)
|
|
123 |
instr.location = model
|
|
124 |
if instr.opcode in ('copy',) and isinstance(instr.src, ForwardReference):
|
|
125 |
forward_reference = instr.src
|
|
126 |
name = forward_reference.name
|
|
127 |
model = self.lookup(name)
|
|
128 |
if not isinstance(model.type, (RoutineType, VectorType)):
|
|
129 |
self.syntax_error('Illegal copy of non-executable "%s"' % name)
|
|
130 |
instr.src = model
|
|
131 |
|
|
132 |
return program
|
119 | 133 |
|
120 | 134 |
def typedef(self):
|
121 | 135 |
self.scanner.expect('typedef')
|
|
336 | 350 |
if loc is not None:
|
337 | 351 |
return loc
|
338 | 352 |
else:
|
339 | |
return name
|
|
353 |
return ForwardReference(name)
|
340 | 354 |
else:
|
341 | 355 |
loc = self.lookup(self.scanner.token)
|
342 | 356 |
self.scanner.scan()
|
|
451 | 465 |
self.scanner.scan()
|
452 | 466 |
name = self.scanner.token
|
453 | 467 |
self.scanner.scan()
|
454 | |
instr = SingleOp(self.scanner.line_number, opcode=opcode, location=name, dest=None, src=None)
|
455 | |
self.backpatch_instrs.append(instr)
|
|
468 |
instr = SingleOp(self.scanner.line_number, opcode=opcode, location=ForwardReference(name), dest=None, src=None)
|
456 | 469 |
return instr
|
457 | 470 |
elif self.scanner.token in ("copy",):
|
458 | 471 |
opcode = self.scanner.token
|
|
461 | 474 |
self.scanner.expect(',')
|
462 | 475 |
dest = self.indlocexpr()
|
463 | 476 |
instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
|
464 | |
self.backpatch_instrs.append(instr)
|
465 | 477 |
return instr
|
466 | 478 |
elif self.scanner.consume("with"):
|
467 | 479 |
self.scanner.expect("interrupts")
|