2 |
7u83 |
1 |
<!-- Crown Copyright (c) 1998 -->
|
|
|
2 |
<HTML>
|
|
|
3 |
<HEAD>
|
|
|
4 |
<TITLE>Control Flow within procedures</TITLE>
|
|
|
5 |
</HEAD>
|
|
|
6 |
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#400080" ALINK="#FF0000">
|
|
|
7 |
<A NAME=S51>
|
|
|
8 |
<H1>TDF Guide, Issue 4.0 </H1>
|
|
|
9 |
<H3>January 1998</H3>
|
|
|
10 |
<A HREF="guide9.html"><IMG SRC="../images/next.gif" ALT="next section">
|
|
|
11 |
</A> <A HREF="guide7.html">
|
|
|
12 |
<IMG SRC="../images/prev.gif" ALT="previous section"></A>
|
|
|
13 |
<A HREF="guide1.html"><IMG SRC="../images/top.gif" ALT="current document"></A>
|
|
|
14 |
<A HREF="../index.html"><IMG SRC="../images/home.gif" ALT="TenDRA home page">
|
|
|
15 |
</A>
|
|
|
16 |
<IMG SRC="../images/no_index.gif" ALT="document index"><P>
|
|
|
17 |
<HR>
|
|
|
18 |
<DL>
|
|
|
19 |
<DT><A HREF="#S52"><B>6.1 </B> - Unconditional flow</A><DD>
|
|
|
20 |
<DT><A HREF="#S53"><B>6.1.1 </B> - sequence</A><DD>
|
|
|
21 |
<DT><A HREF="#S54"><B>6.2 </B> - Conditional flow</A><DD>
|
|
|
22 |
<DT><A HREF="#S55"><B>6.2.1 </B> - labelled, make_label</A><DD>
|
|
|
23 |
<DT><A HREF="#S56"><B>6.2.2 </B> - goto, make_local_lv, goto_local_lv,
|
|
|
24 |
long_jump, return_to_label</A><DD>
|
|
|
25 |
<DT><A HREF="#S57"><B>6.2.3 </B> - integer_test, NTEST</A><DD>
|
|
|
26 |
<DT><A HREF="#S58"><B>6.2.4 </B> - case</A><DD>
|
|
|
27 |
<DT><A HREF="#S59"><B>6.2.5 </B> - conditional, repeat</A><DD>
|
|
|
28 |
<DT><A HREF="#S60"><B>6.3 </B> - Exceptional flow</A><DD>
|
|
|
29 |
</DL>
|
|
|
30 |
<HR>
|
|
|
31 |
<H1>6 Control Flow within procedures</H1>
|
|
|
32 |
<A NAME=S52>
|
|
|
33 |
<HR><H2>6.1. Unconditional flow</H2>
|
|
|
34 |
<A NAME=S53>
|
|
|
35 |
<H3>6.1.1. sequence</H3>
|
|
|
36 |
To perform a sequential set of operations in TDF, one uses the constructor
|
|
|
37 |
sequence:<P>
|
|
|
38 |
<PRE>
|
|
|
39 |
<I> statements</I>: LIST(EXP)
|
|
|
40 |
<I> result</I>: EXP <I>x</I>
|
|
|
41 |
-> EXP <I>x</I>
|
|
|
42 |
</PRE>
|
|
|
43 |
Each of the <I>statements</I> are evaluated in order, throwing away
|
|
|
44 |
their results. Then, <I>result</I> is evaluated and its result is
|
|
|
45 |
the result of the sequence. <P>
|
|
|
46 |
A translator is free to rearrange the order of evaluation if there
|
|
|
47 |
is no observable difference other than in time or space. This applies
|
|
|
48 |
anywhere I say "something is evaluated and then ...". We
|
|
|
49 |
find this kind of statement in definitions of local variables in
|
|
|
50 |
<A HREF="guide7.html#34">section 5.3 on page 30</A>, and in the controlling
|
|
|
51 |
parts of the conditional constructions below. <P>
|
|
|
52 |
For a more precise discussion of allowable reorderings see (S7.14)</A>
|
|
|
53 |
.<P>
|
|
|
54 |
<A NAME=S54>
|
|
|
55 |
<HR><H2>6.2. Conditional flow</H2>
|
|
|
56 |
<A NAME=S55>
|
|
|
57 |
<H3>6.2.1. labelled, make_label</H3>
|
|
|
58 |
All simple changes of flow of control within a TDF procedure are done
|
|
|
59 |
by jumps or branches to LABELs, mirroring what actually happens in
|
|
|
60 |
most computers. There are three constructors which introduce LABELs;
|
|
|
61 |
the most general is labelled which allows arbitrary jumping between
|
|
|
62 |
its component EXPs:<P>
|
|
|
63 |
<PRE>
|
|
|
64 |
<I> placelabs_intro</I>: LIST(LABEL)
|
|
|
65 |
<I> starter</I>: EXP <I>x</I>
|
|
|
66 |
<I> places</I>: LIST(EXP)
|
|
|
67 |
-> EXP <I>w</I>
|
|
|
68 |
</PRE>
|
|
|
69 |
Each of the EXPs in <I>place</I>s is labelled by the corresponding
|
|
|
70 |
LABEL in <I>placelabs_intro</I>; these LABELs are constructed by
|
|
|
71 |
make_label applied to a TDFINT uniquely drawn from the LABEL name-space
|
|
|
72 |
introduced by the enclosing PROPS. The evaluation starts by evaluating
|
|
|
73 |
<I>starter</I>; if this runs to completion the result of the labelled
|
|
|
74 |
is the result of <I>starter.</I> If there is some jump to a LABEL
|
|
|
75 |
in<I> placelabs_intro</I> then control passes to the corresponding
|
|
|
76 |
EXP in <I>place</I>s and so on. If any of these EXPS<I> </I>runs to
|
|
|
77 |
completion then its result is the result of the labelled; hence the
|
|
|
78 |
SHAPE of the result, w, is the LUB of the SHAPEs of the component
|
|
|
79 |
EXPs. <P>
|
|
|
80 |
Note that control does not automatically pass from one EXP to the
|
|
|
81 |
next; if this is required the appropriate EXP must end with an explicit
|
|
|
82 |
goto.<P>
|
|
|
83 |
<A NAME=S56>
|
|
|
84 |
<H3>6.2.2. goto, make_local_lv, goto_local_lv, long_jump, return_to_label</H3>
|
|
|
85 |
The unconditional goto is the simplest method of jumping. In common
|
|
|
86 |
with all the methods of jumping using LABELs, its LABEL parameter
|
|
|
87 |
must have been introduced in an enclosing construction, like labelled,
|
|
|
88 |
which scopes it. <P>
|
|
|
89 |
One can also pick up a label value of SHAPE POINTER {code} (usually
|
|
|
90 |
implemented as a program address) using make_local_lv for later use
|
|
|
91 |
by an "indirect jump" such as goto_local_lv . Here the same
|
|
|
92 |
prohibition holds - the construction which introduced the LABEL must
|
|
|
93 |
still be active. <P>
|
|
|
94 |
The construction goto_local_lv only permits one to jump within the
|
|
|
95 |
current procedure; if one wished to do a jump out of a procedure into
|
|
|
96 |
a calling one, one uses long_jump which requires a pointer to the
|
|
|
97 |
destination frame (produced by current_env in the destination procedure)
|
|
|
98 |
as well as the label value. If a long_jump is made to a label, only
|
|
|
99 |
those local TAGs which have been defined with a visible ACCESS are
|
|
|
100 |
guaranteed to have preserved their values; the translator could allocate
|
|
|
101 |
the other TAGs in scope as registers whose values are not necessarily
|
|
|
102 |
preserved.<P>
|
|
|
103 |
A slightly "shorter" long jump is given by return_to_label.
|
|
|
104 |
Here the destination of the jump must a label value in the calling
|
|
|
105 |
procedure. Usually this value would be passed as parameter of the
|
|
|
106 |
call to provide an alternative exit to the procedure.<P>
|
|
|
107 |
<A NAME=S57>
|
|
|
108 |
<H3>6.2.3. integer_test, NTEST</H3>
|
|
|
109 |
Conditional branching is provided by the various _test constructors,
|
|
|
110 |
one for each primitive SHAPE except BITFIELD. I shall use integer_test
|
|
|
111 |
as the paradigm for them all:<P>
|
|
|
112 |
<PRE>
|
|
|
113 |
<I> nt</I>: NTEST
|
|
|
114 |
<I> dest</I>: LABEL
|
|
|
115 |
<I> arg1</I>: EXP INTEGER(<I>v</I>)
|
|
|
116 |
<I> arg2</I>: EXP INTEGER(<I>v</I>)
|
|
|
117 |
-> EXP TOP
|
|
|
118 |
</PRE>
|
|
|
119 |
The NTEST <I>nt</I> chooses a dyadic test (e.g. =, >=, <, etc.)
|
|
|
120 |
that is to be applied to the results of evaluating
|
|
|
121 |
<I>arg1</I> and <I>arg2</I>. If <I>arg1 nt arg2</I> then the result
|
|
|
122 |
is TOP; otherwise control passes to the LABEL <I>dest</I>. In other
|
|
|
123 |
words, integer_test acts like an assertion where if the assertion
|
|
|
124 |
is false, control passes to the LABEL instead of continuing in the
|
|
|
125 |
normal fashion. <P>
|
|
|
126 |
Some of the constructors for NTESTs are disallowed for some _tests
|
|
|
127 |
(e.g. proc_test ) while others are redundant for some _tests; for
|
|
|
128 |
example, not_greater_than is the same as less_than_or_equal for all
|
|
|
129 |
except possibly floating_test. where the use of NaNs (in the IEEE
|
|
|
130 |
sense) as operands may give different results.<P>
|
|
|
131 |
<A NAME=S58>
|
|
|
132 |
<H3>6.2.4. case</H3>
|
|
|
133 |
There are only two other ways of changing flow of control using LABELs.
|
|
|
134 |
One arises in ERROR_TREATMENTs which will be dealt with in the arithmetic
|
|
|
135 |
operations. The other is case:<P>
|
|
|
136 |
<PRE>
|
|
|
137 |
<I> exhaustive</I>: BOOL
|
|
|
138 |
<I> control</I>: EXP INTEGER(<I>v</I>)
|
|
|
139 |
<I> branches</I>: LIST(CASELIM)
|
|
|
140 |
-> EXP (<I>exhaustive</I> ? BOTTOM : TOP)
|
|
|
141 |
</PRE>
|
|
|
142 |
Each CASELIM is constructed using make_caselim:
|
|
|
143 |
<P>
|
|
|
144 |
<PRE>
|
|
|
145 |
branch: LABEL
|
|
|
146 |
lower: SIGNED_NAT
|
|
|
147 |
upper: SIGNED_NAT
|
|
|
148 |
-> CASELIM
|
|
|
149 |
</PRE>
|
|
|
150 |
In the case construction, the<I> control</I> EXP is evaluated and
|
|
|
151 |
tested to see whether its value lies inclusively between some <I>lower</I>
|
|
|
152 |
and <I>upper </I>in the list of CASELIMs. If so, control passes to
|
|
|
153 |
the corresponding <I>branch</I>. The order in which these tests are
|
|
|
154 |
performed is undefined, so it is probably best if the tests are exclusive.
|
|
|
155 |
The exhaustive flag being true asserts that one of the branches will
|
|
|
156 |
be taken and so the SHAPE of the result is BOTTOM. Otherwise, if none
|
|
|
157 |
of the branches are taken, its SHAPE is TOP and execution carries
|
|
|
158 |
on normally.<P>
|
|
|
159 |
<A NAME=S59>
|
|
|
160 |
<H3>6.2.5. conditional, repeat</H3>
|
|
|
161 |
Besides labelled, two other constructors, conditional and repeat,
|
|
|
162 |
introduce LABELs which can be used with the various jump instructions.
|
|
|
163 |
Both can be expressed as labelled, but have extra constraints which
|
|
|
164 |
make assertions about the use of the LABELs introduced and could usually
|
|
|
165 |
be translated more efficiently; hence producers are advised to use
|
|
|
166 |
them where possible. A conditional expression or statement would usually
|
|
|
167 |
be done using conditional:
|
|
|
168 |
<P>
|
|
|
169 |
<PRE>
|
|
|
170 |
<I> alt_label_intro</I>: LABEL
|
|
|
171 |
<I> first</I>: EXP <I>x</I>
|
|
|
172 |
<I> alt</I>: EXP <I>y</I>
|
|
|
173 |
-> EXP(LUB(<I>x, y</I>))
|
|
|
174 |
</PRE>
|
|
|
175 |
Here <I>first</I> is evaluated; if it terminates normally, its result
|
|
|
176 |
is the result of the conditional. If a jump to <I>alt_label_intro</I>
|
|
|
177 |
occurs then <I>alt</I> is evaluated and its result is the result of
|
|
|
178 |
the conditional. Clearly, this, so far, is just the same as labelled((<I>alt_label_intro
|
|
|
179 |
</I>), <I>first</I>, (<I>alt</I>)). However, conditional imposes the
|
|
|
180 |
constraint that <I>alt</I> cannot use <I>alt_label_intro</I>. All
|
|
|
181 |
jumps to <I>alt_label_intro</I> are "forward jumps" - a
|
|
|
182 |
useful property to know in a translator. <P>
|
|
|
183 |
Obviously, this kind of conditional is rather different to those found
|
|
|
184 |
in traditional high-level languages which usually have three components,
|
|
|
185 |
a boolean expression, a then-part and an else-part. Here, the <I>first</I>
|
|
|
186 |
component includes both the boolean expression and the then-part;
|
|
|
187 |
usually we find that it is a sequence of the tests (branching to <I>alt_label_intro
|
|
|
188 |
</I>) forming the boolean expression followed by the else-part. This
|
|
|
189 |
formulation means that HLL constructions like "andif" and
|
|
|
190 |
"orelse" do not require special constructions in TDF.<P>
|
|
|
191 |
A simple loop can be expressed using repeat:<P>
|
|
|
192 |
<PRE>
|
|
|
193 |
<I> repeat_label_intro</I>: LABEL
|
|
|
194 |
<I> start</I>: EXP TOP
|
|
|
195 |
<I> body</I>: EXP <I>y</I>
|
|
|
196 |
-> EXP <I>y</I>
|
|
|
197 |
</PRE>
|
|
|
198 |
The EXP <I>start</I> is evaluated, followed by <I>body</I> which is
|
|
|
199 |
labelled by <I>repeat_label_intro</I>. If a jump to <I>repeat_label_intro</I>
|
|
|
200 |
occurs in <I>body</I>, then <I>body</I> is re-evaluated. If <I>body</I>
|
|
|
201 |
terminates normally then its result is the result of the repeat. This
|
|
|
202 |
is just the same as:<P>
|
|
|
203 |
<PRE>
|
|
|
204 |
labelled((<I>repeat_label_intro</I>), sequence((<I>start</I>), goto(<I>repeat_label_intro
|
|
|
205 |
</I>)), <I>(body</I>))
|
|
|
206 |
</PRE>
|
|
|
207 |
except that no jumps to <I>repeat_label_intro</I> are allowed in <I>start</I>
|
|
|
208 |
- a useful place to do initialisations for the loop. <P>
|
|
|
209 |
Just as with conditionals, the tests for the continuing or breaking
|
|
|
210 |
the loop are included in <I>body</I> and require no special constructions.<P>
|
|
|
211 |
<A NAME=S60>
|
|
|
212 |
<HR><H2>6.3. <A NAME=31>Exceptional flow</H2>
|
|
|
213 |
A further way of changing the flow of control in a TDF program is
|
|
|
214 |
by means of exceptions. TDF exceptions currently arise from three
|
|
|
215 |
sources - overflow in arithmetic operations with trap ERROR_TREATMENT(see
|
|
|
216 |
<A HREF="guide10.html#6">section 8.1.1 on page 40</A>) , an attempt
|
|
|
217 |
to access a value via a nil pointer using assign_with_mode, contents_with_mode
|
|
|
218 |
or move_some(see <A HREF="guide9.html#8">section 7.3 on page 38</A>)
|
|
|
219 |
or a stack overflow on procedure entry with PROCPROPS check_stack(see
|
|
|
220 |
<A HREF="guide7.html#24">section 5.2.2 on page 29</A>) or a local_alloc_check.
|
|
|
221 |
<P>
|
|
|
222 |
Each of these exceptions have an ERROR_CODE ascribed to them, namely
|
|
|
223 |
overflow, nil_access and stack_overflow. Each ERROR_CODE can be made
|
|
|
224 |
into a distinct NAT by means of the constructor error_val; these NATs
|
|
|
225 |
could be used, for example, to discriminate the different kinds of
|
|
|
226 |
errors using a case construction.<P>
|
|
|
227 |
When one of these exceptions is raised, the translator will arrange
|
|
|
228 |
that a TOKEN, ~Throw, is called with the appropriate ERROR_CODE as
|
|
|
229 |
its (sole) parameter. Given that every language has a different way
|
|
|
230 |
of both characterising and handling exceptions, the exact expansion
|
|
|
231 |
of ~Throw must be given by the producer for that language - usually
|
|
|
232 |
it will involve doing a long_jump to some label specifying a signal
|
|
|
233 |
handler and translating the ERROR_CODE into its language-specific
|
|
|
234 |
representation.<P>
|
|
|
235 |
The expansion of ~Throw forms part of the language specific environment
|
|
|
236 |
required for the translation of TDF derived from the language, just
|
|
|
237 |
as the exact shape of FILE must be given for the translation of C.<P>
|
|
|
238 |
<HR>
|
|
|
239 |
<P><I>Part of the <A HREF="../index.html">TenDRA Web</A>.<BR>Crown
|
|
|
240 |
Copyright © 1998.</I></P>
|
|
|
241 |
</BODY>
|
|
|
242 |
</HTML>
|