git @ Cat's Eye Technologies SixtyPical / 8f1e35f
Add some tests, some failing, for expected fallthru maps. Chris Pressey 3 years ago
3 changed file(s) with 141 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
315315 if context:
316316 for encountered_goto in context.encountered_gotos():
317317 fallthru_map.setdefault(encountered_goto.name, set()).add(routine.name)
318 program.fallthru_map = dict([(k, list(v)) for k, v in fallthru_map.iteritems()])
318 program.fallthru_map = dict([(k, sorted(v)) for k, v in fallthru_map.iteritems()])
319319
320320 def analyze_routine(self, routine):
321321 assert isinstance(routine, Routine)
22 falderal --substring-error \
33 tests/SixtyPical\ Syntax.md \
44 tests/SixtyPical\ Analysis.md \
5 tests/SixtyPical\ Fallthru.md \
56 tests/SixtyPical\ Compilation.md
0 SixtyPical Fallthru
1 ===================
2
3 This is a test suite, written in [Falderal][] format, for SixtyPical's
4 ability to detect which routines make tail calls to other routines,
5 and thus can be re-arranged to simply "fall through" to them.
6
7 [Falderal]: http://catseye.tc/node/Falderal
8
9 -> Functionality "Dump fallthru map of SixtyPical program" is implemented by
10 -> shell command "bin/sixtypical --analyze-only --dump-fallthru-map --traceback %(test-body-file)"
11
12 -> Tests for functionality "Dump fallthru map of SixtyPical program"
13
14 A single routine, obviously, falls through to nothing and has nothing fall
15 through to it.
16
17 | define main routine
18 | {
19 | }
20 = {}
21
22 If main does a `goto foo`, then it can fall through to `foo`.
23
24 | define foo routine trashes a, z, n
25 | {
26 | ld a, 0
27 | }
28 |
29 | define main routine trashes a, z, n
30 | {
31 | goto foo
32 | }
33 = {
34 = "foo": [
35 = "main"
36 = ]
37 = }
38
39 More than one routine can fall through to a routine.
40
41 If main does a `goto foo`, then it can fall through to `foo`.
42
43 | define foo routine trashes a, z, n
44 | {
45 | ld a, 0
46 | }
47 |
48 | define bar routine trashes a, z, n
49 | {
50 | ld a, 0
51 | goto foo
52 | }
53 |
54 | define main routine trashes a, z, n
55 | {
56 | goto foo
57 | }
58 = {
59 = "foo": [
60 = "bar",
61 = "main"
62 = ]
63 = }
64
65 There is nothing stopping two routines from tail-calling each
66 other, but we will only be able to make one of them, at most,
67 fall through to the other.
68
69 | define foo routine trashes a, z, n
70 | {
71 | ld a, 0
72 | goto bar
73 | }
74 |
75 | define bar routine trashes a, z, n
76 | {
77 | ld a, 0
78 | goto foo
79 | }
80 |
81 | define main routine trashes a, z, n
82 | {
83 | }
84 = {
85 = "bar": [
86 = "foo"
87 = ],
88 = "foo": [
89 = "bar"
90 = ]
91 = }
92
93 If a routine does two tail calls (which is possible because they
94 can be in different branches of an `if`) it cannot fall through to another
95 routine.
96
97 | define foo routine trashes a, z, n
98 | {
99 | ld a, 0
100 | }
101 |
102 | define bar routine trashes a, z, n
103 | {
104 | ld a, 0
105 | }
106 |
107 | define main routine inputs z trashes a, z, n
108 | {
109 | if z {
110 | goto foo
111 | } else {
112 | goto bar
113 | }
114 | }
115 = {}
116
117 Similarly, a tail call to a vector can't be turned into a fallthru,
118 because we don't necessarily know what actual routine the vector contains.
119
120 | vector routine trashes a, z, n
121 | vec
122 |
123 | define foo routine trashes a, z, n
124 | {
125 | ld a, 0
126 | }
127 |
128 | define bar routine trashes a, z, n
129 | {
130 | ld a, 0
131 | }
132 |
133 | define main routine outputs vec trashes a, z, n
134 | {
135 | copy bar, vec
136 | goto vec
137 | }
138 = {}