mirror of
https://github.com/catseye/SixtyPical.git
synced 2024-11-22 01:32:13 +00:00
More correct determination of tail position for purposes of goto
.
This commit is contained in:
parent
5f62de11c2
commit
7a3b52dc1e
@ -5,6 +5,8 @@ History of SixtyPical
|
||||
----
|
||||
|
||||
* `--origin` and `--output-format` options added to reference compiler.
|
||||
* "Tail position" is now more correctly determined for the purposes of
|
||||
insisting that `goto` only appears in it.
|
||||
* Fixed bug when `--prelude` option was missing.
|
||||
* Fixed bug when reporting line numbers of scanner-level syntax errors.
|
||||
|
||||
|
@ -101,6 +101,7 @@ class Context(object):
|
||||
self._touched = set()
|
||||
self._range = dict()
|
||||
self._writeable = set()
|
||||
self._has_encountered_goto = False
|
||||
|
||||
for ref in inputs:
|
||||
if ref.is_constant():
|
||||
@ -243,12 +244,17 @@ class Context(object):
|
||||
for ref in refs:
|
||||
self._writeable.remove(ref)
|
||||
|
||||
def set_encountered_goto(self):
|
||||
self._has_encountered_goto = True
|
||||
|
||||
def has_encountered_goto(self):
|
||||
return self._has_encountered_goto
|
||||
|
||||
|
||||
class Analyzer(object):
|
||||
|
||||
def __init__(self, debug=False):
|
||||
self.current_routine = None
|
||||
self.has_encountered_goto = False
|
||||
self.routines = {}
|
||||
self.debug = debug
|
||||
|
||||
@ -281,7 +287,6 @@ class Analyzer(object):
|
||||
def analyze_routine(self, routine):
|
||||
assert isinstance(routine, Routine)
|
||||
self.current_routine = routine
|
||||
self.has_encountered_goto = False
|
||||
if routine.block is None:
|
||||
# it's an extern, that's fine
|
||||
return
|
||||
@ -312,7 +317,7 @@ class Analyzer(object):
|
||||
if ref in type_.outputs:
|
||||
raise UnmeaningfulOutputError(routine, ref.name)
|
||||
|
||||
if not self.has_encountered_goto:
|
||||
if not context.has_encountered_goto():
|
||||
for ref in type_.outputs:
|
||||
context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError)
|
||||
for ref in context.each_touched():
|
||||
@ -323,8 +328,6 @@ class Analyzer(object):
|
||||
def analyze_block(self, block, context):
|
||||
assert isinstance(block, Block)
|
||||
for i in block.instrs:
|
||||
if self.has_encountered_goto:
|
||||
raise IllegalJumpError(i, i)
|
||||
self.analyze_instr(i, context)
|
||||
|
||||
def analyze_instr(self, instr, context):
|
||||
@ -346,7 +349,10 @@ class Analyzer(object):
|
||||
opcode = instr.opcode
|
||||
dest = instr.dest
|
||||
src = instr.src
|
||||
|
||||
|
||||
if context.has_encountered_goto():
|
||||
raise IllegalJumpError(instr, instr)
|
||||
|
||||
if opcode == 'ld':
|
||||
if isinstance(src, IndexedRef):
|
||||
if TableType.is_a_table_type(src.ref.type, TYPE_BYTE) and dest.type == TYPE_BYTE:
|
||||
@ -560,7 +566,7 @@ class Analyzer(object):
|
||||
self.assert_affected_within('outputs', type_, current_type)
|
||||
self.assert_affected_within('trashes', type_, current_type)
|
||||
|
||||
self.has_encountered_goto = True
|
||||
context.set_encountered_goto()
|
||||
elif opcode == 'trash':
|
||||
context.set_touched(instr.dest)
|
||||
context.set_unmeaningful(instr.dest)
|
||||
@ -601,6 +607,8 @@ class Analyzer(object):
|
||||
context._touched = set(context1._touched) | set(context2._touched)
|
||||
context.set_meaningful(*list(outgoing_meaningful))
|
||||
context._writeable = set(context1._writeable) | set(context2._writeable)
|
||||
if context1.has_encountered_goto() or context2.has_encountered_goto():
|
||||
context.set_encountered_goto()
|
||||
|
||||
for ref in outgoing_trashes:
|
||||
context.set_touched(ref)
|
||||
|
@ -2247,6 +2247,36 @@ Calling the vector does indeed trash the things the vector says it does.
|
||||
| }
|
||||
= ok
|
||||
|
||||
| routine bar trashes x, z, n {
|
||||
| ld x, 200
|
||||
| }
|
||||
|
|
||||
| routine main trashes x, z, n {
|
||||
| ld x, 0
|
||||
| if z {
|
||||
| ld x, 1
|
||||
| goto bar
|
||||
| } else {
|
||||
| ld x, 0
|
||||
| }
|
||||
| }
|
||||
= ok
|
||||
|
||||
For the purposes of `goto`, the end of a loop is never tail position.
|
||||
|
||||
| routine bar trashes x, z, n {
|
||||
| ld x, 200
|
||||
| }
|
||||
|
|
||||
| routine main trashes x, z, n {
|
||||
| ld x, 0
|
||||
| repeat {
|
||||
| inc x
|
||||
| goto bar
|
||||
| } until z
|
||||
| }
|
||||
? IllegalJumpError
|
||||
|
||||
Can't `goto` a routine that outputs or trashes more than the current routine.
|
||||
|
||||
| routine bar trashes x, y, z, n {
|
||||
|
Loading…
Reference in New Issue
Block a user