git @ Cat's Eye Technologies SixtyPical / 33d5093
Resolve forward references more explicitly. Chris Pressey 6 years ago
2 changed file(s) with 39 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
3636 def all_children(self):
3737 for attr in self.children_attrs:
3838 for child in self.attrs[attr]:
39 if child is not None:
40 yield child
41 for subchild in child.all_children():
42 yield subchild
43 for attr in self.child_attrs:
44 child = self.attrs[attr]
45 if child is not None:
3946 yield child
4047 for subchild in child.all_children():
4148 yield subchild
42 for attr in self.child_attrs:
43 child = self.attrs[attr]
44 yield child
45 for subchild in child.all_children():
46 yield subchild
4749
4850
4951 class Program(AST):
1717 return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model)
1818
1919
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
2028 class ParsingContext(object):
2129 def __init__(self):
2230 self.symbols = {} # token -> SymEntry
4452 def __init__(self, context, text, filename):
4553 self.context = context
4654 self.scanner = Scanner(text, filename)
47 self.backpatch_instrs = []
4855
4956 def syntax_error(self, msg):
5057 self.scanner.syntax_error(msg)
101108 defn.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
102109 for routine in routines:
103110 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
119133
120134 def typedef(self):
121135 self.scanner.expect('typedef')
336350 if loc is not None:
337351 return loc
338352 else:
339 return name
353 return ForwardReference(name)
340354 else:
341355 loc = self.lookup(self.scanner.token)
342356 self.scanner.scan()
451465 self.scanner.scan()
452466 name = self.scanner.token
453467 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)
456469 return instr
457470 elif self.scanner.token in ("copy",):
458471 opcode = self.scanner.token
461474 self.scanner.expect(',')
462475 dest = self.indlocexpr()
463476 instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
464 self.backpatch_instrs.append(instr)
465477 return instr
466478 elif self.scanner.consume("with"):
467479 self.scanner.expect("interrupts")