1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-09 01:30:50 +00:00

Add some tests, some failing, for expected fallthru maps.

This commit is contained in:
Chris Pressey 2018-03-29 16:44:06 +01:00
parent b33998cddc
commit 8f1e35fb39
3 changed files with 141 additions and 1 deletions

View File

@ -316,7 +316,7 @@ class Analyzer(object):
if context:
for encountered_goto in context.encountered_gotos():
fallthru_map.setdefault(encountered_goto.name, set()).add(routine.name)
program.fallthru_map = dict([(k, list(v)) for k, v in fallthru_map.iteritems()])
program.fallthru_map = dict([(k, sorted(v)) for k, v in fallthru_map.iteritems()])
def analyze_routine(self, routine):
assert isinstance(routine, Routine)

View File

@ -3,4 +3,5 @@
falderal --substring-error \
tests/SixtyPical\ Syntax.md \
tests/SixtyPical\ Analysis.md \
tests/SixtyPical\ Fallthru.md \
tests/SixtyPical\ Compilation.md

View File

@ -0,0 +1,139 @@
SixtyPical Fallthru
===================
This is a test suite, written in [Falderal][] format, for SixtyPical's
ability to detect which routines make tail calls to other routines,
and thus can be re-arranged to simply "fall through" to them.
[Falderal]: http://catseye.tc/node/Falderal
-> Functionality "Dump fallthru map of SixtyPical program" is implemented by
-> shell command "bin/sixtypical --analyze-only --dump-fallthru-map --traceback %(test-body-file)"
-> Tests for functionality "Dump fallthru map of SixtyPical program"
A single routine, obviously, falls through to nothing and has nothing fall
through to it.
| define main routine
| {
| }
= {}
If main does a `goto foo`, then it can fall through to `foo`.
| define foo routine trashes a, z, n
| {
| ld a, 0
| }
|
| define main routine trashes a, z, n
| {
| goto foo
| }
= {
= "foo": [
= "main"
= ]
= }
More than one routine can fall through to a routine.
If main does a `goto foo`, then it can fall through to `foo`.
| define foo routine trashes a, z, n
| {
| ld a, 0
| }
|
| define bar routine trashes a, z, n
| {
| ld a, 0
| goto foo
| }
|
| define main routine trashes a, z, n
| {
| goto foo
| }
= {
= "foo": [
= "bar",
= "main"
= ]
= }
There is nothing stopping two routines from tail-calling each
other, but we will only be able to make one of them, at most,
fall through to the other.
| define foo routine trashes a, z, n
| {
| ld a, 0
| goto bar
| }
|
| define bar routine trashes a, z, n
| {
| ld a, 0
| goto foo
| }
|
| define main routine trashes a, z, n
| {
| }
= {
= "bar": [
= "foo"
= ],
= "foo": [
= "bar"
= ]
= }
If a routine does two tail calls (which is possible because they
can be in different branches of an `if`) it cannot fall through to another
routine.
| define foo routine trashes a, z, n
| {
| ld a, 0
| }
|
| define bar routine trashes a, z, n
| {
| ld a, 0
| }
|
| define main routine inputs z trashes a, z, n
| {
| if z {
| goto foo
| } else {
| goto bar
| }
| }
= {}
Similarly, a tail call to a vector can't be turned into a fallthru,
because we don't necessarily know what actual routine the vector contains.
| vector routine trashes a, z, n
| vec
|
| define foo routine trashes a, z, n
| {
| ld a, 0
| }
|
| define bar routine trashes a, z, n
| {
| ld a, 0
| }
|
| define main routine outputs vec trashes a, z, n
| {
| copy bar, vec
| goto vec
| }
= {}