Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<!-- Crown Copyright (c) 1998 -->
<HTML>
<HEAD>
<TITLE>Control Flow within procedures</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#400080" ALINK="#FF0000">
<A NAME=S51>
<H1>TDF Guide, Issue 4.0 </H1>
<H3>January 1998</H3>
<A HREF="guide9.html"><IMG SRC="../images/next.gif" ALT="next section">
</A> <A HREF="guide7.html">
<IMG SRC="../images/prev.gif" ALT="previous section"></A>
<A HREF="guide1.html"><IMG SRC="../images/top.gif" ALT="current document"></A>
<A HREF="../index.html"><IMG SRC="../images/home.gif" ALT="TenDRA home page">
</A>
<IMG SRC="../images/no_index.gif" ALT="document index"><P>
<HR>
<DL>
<DT><A HREF="#S52"><B>6.1 </B> - Unconditional flow</A><DD>
<DT><A HREF="#S53"><B>6.1.1 </B> - sequence</A><DD>
<DT><A HREF="#S54"><B>6.2 </B> - Conditional flow</A><DD>
<DT><A HREF="#S55"><B>6.2.1 </B> - labelled, make_label</A><DD>
<DT><A HREF="#S56"><B>6.2.2 </B> - goto, make_local_lv, goto_local_lv,
long_jump, return_to_label</A><DD>
<DT><A HREF="#S57"><B>6.2.3 </B> - integer_test, NTEST</A><DD>
<DT><A HREF="#S58"><B>6.2.4 </B> - case</A><DD>
<DT><A HREF="#S59"><B>6.2.5 </B> - conditional, repeat</A><DD>
<DT><A HREF="#S60"><B>6.3 </B> - Exceptional flow</A><DD>
</DL>
<HR>
<H1>6 Control Flow within procedures</H1>
<A NAME=S52>
<HR><H2>6.1. Unconditional flow</H2>
<A NAME=S53>
<H3>6.1.1. sequence</H3>
To perform a sequential set of operations in TDF, one uses the constructor
sequence:<P>
<PRE>
<I> statements</I>: LIST(EXP)
<I> result</I>: EXP <I>x</I>
-> EXP <I>x</I>
</PRE>
Each of the <I>statements</I> are evaluated in order, throwing away
their results. Then, <I>result</I> is evaluated and its result is
the result of the sequence. <P>
A translator is free to rearrange the order of evaluation if there
is no observable difference other than in time or space. This applies
anywhere I say "something is evaluated and then ...". We
find this kind of statement in definitions of local variables in
<A HREF="guide7.html#34">section 5.3 on page 30</A>, and in the controlling
parts of the conditional constructions below. <P>
For a more precise discussion of allowable reorderings see (S7.14)</A>
.<P>
<A NAME=S54>
<HR><H2>6.2. Conditional flow</H2>
<A NAME=S55>
<H3>6.2.1. labelled, make_label</H3>
All simple changes of flow of control within a TDF procedure are done
by jumps or branches to LABELs, mirroring what actually happens in
most computers. There are three constructors which introduce LABELs;
the most general is labelled which allows arbitrary jumping between
its component EXPs:<P>
<PRE>
<I> placelabs_intro</I>: LIST(LABEL)
<I> starter</I>: EXP <I>x</I>
<I> places</I>: LIST(EXP)
-> EXP <I>w</I>
</PRE>
Each of the EXPs in <I>place</I>s is labelled by the corresponding
LABEL in <I>placelabs_intro</I>; these LABELs are constructed by
make_label applied to a TDFINT uniquely drawn from the LABEL name-space
introduced by the enclosing PROPS. The evaluation starts by evaluating
<I>starter</I>; if this runs to completion the result of the labelled
is the result of <I>starter.</I> If there is some jump to a LABEL
in<I> placelabs_intro</I> then control passes to the corresponding
EXP in <I>place</I>s and so on. If any of these EXPS<I> </I>runs to
completion then its result is the result of the labelled; hence the
SHAPE of the result, w, is the LUB of the SHAPEs of the component
EXPs. <P>
Note that control does not automatically pass from one EXP to the
next; if this is required the appropriate EXP must end with an explicit
goto.<P>
<A NAME=S56>
<H3>6.2.2. goto, make_local_lv, goto_local_lv, long_jump, return_to_label</H3>
The unconditional goto is the simplest method of jumping. In common
with all the methods of jumping using LABELs, its LABEL parameter
must have been introduced in an enclosing construction, like labelled,
which scopes it. <P>
One can also pick up a label value of SHAPE POINTER {code} (usually
implemented as a program address) using make_local_lv for later use
by an "indirect jump" such as goto_local_lv . Here the same
prohibition holds - the construction which introduced the LABEL must
still be active. <P>
The construction goto_local_lv only permits one to jump within the
current procedure; if one wished to do a jump out of a procedure into
a calling one, one uses long_jump which requires a pointer to the
destination frame (produced by current_env in the destination procedure)
as well as the label value. If a long_jump is made to a label, only
those local TAGs which have been defined with a visible ACCESS are
guaranteed to have preserved their values; the translator could allocate
the other TAGs in scope as registers whose values are not necessarily
preserved.<P>
A slightly "shorter" long jump is given by return_to_label.
Here the destination of the jump must a label value in the calling
procedure. Usually this value would be passed as parameter of the
call to provide an alternative exit to the procedure.<P>
<A NAME=S57>
<H3>6.2.3. integer_test, NTEST</H3>
Conditional branching is provided by the various _test constructors,
one for each primitive SHAPE except BITFIELD. I shall use integer_test
as the paradigm for them all:<P>
<PRE>
<I> nt</I>: NTEST
<I> dest</I>: LABEL
<I> arg1</I>: EXP INTEGER(<I>v</I>)
<I> arg2</I>: EXP INTEGER(<I>v</I>)
-> EXP TOP
</PRE>
The NTEST <I>nt</I> chooses a dyadic test (e.g. =, >=, <, etc.)
that is to be applied to the results of evaluating
<I>arg1</I> and <I>arg2</I>. If <I>arg1 nt arg2</I> then the result
is TOP; otherwise control passes to the LABEL <I>dest</I>. In other
words, integer_test acts like an assertion where if the assertion
is false, control passes to the LABEL instead of continuing in the
normal fashion. <P>
Some of the constructors for NTESTs are disallowed for some _tests
(e.g. proc_test ) while others are redundant for some _tests; for
example, not_greater_than is the same as less_than_or_equal for all
except possibly floating_test. where the use of NaNs (in the IEEE
sense) as operands may give different results.<P>
<A NAME=S58>
<H3>6.2.4. case</H3>
There are only two other ways of changing flow of control using LABELs.
One arises in ERROR_TREATMENTs which will be dealt with in the arithmetic
operations. The other is case:<P>
<PRE>
<I> exhaustive</I>: BOOL
<I> control</I>: EXP INTEGER(<I>v</I>)
<I> branches</I>: LIST(CASELIM)
-> EXP (<I>exhaustive</I> ? BOTTOM : TOP)
</PRE>
Each CASELIM is constructed using make_caselim:
<P>
<PRE>
branch: LABEL
lower: SIGNED_NAT
upper: SIGNED_NAT
-> CASELIM
</PRE>
In the case construction, the<I> control</I> EXP is evaluated and
tested to see whether its value lies inclusively between some <I>lower</I>
and <I>upper </I>in the list of CASELIMs. If so, control passes to
the corresponding <I>branch</I>. The order in which these tests are
performed is undefined, so it is probably best if the tests are exclusive.
The exhaustive flag being true asserts that one of the branches will
be taken and so the SHAPE of the result is BOTTOM. Otherwise, if none
of the branches are taken, its SHAPE is TOP and execution carries
on normally.<P>
<A NAME=S59>
<H3>6.2.5. conditional, repeat</H3>
Besides labelled, two other constructors, conditional and repeat,
introduce LABELs which can be used with the various jump instructions.
Both can be expressed as labelled, but have extra constraints which
make assertions about the use of the LABELs introduced and could usually
be translated more efficiently; hence producers are advised to use
them where possible. A conditional expression or statement would usually
be done using conditional:
<P>
<PRE>
<I> alt_label_intro</I>: LABEL
<I> first</I>: EXP <I>x</I>
<I> alt</I>: EXP <I>y</I>
-> EXP(LUB(<I>x, y</I>))
</PRE>
Here <I>first</I> is evaluated; if it terminates normally, its result
is the result of the conditional. If a jump to <I>alt_label_intro</I>
occurs then <I>alt</I> is evaluated and its result is the result of
the conditional. Clearly, this, so far, is just the same as labelled((<I>alt_label_intro
</I>), <I>first</I>, (<I>alt</I>)). However, conditional imposes the
constraint that <I>alt</I> cannot use <I>alt_label_intro</I>. All
jumps to <I>alt_label_intro</I> are "forward jumps" - a
useful property to know in a translator. <P>
Obviously, this kind of conditional is rather different to those found
in traditional high-level languages which usually have three components,
a boolean expression, a then-part and an else-part. Here, the <I>first</I>
component includes both the boolean expression and the then-part;
usually we find that it is a sequence of the tests (branching to <I>alt_label_intro
</I>) forming the boolean expression followed by the else-part. This
formulation means that HLL constructions like "andif" and
"orelse" do not require special constructions in TDF.<P>
A simple loop can be expressed using repeat:<P>
<PRE>
<I> repeat_label_intro</I>: LABEL
<I> start</I>: EXP TOP
<I> body</I>: EXP <I>y</I>
-> EXP <I>y</I>
</PRE>
The EXP <I>start</I> is evaluated, followed by <I>body</I> which is
labelled by <I>repeat_label_intro</I>. If a jump to <I>repeat_label_intro</I>
occurs in <I>body</I>, then <I>body</I> is re-evaluated. If <I>body</I>
terminates normally then its result is the result of the repeat. This
is just the same as:<P>
<PRE>
labelled((<I>repeat_label_intro</I>), sequence((<I>start</I>), goto(<I>repeat_label_intro
</I>)), <I>(body</I>))
</PRE>
except that no jumps to <I>repeat_label_intro</I> are allowed in <I>start</I>
- a useful place to do initialisations for the loop. <P>
Just as with conditionals, the tests for the continuing or breaking
the loop are included in <I>body</I> and require no special constructions.<P>
<A NAME=S60>
<HR><H2>6.3. <A NAME=31>Exceptional flow</H2>
A further way of changing the flow of control in a TDF program is
by means of exceptions. TDF exceptions currently arise from three
sources - overflow in arithmetic operations with trap ERROR_TREATMENT(see
<A HREF="guide10.html#6">section 8.1.1 on page 40</A>) , an attempt
to access a value via a nil pointer using assign_with_mode, contents_with_mode
or move_some(see <A HREF="guide9.html#8">section 7.3 on page 38</A>)
or a stack overflow on procedure entry with PROCPROPS check_stack(see
<A HREF="guide7.html#24">section 5.2.2 on page 29</A>) or a local_alloc_check.
<P>
Each of these exceptions have an ERROR_CODE ascribed to them, namely
overflow, nil_access and stack_overflow. Each ERROR_CODE can be made
into a distinct NAT by means of the constructor error_val; these NATs
could be used, for example, to discriminate the different kinds of
errors using a case construction.<P>
When one of these exceptions is raised, the translator will arrange
that a TOKEN, ~Throw, is called with the appropriate ERROR_CODE as
its (sole) parameter. Given that every language has a different way
of both characterising and handling exceptions, the exact expansion
of ~Throw must be given by the producer for that language - usually
it will involve doing a long_jump to some label specifying a signal
handler and translating the ERROR_CODE into its language-specific
representation.<P>
The expansion of ~Throw forms part of the language specific environment
required for the translation of TDF derived from the language, just
as the exact shape of FILE must be given for the translation of C.<P>
<HR>
<P><I>Part of the <A HREF="../index.html">TenDRA Web</A>.<BR>Crown
Copyright © 1998.</I></P>
</BODY>
</HTML>