mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-25 23:49:17 +00:00
Resolve forward references more explicitly.
This commit is contained in:
parent
5bad7ff576
commit
33d5093e5a
@ -37,14 +37,16 @@ class AST(object):
|
|||||||
def all_children(self):
|
def all_children(self):
|
||||||
for attr in self.children_attrs:
|
for attr in self.children_attrs:
|
||||||
for child in self.attrs[attr]:
|
for child in self.attrs[attr]:
|
||||||
|
if child is not None:
|
||||||
|
yield child
|
||||||
|
for subchild in child.all_children():
|
||||||
|
yield subchild
|
||||||
|
for attr in self.child_attrs:
|
||||||
|
child = self.attrs[attr]
|
||||||
|
if child is not None:
|
||||||
yield child
|
yield child
|
||||||
for subchild in child.all_children():
|
for subchild in child.all_children():
|
||||||
yield subchild
|
yield subchild
|
||||||
for attr in self.child_attrs:
|
|
||||||
child = self.attrs[attr]
|
|
||||||
yield child
|
|
||||||
for subchild in child.all_children():
|
|
||||||
yield subchild
|
|
||||||
|
|
||||||
|
|
||||||
class Program(AST):
|
class Program(AST):
|
||||||
|
@ -18,6 +18,14 @@ class SymEntry(object):
|
|||||||
return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model)
|
return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model)
|
||||||
|
|
||||||
|
|
||||||
|
class ForwardReference(object):
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%s(%r)" % (self.__class__.__name__, self.name)
|
||||||
|
|
||||||
|
|
||||||
class ParsingContext(object):
|
class ParsingContext(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.symbols = {} # token -> SymEntry
|
self.symbols = {} # token -> SymEntry
|
||||||
@ -45,7 +53,6 @@ class Parser(object):
|
|||||||
def __init__(self, context, text, filename):
|
def __init__(self, context, text, filename):
|
||||||
self.context = context
|
self.context = context
|
||||||
self.scanner = Scanner(text, filename)
|
self.scanner = Scanner(text, filename)
|
||||||
self.backpatch_instrs = []
|
|
||||||
|
|
||||||
def syntax_error(self, msg):
|
def syntax_error(self, msg):
|
||||||
self.scanner.syntax_error(msg)
|
self.scanner.syntax_error(msg)
|
||||||
@ -102,21 +109,28 @@ class Parser(object):
|
|||||||
defn.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
defn.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
||||||
for routine in routines:
|
for routine in routines:
|
||||||
routine.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
routine.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
||||||
for instr in self.backpatch_instrs:
|
|
||||||
if instr.opcode in ('call', 'goto'):
|
|
||||||
name = instr.location
|
|
||||||
model = self.lookup(name)
|
|
||||||
if not isinstance(model.type, (RoutineType, VectorType)):
|
|
||||||
self.syntax_error('Illegal call of non-executable "%s"' % name)
|
|
||||||
instr.location = model
|
|
||||||
if instr.opcode in ('copy',) and isinstance(instr.src, str):
|
|
||||||
name = instr.src
|
|
||||||
model = self.lookup(name)
|
|
||||||
if not isinstance(model.type, (RoutineType, VectorType)):
|
|
||||||
self.syntax_error('Illegal copy of non-executable "%s"' % name)
|
|
||||||
instr.src = model
|
|
||||||
|
|
||||||
return Program(self.scanner.line_number, defns=defns, routines=routines)
|
program = Program(self.scanner.line_number, defns=defns, routines=routines)
|
||||||
|
|
||||||
|
for node in program.all_children():
|
||||||
|
if isinstance(node, SingleOp):
|
||||||
|
instr = node
|
||||||
|
if instr.opcode in ('call', 'goto'):
|
||||||
|
forward_reference = instr.location
|
||||||
|
name = forward_reference.name
|
||||||
|
model = self.lookup(name)
|
||||||
|
if not isinstance(model.type, (RoutineType, VectorType)):
|
||||||
|
self.syntax_error('Illegal call of non-executable "%s"' % name)
|
||||||
|
instr.location = model
|
||||||
|
if instr.opcode in ('copy',) and isinstance(instr.src, ForwardReference):
|
||||||
|
forward_reference = instr.src
|
||||||
|
name = forward_reference.name
|
||||||
|
model = self.lookup(name)
|
||||||
|
if not isinstance(model.type, (RoutineType, VectorType)):
|
||||||
|
self.syntax_error('Illegal copy of non-executable "%s"' % name)
|
||||||
|
instr.src = model
|
||||||
|
|
||||||
|
return program
|
||||||
|
|
||||||
def typedef(self):
|
def typedef(self):
|
||||||
self.scanner.expect('typedef')
|
self.scanner.expect('typedef')
|
||||||
@ -337,7 +351,7 @@ class Parser(object):
|
|||||||
if loc is not None:
|
if loc is not None:
|
||||||
return loc
|
return loc
|
||||||
else:
|
else:
|
||||||
return name
|
return ForwardReference(name)
|
||||||
else:
|
else:
|
||||||
loc = self.lookup(self.scanner.token)
|
loc = self.lookup(self.scanner.token)
|
||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
@ -452,8 +466,7 @@ class Parser(object):
|
|||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
name = self.scanner.token
|
name = self.scanner.token
|
||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
instr = SingleOp(self.scanner.line_number, opcode=opcode, location=name, dest=None, src=None)
|
instr = SingleOp(self.scanner.line_number, opcode=opcode, location=ForwardReference(name), dest=None, src=None)
|
||||||
self.backpatch_instrs.append(instr)
|
|
||||||
return instr
|
return instr
|
||||||
elif self.scanner.token in ("copy",):
|
elif self.scanner.token in ("copy",):
|
||||||
opcode = self.scanner.token
|
opcode = self.scanner.token
|
||||||
@ -462,7 +475,6 @@ class Parser(object):
|
|||||||
self.scanner.expect(',')
|
self.scanner.expect(',')
|
||||||
dest = self.indlocexpr()
|
dest = self.indlocexpr()
|
||||||
instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
|
instr = SingleOp(self.scanner.line_number, opcode=opcode, dest=dest, src=src)
|
||||||
self.backpatch_instrs.append(instr)
|
|
||||||
return instr
|
return instr
|
||||||
elif self.scanner.consume("with"):
|
elif self.scanner.consume("with"):
|
||||||
self.scanner.expect("interrupts")
|
self.scanner.expect("interrupts")
|
||||||
|
Loading…
Reference in New Issue
Block a user