Subversion Repositories tendra.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<!-- Crown Copyright (c) 1998 -->
<HTML>
<HEAD>
<TITLE>Notes</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#400080" ALINK="#FF0000">
<H1><A NAME=S382>TDF Specification, Issue 4.0</A></H1>
<H3>January 1998</H3>
<A HREF="spec11.html"><IMG SRC="../images/next.gif" ALT="next section"></A>
<A HREF="spec9.html"><IMG SRC="../images/prev.gif" ALT="previous section"></A>
<A HREF="spec1.html"><IMG SRC="../images/top.gif" ALT="current document"></A>
<A HREF="../index.html"><IMG SRC="../images/home.gif" ALT="TenDRA home page">
</A>
<A HREF="spec12.html"><IMG SRC="../images/index.gif" ALT="document index"></A>
<P>
<HR>
<DL>
<DT><A HREF="#S383"><B>7.1</B> - Binding</A><DD>
<DT><A HREF="#S384"><B>7.2</B> - Character codes</A><DD>
<DT><A HREF="#S385"><B>7.3</B> - Constant evaluation</A><DD>
<DT><A HREF="#S386"><B>7.4</B> - Division and modulus</A><DD>
<DT><A HREF="#S387"><B>7.5</B> - Equality of EXPs</A><DD>
<DT><A HREF="#S388"><B>7.6</B> - Equality of SHAPEs</A><DD>
<DT><A HREF="#S389"><B>7.7</B> - Equality of ALIGNMENTS</A><DD>
<DT><A HREF="#S390"><B>7.8</B> - Exceptions and jumps</A><DD>
<DT><A HREF="#S391"><B>7.9</B> - Procedures</A><DD>
<DT><A HREF="#S392"><B>7.10</B> - Frames</A><DD>
<DT><A HREF="#S393"><B>7.11</B> - Lifetimes</A><DD>
<DT><A HREF="#S394"><B>7.12</B> - Alloca</A><DD>
<DT><A HREF="#S395"><B>7.13</B> - Memory Model</A><DD>
<DL>
<DT><A HREF="#S396"><B>7.13.1</B> - Simple model</A><DD>
<DT><A HREF="#S397"><B>7.13.2</B> - Comparison of pointers and offsets</A><DD>
<DT><A HREF="#S398"><B>7.13.3</B> - Circular types in languages</A><DD>
<DT><A HREF="#S399"><B>7.13.4</B> - Special alignments</A><DD>
<DT><A HREF="#S400"><B>7.13.5</B> - Atomic assignment</A><DD>
</DL>
<DT><A HREF="#S401"><B>7.14</B> - Order of evaluation</A><DD>
<DT><A HREF="#S402"><B>7.15</B> - Original pointers</A><DD>
<DT><A HREF="#S403"><B>7.16</B> - Overlapping</A><DD>
<DT><A HREF="#S404"><B>7.17</B> - Incomplete assignment</A><DD>
<DT><A HREF="#S405"><B>7.18</B> - Representing integers</A><DD>
<DT><A HREF="#S406"><B>7.19</B> - Overflow and Integers</A><DD>
<DT><A HREF="#S407"><B>7.20</B> - Representing floating point</A><DD>
<DT><A HREF="#S408"><B>7.21</B> - Floating point errors</A><DD>
<DT><A HREF="#S409"><B>7.22</B> - Rounding and floating point</A><DD>
<DT><A HREF="#S410"><B>7.23</B> - Floating point accuracy</A><DD>
<DT><A HREF="#S411"><B>7.24</B> - Representing bitfields</A><DD>
<DT><A HREF="#S412"><B>7.25</B> - Permitted limits</A><DD>
<DT><A HREF="#S413"><B>7.26</B> - Least Upper Bound</A><DD>
<DT><A HREF="#S414"><B>7.27</B> - Read-only areas</A><DD>
<DT><A HREF="#S415"><B>7.28</B> - Tag and Token signatures</A><DD>
<DT><A HREF="#S416"><B>7.29</B> - Dynamic initialisation</A><DD>
</DL>
<HR>
<H1>7. Notes</H1>
<A NAME=S383>

<HR>
<H2>7.1. Binding</H2>
<A NAME=M1><A NAME=M2>The following constructions introduce 
<CODE>TAG</CODE>s: <I>identify</I>, <I>variable</I>, <I>make_proc</I>,
<I>make_general_proc</I>, <I>make_id_tagdec</I>, <I>make_var_tagdec</I>,
<I>common_tagdec</I>. 
<P>
During the evaluation of <I>identify</I> and <I>variable</I> a value,
<I>v</I>, is produced which is bound to the <CODE>TAG</CODE> during
the evaluation of an <CODE>EXP</CODE> or <CODE>EXP</CODE>s. The 
<CODE>TAG</CODE> is &quot;in scope&quot; for these <CODE>EXP</CODE>s.
This means that in the <CODE>EXP</CODE> a use of the <CODE>TAG</CODE>
is permissible and will refer to the declaration. 
<P>
The <I>make_proc</I> and <I>make_general_proc</I> construction introduces
<CODE>TAG</CODE>s which are bound to the actual parameters on each
call of the procedure. These <CODE>TAG</CODE>s are &quot;in scope&quot;
for the body of the procedure. 
<P>
If a <I>make_proc</I> or <I>make_general_proc</I> construction occurs
in the body of another <I>make_proc</I> or <I>make_general_proc</I>,
the <CODE>TAG</CODE>s of the inner procedure are not in scope in the
outer procedure, nor are the <CODE>TAG</CODE>s of the outer in scope
in the inner. 
<P>
The <I>apply_general_proc</I> construction permits the introduction
of 
<CODE>TAG</CODE>s whose scope is the <I>postlude</I> argument. These
are bound to the values of caller parameters after the evaluation
of the body of the procedure. 
<P>
The <I>make_id_tagdec</I>, <I>make_var_tagdec</I> and <I>common_tagdec</I>
constructions introduce <CODE>TAG</CODE>s which are &quot;in scope&quot;
throughout all the <I>tagdef</I> <CODE>UNIT</CODE>s. These <CODE>TAG</CODE>s
may have values defined for them in the <I>tagdef</I> <CODE>UNIT</CODE>s,
or values may be supplied by linking. 
<P>
<A NAME=M3><A NAME=M4><A NAME=M5>The following constructions introduce
<CODE>LABEL</CODE>s: <I>conditional</I>, 
<I>repeat</I>, <I>labelled</I>. 
<P>
The construction themselves define <CODE>EXP</CODE>s for which these
<CODE>LABEL</CODE>s are &quot;in scope&quot;. This means that in the
<CODE>EXP</CODE>s a use of the <CODE>LABEL</CODE> is permissible and
will refer to the introducing construction. 
<P>
<CODE>TAG</CODE>s, <CODE>LABEL</CODE>s and <CODE>TOKEN</CODE>s (as
<CODE>TOKEN</CODE> parameters) introduced in the body of a 
<CODE>TOKEN</CODE> definition are systematically renamed in their
scope each time the <CODE>TOKEN</CODE> definition is applied. The
scope will be completely included by the <CODE>TOKEN</CODE> definition.
<P>
Each of the values introduced in a <CODE>UNIT</CODE> will be named
by a different <CODE>TAG</CODE>, and the labelling constructions will
use different labels, so no visibility rules are needed. The set of
<CODE>TAG</CODE>s and <CODE>LABEL</CODE>s used in a simple 
<CODE>UNIT</CODE> are considered separately from those in another
simple 
<CODE>UNIT</CODE>, so no question of visibility arises. The compound
and link <CODE>UNIT</CODE>s provide a method of relating the items
in one simple <CODE>UNIT</CODE> to those in another, but this is through
the intermediary of another set of <CODE>TAG</CODE>s and <CODE>TOKEN</CODE>s
at the <CODE>CAPSULE</CODE> level. 
<P>
<A NAME=S384>

<HR>
<H2>7.2. Character codes</H2>
<A NAME=M6>TDF does not have a concept of characters. It transmits
integers of various sizes. So if a producer wishes to communicate
characters to an installer, it will usually have to do so by encoding
them in some way as integers. 
<P>
An ANSI C producer sending a TDF program to a set of normal C environments
may well choose to encode its characters using the ASCII codes, an
EBCDIC based producer transmitting to a known set of EBCDIC environments
might use the code directly, and a wide character producer might likewise
choose a specific encoding. For some programs this way of proceeding
is necessary, because the codes are used both to represent characters
and for arithmetic, so the particular encoding is enforced. In these
cases it will not be possible to translate the characters to another
encoding because the character codes will be used in the TDF as ordinary
integers, which must not be translated. 
<P>
Some producers may wish to transmit true characters, in the sense
that something is needed to represent particular printing shapes and
nothing else. These representations will have to be transformed into
the correct character encoding on the target machine. 
<P>
Probably the best way to do this is to use <CODE>TOKEN</CODE>s. A
fixed representation for the printing marks could be chosen in terms
of integers and <CODE>TOKEN</CODE>s introduced to represent the translation
from these integers to local character codes, and from strings of
integers to strings of local character codes. These definitions could
be bound on the target machine and the installer should be capable
of translating these constructions into efficient machine code. To
make this a standard, unique <CODE>TOKEN</CODE>s should be used. 
<P>
But this raises the question, who chooses the fixed representation
and the unique <CODE>TOKEN</CODE>s and their specification? Clearly
TDF provides a mechanism for performing the standardisation without
itself defining a standard. 
<P>
Here TDF gives rise to the need for extra standards, especially in
the specification of globally named unique <CODE>TOKEN</CODE>s. 
<P>
<A NAME=S385>

<HR>
<H2>7.3. <A NAME=7>Constant evaluation</H2>
<A NAME=M8><A NAME=M9>Some constructions require an 
<CODE>EXP</CODE> argument which is &quot;constant at install time&quot;.
For an <CODE>EXP</CODE> to satisfy this condition it must be constructed
according to the following rules after substitution of token definitions
and selection of <I>exp_cond</I> branches. 
<P>
If it contains <I>obtain_tag</I> then the tag will be introduced within
the <CODE>EXP</CODE>, or defined with <I>make_id_tagdef</I> within
the current capsule. 
<P>
It may not contain any of the following constructions: <I>apply_proc,
apply_general_proc, assign_with_mode</I>, <I>contents_with_mode</I>,
<I>continue</I>, <I>current_env</I>, <I>error_jump</I>, 
<I>goto_local_lv</I>, <I>make_local_lv</I>, <I>move_some</I>, 
<I>repeat</I>, <I>round_as_state</I>. 
<P>
Unless it is the <CODE>EXP</CODE> argument of a <CODE>TAGDEF</CODE>,
a &quot;constant at install time&quot; may not contain <I>env_offset</I>
or <I>env_size</I>. 
<P>
Any use of <I>contents</I> or <I>assign</I> will be applied only to
<CODE>POINTER</CODE>s derived from <I>variable</I> constructions.
<P>
If it contains <I>labelled</I> there will only be jumps to the 
<CODE>LABEL</CODE>s from within <I>starter</I>, not from within any
of the <I>places</I>. 
<P>
Any use of <I>obtain_tag</I> defined with <I>make_id_tagdef</I> will
occur after the end of the <I>make_id_tagdef</I>. 
<P>
Note specifically that a constant <CODE>EXP</CODE> forming the defining
value of a <CODE>TAGDEF</CODE> construct may contain <I>env_offset</I>
and/or <I>env_size</I>. 
<P>
<A NAME=S386>

<HR>
<H2>7.4. <A NAME=10>Division and modulus</H2>
<A NAME=M11><A NAME=M12>Two classes of division (D) and remainder
(M) construct are defined. The two classes have the same definition
if both operands have the same sign. Neither is defined if the second
argument is zero. 
<P><B>Class 1</B>: 
<PRE>
        <I>p</I> D1 <I>q</I> = <I>n</I>
</PRE>
where: 
<PRE>
        <I>p</I> = <I>n</I>*<I>q</I> + (<I>p</I> M1 <I>q</I>)
        sign(<I>p</I> M1 <I>q</I>) = sign(<I>q</I>)
        0 &lt;= |<I>p</I> M1 <I>q</I>| &lt; |<I>q</I>|
</PRE>
<P><B>Class 2</B>: 
<PRE>
        <I>p</I> D2 <I>q</I> = <I>n</I>
</PRE>
where: 
<PRE>
        <I>p</I> = <I>n</I>*<I>q</I> + (<I>p</I> M2 <I>q</I>)
        sign(<I>p</I> M2 <I>q</I>) = sign(<I>p</I>)
        0 &lt;= |<I>p</I> M2 <I>q</I>| &lt; |<I>q</I>|
</PRE>
<P>
<A NAME=S387>

<HR>
<H2>7.5. Equality of EXPs</H2>
<A NAME=M13>A definition of equality of <CODE>EXP</CODE>s would be
a considerable part of a formal specification of TDF, and is not given
here. 
<P>
<A NAME=S388>

<HR>
<H2>7.6. Equality of SHAPEs</H2>
<A NAME=M14>Equality of <CODE>SHAPE</CODE>s is defined recursively:
<UL>
<LI>Two <CODE>SHAPE</CODE>s are equal if they are both <CODE>BOTTOM</CODE>,
or both <CODE>TOP</CODE> or both <CODE>PROC</CODE>.<P>
<LI>Two <CODE>SHAPE</CODE>s are equal if they are both <I>integer</I>
or both <I>floating</I>, or both <I>bitfield</I>, and the corresponding
parameters are equal.<P>
<LI>Two <CODE>SHAPE</CODE>s are equal if they are both <CODE>NOF</CODE>,
the numbers of items are equal and the <CODE>SHAPE</CODE> parameters
are equal.<P>
<LI>Two <CODE>OFFSET</CODE>s or two <CODE>POINTER</CODE>s are equal
if their <CODE>ALIGNMENT</CODE> parameters are pairwise equal.<P>
<LI>Two <CODE>COMPOUND</CODE>s are equal if their <CODE>OFFSET</CODE>
<CODE>EXP</CODE>s are equal.<P>
<LI>No other pairs of <CODE>SHAPE</CODE>s are equal. 
</UL>
<P>
<A NAME=S389>

<HR>
<H2>7.7. <A NAME=15>Equality of ALIGNMENTs</H2>
<A NAME=M16>Two <CODE>ALIGNMENT</CODE>s are equal if and only if they
are equal sets. 
<P>
<A NAME=S390>

<HR>
<H2>7.8. <A NAME=17>Exceptions and jumps</H2>
TDF allows simply for labels and jumps within a procedure, by means
of the <I>conditional</I>, <I>labelled</I> and <I>repeat</I> constructions,
and the <I>goto</I>, <I>case</I> and various <I>test</I> constructions.
But there are two more complex jumping situations. 
<P>
First there is the jump, known to stay within a procedure, but to
a computed destination. Many languages have discouraged this kind
of construction, but it is still available in Cobol (implicitly),
and it can be used to provide other facilities (see below). TDF allows
it by means of the <CODE>POINTER(</CODE>{<I>code</I><CODE>})</CODE>.
TDF is arranged so that this can usually be implemented as the address
of the label. The <I>goto_local_lv</I> construction just jumps to
the label. 
<P>
The other kind of construction needed is the jump out of a procedure
to a label which is still active, restoring the environment of the
destination procedure: the long jump. Related to this is the notion
of exception. Unfortunately long jumps and exceptions do not co-exist
well. Exceptions are commonly organised so that any necessary destruction
operations are performed as the stack of frames is traversed; long
jumps commonly go directly to the destination. TDF must provide some
facility which can express both of these concepts. Furthermore exceptions
come in several different versions, according to how the exception
handlers are discriminated and whether exception handling is initiated
if there is no handler which will catch the exception. 
<P>
Fortunately the normal implementations of these concepts provide a
suggestion as to how they can be introduced into TDF. The local label
value provides the destination address, the environment (produced
by <I>current_env</I>) provides the stack frame for the destination,
and the stack re-setting needed by the local label jumps themselves
provides the necessary stack information. If more information is needed,
such as which exception handlers are active, this can be created by
producing the appropriate TDF. 
<P>
So TDF takes the long jump as the basic construction, and its parameters
are a local label value and an environment. Everything else can be
built in terms of these. 
<P>
The TDF arithmetic constructions allows one to specify a <CODE>LABEL</CODE>
as destination if the result of the operation is exceptional. This
is sufficient for the kind of explicit exception handling found in
C++ and, in principle, could also be used to implement the kind of
&quot;automatic&quot; exception detection and handling found in Ada,
for example. 
<P>
However many architectures have facilities for automatically trapping
on exceptions without explicit testing. To take advantage of this,
there is a <I>trap</I> <CODE>ERROR_TREATMENT</CODE> with associated
<CODE>ERROR_CODE</CODE>s. The action taken on an exception with 
<I>trap</I> <CODE>ERROR_TREATMENT</CODE> will be to &quot;throw&quot;
the 
<CODE>ERROR_CODE</CODE>.  Since each language has its own idea of
how to interpret the <CODE>ERROR_CODE</CODE> and handle exceptions,
the onus is on the producer writer to describe how to throw an 
<CODE>ERROR_CODE</CODE>. 
<P>
The producer writer must give a definition of a <CODE>TOKEN</CODE>
<I>~Throw</I> : <CODE>NAT</CODE> -&gt; <CODE>EXP</CODE> where the
<CODE>NAT</CODE> will be the <I>error_val</I> of some <CODE>ERROR_CODE</CODE>.
The expansion of this token will be consistent with the interpretation
of the relevant <CODE>ERROR_CODE</CODE> and the method of handling
exceptions.  Usually this will consist of decoding the 
<CODE>ERROR_CODE</CODE> and doing a long_jump on some globals set
up by the procedure in which the exception handling takes place. 
<P>
The translator writer will provide a parameterless <CODE>EXP TOKEN</CODE>,
<I>~Set_signal_handler</I>.  This <CODE>TOKEN</CODE> will use <I>~Throw</I>
and must be applied before any possible exceptions. This implies that
the definition of both <I>~Throw</I> and 
<I>~Set_signal_handler</I> must be bound before translation of any
<CODE>CAPSULE</CODE> which uses them, presumeably by linking with
some TDF libraries. 
<P>
These tokens are specified in more detail in the companion document,
<A HREF="register.html">TDF Token Register</A>. 
<P>
<A NAME=S391>

<HR>
<H2>7.9. <A NAME=18>Procedures</H2>
The <I>var_intro</I> of a <I>make_proc</I>, if present, may be used
under one of two different circumstances. In one circumstance, the
<CODE>POINTER TAG</CODE> provided by the <I>var_intro</I> is used
to access the actual <I>var_param</I> of an <I>apply_proc</I>. If
this is the case, all uses of <I>apply_proc</I> which have the effect
of calling this procedure will have the <I>var_param</I> option present,
and they will all have precisely the same number of <I>params</I>
as 
<I>params_intro</I> in the <I>make_proc</I>. The body of the 
<I>make_proc</I> can access elements of the <I>var_param</I> by using
<CODE>OFFSET</CODE> arithmetic relative to the <CODE>POINTER TAG</CODE>.
This provides a method of supplying a variable number of parameters,
by composing them into a compound value which is supplied as the 
<I>var_param</I>. 
<P>
However, this has proved to be unsatisfactory for the implementation
of variable number of parameters in C - one cannot choose the 
<CODE>POINTER</CODE> alignment of the <CODE>TAG</CODE> a priori in
non-prototype calls. 
<P>
An alternative circumstance for using <I>var_intro</I> is where all
uses of <I>apply_proc</I> which have the effect of calling this procedure
may have more <I>params</I> present than the number of <I>params_intro</I>,
and none of them will have their <I>var_param</I> option present.
The body of the <I>make_proc</I> can access the additional params
by using installer-defined <CODE>TOKEN</CODE>s specified in the companion
document <A HREF="register.html">TDF Token Register</A>, analogous
to the use of variable argument lists in C. A local variable <I>v</I>
of shape <I>~va_list</I> must be initialised to <I>~__va_start</I>(<I>p</I>),
where <I>p</I> is the 
<CODE>POINTER</CODE> obtained from the <I>var_intro</I>. Successive
elements of the <I>params</I> list can then be obtained by successive
applications of <I>~va_arg</I>(<I>v</I>,<I>s</I>) where <I>s</I> is
the 
<CODE>SHAPE</CODE> of element obtained. Finally, 
<I>~va_end</I>(<I>v</I>) completes the use of <I>v</I>. 
<P>
The definition of caller parameters in general procedures addesses
this difficulty in a different way, by describing the layout of caller
parameters qualified by <CODE>PROCPROPS</CODE> <I>var_callers</I>.
This allows both the call and the body to have closely associated
views of the <CODE>OFFSET</CODE>s within a parameter set, regardless
of whether or not the particular parameter has been named. The installer-defined
<CODE>TOKEN</CODE> <I>~next_caller_offset</I> provides access to successive
caller parameters, by using <CODE>OFFSET</CODE>s relative to the current
frame pointer <I>current_env</I>, adjusting for any differences there
may be between the closely associated views.  The 
<I>caller_intro</I> list of the <I>make_general_proc</I> must not
be empty, then the sequence of <CODE>OFFSET</CODE>s can start with
an appropriate <I>env_offset</I>. Similar consideration applies to
accessing within the callee parameters, using the installer-defined
<CODE>TOKEN</CODE> <I>~next_callee_offset</I>. 
<P>
All uses of <I>return</I>, <I>untidy_return</I> and <I>tail_call</I>
in a procedure will return values of the same <CODE>SHAPE</CODE>,
and this will be the <I>result_shape</I> specified in all uses of
<I>apply_proc</I> or <I>apply_general_proc</I> calling the procedure.
<P>
The use of <I>untidy_return</I> gives a generalisation of 
<I>local_alloc</I>.  It extends the validity of pointers allocated
by 
<I>local_alloc</I> within the immediatly enclosing procedure into
the calling procedure.  The original space of these pointers may be
invalidated by <I>local_free</I> just as if it had been generated
by 
<I>local_alloc</I> in the calling procedure. 
<P>
The <CODE>PROCPROPS</CODE> <I>check_stack</I> may be used to check
that limit set by set_stack_limit is not exceeded by the allocation
of the static locals of a procedure body to be obeyed. If it is exceeded
then the producer-defined <CODE>TOKEN</CODE> <I>~Throw</I>: <CODE>NAT</CODE>
-&gt; <CODE>EXP</CODE> will be invoked as 
<I>~Throw</I>(<I>error_val</I>(<I>stack_overflow</I>)).  Note that
this will not include any space generated by <CODE>local_alloc</CODE>;
an explicit test is required to do check these. 
<P>
Any <CODE>SHAPE</CODE> is permitted as the <I>result_shape</I> in
an <I>apply_proc</I> or <I>apply_general_proc</I>. 
<P>
<A NAME=S392>

<HR>
<H2>7.10. <A NAME=19>Frames</H2>
<A NAME=M20>TDF states that while a particular procedure activation
is current, it is possible to create a <CODE>POINTER</CODE>, by using
<I>current_env</I>, which gives access to all the declared variables
and identifications of the activation which are alive and which have
been marked as <I>visible</I>. The construction 
<I>env_offset</I> gives the <CODE>OFFSET</CODE> of one of these relative
to such a <CODE>POINTER</CODE>.  These constructions may serve for
several purposes. 
<P>
One significant purpose is to implement such languages as Pascal which
have procedures declared inside other procedures. One way of implementing
this is by means of a &quot;display&quot;, that is, a tuple of frame
pointers of active procedures. 
<P>
Another purpose is to find active variables satisfying some criterion
in all the procedure activations. This is commonly required for garbage
collection. TDF does not force the installer to implement a frame
pointer register, since some machines do not work best in this way.
Instead, a frame pointer is created only if required by <I>current_env</I>.
The implication of this is that this sort of garbage collection needs
the collaboration of the producer to create TDF which makes the correct
calls on <I>current_env</I> and <I>env_offset</I> and place suitable
values in known positions. 
<P>
Programs compiled especially to provide good diagnostic information
can also use these operations. 
<P>
In general any program which wishes to manipulate the frames of procedures
other than the current one can use <I>current_env</I> and <I>env_offset</I>
to do so. 
<P>
A frame consists of three components, the caller parameters, callee
parameters and locals of the procedure involved. Since each component
may have different internal methods of access within the frame, each
has a different special frame alignment associated with pointers within
them. These are <I>callers_alignment</I>, <I>callees_alignment</I>
and 
<I>locals_alignment</I>. The <CODE>POINTER</CODE> produced by 
<I>current_env</I> will be some union of these special alignments
depending on how the procedure was defined. 
<P>
Each of these frame alignments are considered to contain any 
<CODE>ALIGNMENT</CODE> produced by <I>alignment</I> from any 
<CODE>SHAPE</CODE>. Note that this does not say that they are the
set union of all such <CODE>ALIGNMENT</CODE>s. This is because the
interpretation of pointer and offset operations (notably 
<I>add_to_pointer</I>) may be different depending on the implementation
of the frames; they may involve extra indirections. 
<P>
Accordingly, because of the constraints on <I>add_to_ptr</I>, an 
<CODE>OFFSET</CODE> produced by <I>env_offset</I> can only be added
to a 
<CODE>POINTER</CODE> produced by <I>current_env</I>. It is a further
constraint that such an <CODE>OFFSET</CODE> will only be added to
a 
<CODE>POINTER</CODE> produced from <I>current_env</I> used on the
procedure which declared the <CODE>TAG</CODE>. 
<P>
<A NAME=S393>

<HR>
<H2>7.11. Lifetimes</H2>
<A NAME=M21><CODE>TAG</CODE>s are bound to values during the evaluation
of <CODE>EXP</CODE>s, which are specified by the construction which
introduces the <CODE>TAG</CODE>. The evaluation of these 
<CODE>EXP</CODE>s is called the lifetime of the activation of the
<CODE>TAG</CODE>. 
<P>
Note that lifetime is a different concept from that of scope. For
example, if the <CODE>EXP</CODE> contains the application of a procedure,
the evaluation of the body of the procedure is within the lifetime
of the <CODE>TAG</CODE>, but the <CODE>TAG</CODE> will not be in scope.
<P>
A similar concept applies to <CODE>LABEL</CODE>s. 
<P>
<A NAME=S394>

<HR>
<H2>7.12. <A NAME=22>Alloca</H2>
<A NAME=M23>The constructions involving <I>alloca</I>
(<I>last_local</I>, <I>local_alloc</I>, <I>local_free</I>, 
<I>local_free_all</I>) as well as the <I>untidy_return</I> construction
imply a stack-like implementation which is related to procedure calls.
They may be implemented using the same stack as the procedure frames,
if there is such a stack, or it may be more convenient to implement
them separately. However note that if the <I>alloca</I> mechanism
is implemented as a stack, this may be an upward or a downward growing
stack. 
<P>
The state of this notional stack is referred to here as the <I>alloca</I>
state. The construction <I>local_alloc</I> creates a new space on
the <I>alloca</I> stack, the size of this space being given by an
<CODE>OFFSET</CODE>. In the special case that this <CODE>OFFSET</CODE>
is zero, <I>local_alloc</I> in effect gives the current <I>alloca</I>
state (normally a <CODE>POINTER</CODE> to the top of the stack). 
<P>
A use of <I>local_free_all</I> returns the <I>alloca</I> state to
what it was on entry to the current procedure. 
<P>
The construction <I>last_local</I> gives a <CODE>POINTER</CODE> to
the top item on the stack, but it is necessary to give the size of
this (as an <CODE>OFFSET</CODE>) because this cannot be deduced if
the stack is upward growing. This top item will be the whole of an
item previously allocated with <I>local_alloc</I>. 
<P>
The construction <I>local_free</I> returns the state of the <I>alloca</I>
machine to what it was when its parameter <CODE>POINTER</CODE> was
allocated. The <CODE>OFFSET</CODE> parameter will be the same value
as that with which the <CODE>POINTER</CODE> was allocated. 
<P>
The <CODE>ALIGNMENT</CODE> of the <CODE>POINTER</CODE> delivered by
<I>local_alloc</I> is <I>alloca_alignment</I>. This shall include
the set union of all the <CODE>ALIGNMENT</CODE>s which can be produced
by <I>alignment</I> from any <CODE>SHAPE</CODE>. 
<P>
<A NAME=M24><A NAME=M25>The use of <I>alloca_alignment</I>
arises so that the <I>alloca</I> stack can hold any kind of value.
The sizes of spaces allocated must be rounded up to the appropriate
<CODE>ALIGNMENT</CODE>. Since this includes all value 
<CODE>ALIGNMENT</CODE>s a value of any <CODE>ALIGNMENT</CODE> can
be assigned into this space.  Note that there is no necessary relation
with the special frame alignments (see <A HREF="#19">section 7.10</A>)
though they must both contain all the <CODE>ALIGNMENT</CODE>s which
can be produced by <I>alignment</I> from any <CODE>SHAPE</CODE>. 
<P>
Stack pushing is <I>local_alloc</I>. Stack popping can be performed
by use of <I>last_local</I> and <I>local_free</I>. Remembering the
state of the <I>alloca</I> stack and returning to it can be performed
by using 
<I>local_alloc</I> with a zero <CODE>OFFSET</CODE> and 
<I>local_free</I>. 
<P>
Note that stack pushing can also be achieved by the use of a procedure
call with <I>untidy_return</I>. 
<P>
A transfer of control to a local label by means of <I>goto</I>, 
<I>goto_local_lv</I>, any <I>test</I> construction or any 
<I>error_jump</I> will not change the <I>alloca</I> stack. 
<P>
<I>If an installer implements identify and variable by creating space
on a stack when they come into existence, rather than doing the allocation
for identify and variable at the start of a procedure activation,
then it may have to consider making the alloca stack into a second
stack.</I>
<P>
<A NAME=S395>

<HR>
<H2>7.13. <A NAME=26>Memory Model</H2>
<A NAME=M27><A NAME=M28><A NAME=M29>The layout of data in memory is
entirely determined by the calculation of 
<CODE>OFFSET</CODE>s relative to <CODE>POINTER</CODE>s. That is, it
is determined by <CODE>OFFSET</CODE> arithmetic and the <I>add_to_ptr</I>
construction. 
<P>
A <CODE>POINTER</CODE> is parameterised by the <CODE>ALIGNMENT</CODE>
of the data indicated. An <CODE>ALIGNMENT</CODE> is a set of all the
different kinds of basic value which can be indicated by a 
<CODE>POINTER</CODE>.  That is, it is a set chosen from all 
<CODE>VARIETY</CODE>s, all <CODE>FLOATING_VARIETY</CODE>s, <I>all</I>
<CODE>BITFIELD_VARIETY</CODE>s<I>, proc</I>, <I>code</I>, 
<I>pointer</I> and <I>offset</I>. There are also three special 
<CODE>ALIGNMENT</CODE>s, <I>frame_alignment</I>, <I>alloca_alignment</I>
and <I>var_param_alignment</I>. 
<P>
The parameter of a <CODE>POINTER</CODE> will not consist entirely
of <CODE>BITFIELD_VARIETY</CODE>s. 
<P>
The implication of this is that the <CODE>ALIGNMENT</CODE> of all
procedures is the same, the <CODE>ALIGNMENT</CODE> of all 
<CODE>POINTER</CODE>s is the same and the <CODE>ALIGNMENT</CODE> of
all 
<CODE>OFFSET</CODE>s is the same. 
<P>
At present this corresponds to the state of affairs for all machines.
But it is certainly possible that, for example, 64-bit pointers might
be aligned on 64-bit boundaries while 32-bit pointers are aligned
on 32-bit boundaries. In this case it will become necessary to add
different kinds of pointer to TDF. This will not present a problem,
because, to use such pointers, similar changes will have to be made
in languages to distinguish the kinds of pointer if they are to be
mixed. 
<P>
The difference between two <CODE>POINTER</CODE>s is measured by an
<CODE>OFFSET</CODE>. Hence an <CODE>OFFSET</CODE> is parameterised
by two <CODE>ALIGNMENT</CODE>s, that of the starting <CODE>POINTER</CODE>
and that of the end <CODE>POINTER</CODE>. The <CODE>ALIGNMENT</CODE>
set of the first must include the <CODE>ALIGNMENT</CODE> set of the
second. 
<P>
The parameters of an <CODE>OFFSET</CODE> may consist entirely of 
<CODE>BITFIELD_VARIETY</CODE>s. 
<P>
The operations on <CODE>OFFSET</CODE>s are subject to various constraints
on <CODE>ALIGNMENT</CODE>s. It is important not to read into offset
arithmetic what is not there. Accordingly some rules of the algebra
of <CODE>OFFSET</CODE>s are given below. 
<UL>
<LI><I>offset_add</I> is associative.<P>
<LI><I>offset_mult</I> corresponds to repeated offset_addition.<P>
<LI><I>offset_max</I> is commutative, associative and idempotent.<P>
<LI><I>offset_add</I> distributes over <I>offset_max</I> where they
form legal expressions.<P>
<LI><I>offset_test</I>(<I>prob</I>, &gt;= , <I>a</I>, <I>b</I>) continues
if <I>offset_max</I>(<I>a</I>,<I>b</I>) = <I>a</I>.<P>
</UL>
<P>
<A NAME=S396>
<H3>7.13.1. Simple model</H3>
<A NAME=M30>An example of the representation of <CODE>OFFSET</CODE>
arithmetic is given below. This is not a definition, but only an example.
In order to make this clear a machine with bit addressing is hypothesized.
This machine is referred to as the simple model. 
<P>
In this machine <CODE>ALIGNMENT</CODE>s will be represented by the
number by which the bit address of data must be divisible. For example,
8-bit bytes might have an <CODE>ALIGNMENT</CODE> of 8, longs of 32
and doubles of 64. <CODE>OFFSET</CODE>s will be represented by the
displacement in bits from a <CODE>POINTER</CODE>. <CODE>POINTER</CODE>s
will be represented by the bit address of the data. Only one memory
space will exist. Then in this example a possible conforming implementation
would be as follows. 
<UL>
<LI><I>add_to_ptr</I> is addition.<P>
<LI><I>offset_add</I> is addition.<P>
<LI><I>offset_div</I> and <I>offset_div_by_int</I> are exact division.<P>
<LI><I>offset_max</I> is maximum.<P>
<LI><I>offset_mult</I> is multiply.<P>
<LI><I>offset_negate</I> is negate.<P>
<LI><I>offset_pad</I>(<I>a</I>, <I>x</I>) is ((<I>x</I> + <I>a</I>
- 1) / <I>a</I>) * <I>a</I><P>
<LI><I>offset_subtract</I> is subtract.<P>
<LI><I>offset_test</I> is <I>integer_test</I>.<P>
<LI><I>offset_zero</I> is 0.<P>
<LI><I>shape_offset</I>(<I>s</I>) is the minimum number of bits needed
to be moved to move a value of <CODE>SHAPE</CODE> <I>s</I>. 
</UL>
<P>
Note that these operations only exist where the constraints on the
parameters are satisfied. Elsewhere the operations are undefined.
<P>
All the computations in this representation are obvious, but there
is one point to make concerning <I>offset_max</I>, which has the following
arguments and result. 
<P>
<PRE>
        <I>arg1</I>:            EXP OFFSET(<I>x</I>, <I>y</I>)
        <I>arg2</I>:            EXP OFFSET(<I>z</I>, <I>y</I>)
                   -&gt; EXP OFFSET(<I>unite_alignments</I>(<I>x</I>, <I>z</I>), <I>y</I>)
</PRE>
The <CODE>SHAPE</CODE>s could have been chosen to be:<P>
<PRE>
        <I>arg1</I>:            EXP OFFSET(<I>x</I>, <I>y</I>)
        <I>arg2</I>:            EXP OFFSET(<I>z</I>, <I>t</I>)
                   -&gt; EXP OFFSET(<I>unite_alignments</I>(<I>x</I>, <I>z</I>),
                                 <I>intersect_alignments</I>(<I>y</I>, <I>t</I>))
</PRE>
where <I>unite_alignments</I> is set union and 
<I>intersect_alignments</I> is set intersection. This would have expressed
the most general reality.  The representation of 
<I>unite_alignments</I>(<I>x</I>, <I>z</I>) is the maximum of the
representations of <I>x</I> and <I>z</I> in the simple model. Unfortunately
the representation of 
<I>intersect_alignments</I>(<I>y</I>, <I>t</I>) is not the minimum
of the representations of <I>y</I> and <I>t</I>. In other words the
simple model representation is not a homomorphism if 
<I>intersect_alignments</I> is used. Because the choice of representation
in the installer is an important consideration the actual definition
was chosen instead. It seems unlikely that this will affect practical
programs significantly. 
<P>
<A NAME=S397>
<H3>7.13.2. <A NAME=31>Comparison of pointers and offsets</H3>
Two <CODE>POINTER</CODE>s to the same <CODE>ALIGNMENT</CODE>, <I>a</I>,
are equal if and only if the result of <I>subtract_ptrs</I> applied
to them is equal to <I>offset_zero</I>(<I>a</I>). 
<P>
The comparison of <CODE>OFFSET</CODE>s is reduced to the definition
of <I>offset_max</I> and the equality of <CODE>OFFSET</CODE>s by the
note in <A HREF="spec8.html#M172">offset_test</A>. 
<P>
<A NAME=S398>
<H3>7.13.3. <A NAME=32>Circular types in languages</H3>
<A NAME=M33>It is assumed that circular types in programming languages
will always involve the <CODE>SHAPE</CODE>s <CODE>PROC</CODE>
or <CODE>POINTER</CODE>(<I>x</I>) on the circular path in their TDF
representation. Since the <CODE>ALIGNMENT</CODE> of <CODE>POINTER</CODE>
is {<I>pointer</I>} and does not involve the <CODE>ALIGNMENT</CODE>
of the thing pointed at, circular <CODE>SHAPE</CODE>s are not needed.
The circularity is always broken in <CODE>ALIGNMENT</CODE> (or 
<CODE>PROC</CODE>). 
<P>
<A NAME=S399>
<H3>7.13.4. <A NAME=34>Special alignments</H3>
<A NAME=M35><A NAME=M36><A NAME=M37>
<A NAME=M38>There are seven special <CODE>ALIGNMENT</CODE>s. One of
these is <I>code_alignment</I>, the <CODE>ALIGNMENT</CODE> of the
<CODE>POINTER</CODE> delivered by <I>make_local_lv</I>. 
<P>
The <CODE>ALIGNMENT</CODE> of a parameter of <CODE>SHAPE</CODE> <I>s</I>
is given by <I>parameter_alignment</I>(<I>s</I>) which will always
contain 
<I>alignment</I>(<I>s</I>). 
<P>
The other five special <CODE>ALIGNMENT</CODE>s are <I>alloca_alignment</I>,
<I>callees_alignment, callers_alignment, locals_alignment</I> and
<I>var_param_alignment</I>. Each of these contains the set union of
all the <CODE>ALIGNMENT</CODE>s which can be produced by <I>alignment</I>
from any <CODE>SHAPE</CODE>. But they need not be equal to that set
union, nor need there be any relation between them. 
<P>
In particular they are not equal (in the sense of <A HREF="#15">Equality
of <CODE>ALIGNMENT</CODE>s</A>). 
<P>
Each of these five refer to alignments of various components of a
frame. 
<P>
Notice that pointers and offsets such as 
<CODE>POINTER</CODE>(<I>callees_alignment</I>(true)) and 
<CODE>OFFSET</CODE>(<I>callees_alignment</I>(true), <I>x</I>) etc.
can have some special representation and that <I>add_to_ptr</I> and
<I>offset_add</I> can operate correctly on these representations.
However it is necessary that 
<PRE>
        <I>alignment</I>(POINTER(<I>A</I>))={<I>pointer</I>}
</PRE>
for any <CODE>ALIGNMENT</CODE> <I>A</I>.<P>
<A NAME=S400>
<H3>7.13.5. Atomic assignment</H3>
<A NAME=M39><A NAME=M40>At least one <CODE>VARIETY</CODE>
shall exist such that <I>assign</I> and <I>assign_with_mode</I> are
atomic operations. This <CODE>VARIETY</CODE> shall be specified as
part of the installer specification. It shall be capable of representing
the numbers 0 to 127. 
<P>
<I>Note that it is not necessary for this to be the same 
<CODE>VARIETY</CODE> on each machine. Normal practice will be to use
a 
<CODE>TOKEN</CODE> for this <CODE>VARIETY</CODE> and choose the definition
of the <CODE>TOKEN</CODE> on the target machine.</I>
<P>
<A NAME=S401>

<HR>
<H2>7.14. <A NAME=41>Order of evaluation</H2>
<A NAME=M42><A NAME=M43>The order of evaluation is specified in certain
constructions in terms of equivalent effect with a canonical order
of evaluation. These constructions are 
<I>conditional</I>, <I>identify</I>, <I>labelled</I>, <I>repeat</I>,
<I>sequence</I> and <I>variable</I>.  Let these be called the order-specifying
constructions. 
<P>
The constructions which change control also specify a canonical order.
These are <I>apply_proc</I>, <I>apply_general_proc</I>, <I>case</I>,
<I>goto</I>, <I>goto_local_lv</I>, <I>long_jump</I>, <I>return</I>,
u<I>ntidy_return, return_to_label, tail_call,</I> the <I>test</I>
constructions and all instructions containing the <I>error_jump</I>
and <I>trap</I> <CODE>ERROR_TREATMENT</CODE>s. 
<P>
The order of evaluation of the components of other constructions is
as follows. The components may be evaluated in any order and with
their components - down to the TDF leaf level - interleaved in any
order. The constituents of the order specifying constructions may
also be interleaved in any order, but the order of the operations
within an order specifying operation shall be equivalent in effect
to a canonical order. 
<P>
Note that the rule specifying when error_jumps or traps are to be
taken (<A HREF="spec8.html#M68"><I>error_jump</I></A>) relaxes the
strict rule that everything has to be &quot;as if&quot; completed
by the end of certain constructions. Without this rule pipelines would
have to stop at such points, in order to be sure of processing any
errors. Since this is not normally needed, it would be an expensive
requirement. Hence this rule. However a construction will be required
to force errors to be processed in the cases where this is important.
<P>
<A NAME=S402>

<HR>
<H2>7.15. <A NAME=44>Original pointers</H2>
<A NAME=M45><A NAME=M46>Certain constructions are specified as producing
original pointers. They allocate space to hold values and produce
pointers indicating that new space. All other pointer values are derived
pointers, which are produced from original pointers by a sequence
of <I>add_to_ptr</I> operations. Counting original pointers as being
derived from themselves, every pointer is derived from just one original
pointer. 
<P>
A null pointer is counted as an original pointer. 
<P>
<A NAME=M47>If procedures are called which come from outside the TDF
world (such as <I>calloc</I>) it is part of their interface with TDF
to state if they produce original pointers, and what is the lifetime
of the pointer. 
<P>
As a special case, original pointers can be produced by using <I>current_env</I>
and <I>env_offset</I> (see <A HREF="spec8.html#M101"><I>current_env</I></A>).
<P>
Note that: 
<PRE>
        <I>add_to_ptr(p, offset_add(q, r))</I>
</PRE>
is equivalent to: 
<PRE>
        <I>add_to_ptr(add_to_ptr(p, q), r)</I>
</PRE>
In the case that <I>p</I> is the result of <I>current_env</I> and
<I>q</I> is the result of <I>env_offset</I>: 
<PRE>
        <I>add_to_ptr(p, q)</I>
</PRE>
is defined to be an original pointer. For any such expression <I>q</I>
will be produced by <I>env_offset</I> applied to a <CODE>TAG</CODE>
introduced in the procedure in which <I>current_env</I> was used to
make <I>p</I>. 
<P>
<A NAME=S403>

<HR>
<H2>7.16. <A NAME=48>Overlapping</H2>
<A NAME=M49>In the case of <I>move_some</I>, or <I>assign</I>
or <I>assign_with_mode</I> in which <I>arg2</I> is a <I>contents</I>
or <I>contents_with_mode</I>, it is possible that the source and destination
of the transfer might overlap. 
<P>
In this case, if the operation is <I>move_some</I> or 
<I>assign_with_mode</I> and the <CODE>TRANSFER_MODE</CODE> contains
<I>overlap</I>, then the transfer shall be performed correctly, that
is, as if the data were copied from the source to an independent place
and then to the destination. 
<P>
In all cases, if the source and destination do not overlap the transfer
shall be performed correctly. 
<P>
Otherwise the effect is undefined. 
<P>
<A NAME=S404>

<HR>
<H2>7.17. <A NAME=50>Incomplete assignment</H2>
If the <I>arg2</I> component of an <I>assign</I> or <I>assign_with_mode</I>
operation is left by means of a jump, the question arises as to what
value is in the destination of the transfer. 
<P>
If the <CODE>TRANSFER_MODE</CODE> <I>complete</I> is used, the destination
shall be left unchanged if the <I>arg2</I> component is left by means
of a jump. If <I>complete</I> is not used and <I>arg2</I> is left
by a jump, the destination may be affected in any way. 
<P>
<A NAME=S405>

<HR>
<H2>7.18. <A NAME=51>Representing integers</H2>
<A NAME=M52><A NAME=M53>Integer <CODE>VARIETY</CODE>s shall be represented
by a range of integers which includes those specified by the given
bounds. This representation shall be twos-complement. 
<P>
If the lower bound of the <CODE>VARIETY</CODE> is non-negative, the
representing range shall be from 0 to 2<SUP><I>8n</I></SUP>-1 for
some 
<I>n</I>. 
<I>n</I> is called the number of bytes in the representation. The
number of bits in the representation is 8<I>n</I>. 
<P>
If the lower bound of the <CODE>VARIETY</CODE> is negative the representing
range shall be from -2<SUP><I>8n-1</I></SUP> to 2<SUP><I>8n-1</I></SUP>-1
for some <I>n</I>. 
<I>n</I> is called the number of bytes in the representation. The
number of bits in the representation is 8<I>n</I><P>
Installers may limit the size of <CODE>VARIETY</CODE> that they implement.
A statement of such limits shall be part of the specification of the
installer. In no case may such limits be less than 64 bits, signed
or unsigned. 
<P>
<I>It is intended that there should be no upper limit allowed at some
future date.</I>
<P>
Operations are performed in the representing <CODE>VARIETY</CODE>.
If the result of an operation does not lie within the bounds of the
stated 
<CODE>VARIETY</CODE>, but does lie in the representation, the value
produced in that representation shall be as if the <CODE>VARIETY</CODE>
had the lower and upper bounds of the representation. The implication
of this is usually that a number in a <CODE>VARIETY</CODE> is represented
by that same number in the representation. 
<P>
If the bounds of a <CODE>VARIETY</CODE>, <I>v</I>, include those of
a 
<CODE>VARIETY</CODE>, <I>w</I>, the representing <CODE>VARIETY</CODE>
for <I>v</I> shall include or be equal to the representing 
<CODE>VARIETY</CODE> for <I>w</I>. 
<P>
The representations of two <CODE>VARIETY</CODE>s of the form 
<I>var_limits</I>(0, 2<SUP><I>n</I></SUP>-1) and 
<I>var_limits</I>(-2<SUP><I>n-1</I></SUP>, 2<SUP><I>n-1</I></SUP>-1)
shall have the same number of bits and the mapping of their 
<CODE>ALIGNMENT</CODE>s into the target alignment shall be the same.
<P>
<A NAME=S406>

<HR>
<H2>7.19. <A NAME=54>Overflow and Integers</H2>
<A NAME=M55><A NAME=M56>It is necessary first to define what overflow
means for integer operations and second to specify what happens when
it occurs. The intention of TDF is to permit the simplest possible
implementation of common constructions on all common machines while
allowing precise effects to be achieved, if necessary at extra cost.
<P>
Integer varieties may be represented in the computer by a range of
integers which includes the bounds given for the variety. An arithmetic
operation may therefore yield a result which is within the stated
variety, or outside the stated variety but inside the range of representing
values, or outside that range. Most machines provide instructions
to detect the latter case; testing for the second case is possible
but a little more costly. 
<P>
In the first two cases the result is defined to be the value in the
representation. Overflow occurs only in the third case. 
<P>
If the <CODE>ERROR_TREATMENT</CODE> is <I>impossible</I> overflow
will not occur. If it should happen to do so the effect of the operation
is undefined. 
<P>
If the <CODE>ERROR_TREATMENT</CODE> is <I>error_jump</I> a 
<CODE>LABEL</CODE> is provided to jump to if overflow occurs. 
<P>
If the <CODE>ERROR_TREATMENT</CODE> is <I>trap(overflow),</I> a producer-defined
<CODE>TOKEN</CODE> <I>~Throw</I>: <CODE>NAT</CODE>
-&gt; <CODE>EXP</CODE> must be provided.  On an overflow, the installer
will arrange that <I>~Throw</I>(<I>error_val</I>(<I>overflow</I>))
is evaluated. 
<P>
The <I>wrap</I> <CODE>ERROR_TREATMENT</CODE> is provided so that a
useful defined result may be produced in certain cases where it is
usually easily available on most machines. This result is available
on the assumption that machines use binary arithmetic for integers.
This is certainly so at present, and there is no close prospect of
other bases being used. 
<P>
If a precise result is required further arithmetic and testing may
be needed which the installer may be able to optimise away if the
word lengths happen to suit the problem. In extreme cases it may be
necessary to use a larger variety. 
<P>
<A NAME=S407>

<HR>
<H2>7.20. <A NAME=57>Representing floating point</H2>
<A NAME=M58><A NAME=M59><CODE>FLOATING_VARIETY</CODE>s shall be implemented
by a representation which has at least the properties specified. 
<P>
Installers may limit the size of <CODE>FLOATING_VARIETY</CODE> which
they implement. A statement of such limits shall be part of the specification
of an installer. 
<P>
The limit may also permit or exclude infinities. 
<P>
Any installer shall implement at least one <CODE>FLOATING_VARIETY</CODE>
with the following properties (c.f. IEEE doubles): 
<UL>
<LI><I>mantissa_digs</I> shall not be less than 53. 
<LI><I>min_exponent</I> shall not be less than 1023.  
<LI><I>max_exponent</I> shall not be less than 1022.  
</UL>
Operations are performed and overflows detected in the representing
<CODE>FLOATING_VARIETY</CODE>. 
<P>
There shall be at least two <CODE>FLOATING_VARIETY</CODE>s, one occupying
the same number of bytes and having the same alignment as a 
<CODE>VARIETY</CODE> representation, and one occupying twice as many
bytes. 
<P>
<A NAME=S408>

<HR>
<H2>7.21. <A NAME=60>Floating point errors</H2>
<A NAME=M61><A NAME=M62>The only permitted 
<CODE>ERROR_TREATMENT</CODE>s for operations delivering 
<CODE>FLOATING_VARIETY</CODE>s are <I>impossible, error_jump</I> and
<I>trap</I> (overflow). 
<P>
The kinds of floating point error which can occur depend on the machine
architecture (especially whether it has IEEE floating point) and on
the definitions in the ABI being obeyed. 
<P>
Possible floating point errors depend on the state of the machine
and may include overflow, divide by zero, underflow, invalid operation
and inexact. The setting of this state is performed outside TDF (at
present). 
<P>
If an <I>error_jump</I> or <I>trap</I> is taken as the result of a
floating point error the operations to test what kind of error it
was are outside the TDF definition (at present). 
<P>
<A NAME=S409>

<HR>
<H2>7.22. Rounding and floating point</H2>
<A NAME=M63>Each machine has a rounding state which shall be one of
<I>to_nearest</I>, <I>toward_larger</I>, <I>toward_smaller</I>, 
<I>toward_zero</I>. For each operation delivering a 
<CODE>FLOATING_VARIETY</CODE>, except for <I>make_floating</I>, any
rounding necessary shall be performed according to the rounding state.
<P>
<A NAME=S410>

<HR>
<H2>7.23. <A NAME=64>Floating point accuracy</H2>
While it is understood that most implementations will use IEEE floating
arithmetic operations, there are machines which use other formats
and operations. It is intended that they should not be excluded from
having TDF implementations. 
<P>
For TDF to have reasonably consistent semantics across many platforms,
one must have some <I>minimum</I> requirements on the accuracies of
the results of the floating point operations defined in TDF. The provisional
requirements sketched below would certainly be satisfied by an IEEE
implementation. 
<P>
Let <I>@</I>  be some primitive dyadic arithmetic operator and <I>@'</I>
be its TDF floating-point implementation. Let <I>F</I> be some non-complex
<CODE>FLOATING_VARIETY</CODE> and <I>F'</I> be a representational
variety of <I>F</I>. 
<P>
<B>Condition 1</B>:<P>
If <I>a</I>, <I>b</I> and <I>a @ b</I> can all be represented exactly
in <I>F</I>, then they will also be represented exactly in <I>F'</I>.
Extending the '-notation in the obvious manner: 
<PRE>
        <I>(a @ b)' = (a' @' b')</I>
</PRE>
This equality will also hold using the TDF equality test, i.e.: 
<PRE>
        <I>(a @ b)' =' (a' @' b')</I>
</PRE>
<P>
<B>Condition 2</B>:<P>
The operator <I>@'</I> is monotonic in the sense apposite to the operator
<I>@</I>. For example, consider the operator +; if <I>x</I> is any
number and 
<I>a</I> and <I>b</I> are as above: 
<PRE>
        <I>(x &gt; b) =&gt; ((a' +' x') &gt;=  (a + b)')</I>
</PRE>
and: 
<PRE>
        <I>(x &lt; b) =&gt;  ((a' +' x') &lt;= (a + b)')</I>
</PRE>
and so on, reflecting the weakening of the ordering after the operation
from &gt; to &gt;=  and &lt; to &lt;=.  Once again, the inequalities
will hold for their TDF equivalents e.g., &gt;=' and &gt;'. 
<P>
Similar conditions can be expressed for the monadic operations. 
<P>
For the floating-point test operation, there are obvious analogues
to both conditions. The weakening of the ordering in the monotonicity
condition, however, may lead to surprising results, arising mainly
from the uncertainty of the result of equality between floating numbers
which cannot be represented exactly in <I>F</I>. 
<P>
Accuracy requirements for complex <CODE>FLOATING_VARIETY</CODE>s could
follow directly by considering the above conditions applied to real
and imaginary parts independently. The following proviso is added
for some complex operations however, to allow for possible intermediate
error conditions.  With <I>floating_div</I>, <I>floating_mult</I>
and 
<I>floating_power</I> for complex <CODE>FLOATING_VARIETY</CODE>s,
errors are guaranteed not to occur only if the square of the modulus
of each argument is representable and the square of the modulus of
the result is representable. Whenever these additional constraints
are not met, the operation will either complete with the accuracy
conditions above applying, or it will complete according to the 
<CODE>ERROR_TREATMENT</CODE> specified. 
<P>
<A NAME=S411>

<HR>
<H2>7.24. <A NAME=66><A NAME=66>Representing bitfields</H2>
<A NAME=M67><CODE>BITFIELD_VARIETY</CODE>s specify a number of bits
and shall be represented by exactly that number of bits in twos-complement
notation. Producers may expect them to be packed as closely as possible.
<P>
Installers may limit the number of bits permitted in 
<CODE>BITFIELD_VARIETY</CODE>s.  Such a limit shall be not less than
32 bits, signed or unsigned. 
<P>
<I>It is intended that there should be no upper limit allowed at some
future date.</I>
<P>
Some offsets of which the second parameter contains a <CODE>BITFIELD</CODE>
alignment are subject to a constraint defined below. This constraint
is referred to as <I>variety_enclosed.</I><P>
The intent of this constraint is to force <CODE>BITFIELD</CODE>s to
be implemented (in memory) as being included in some properly aligned
<CODE>VARIETY</CODE> value.  The constraint applies to: 
<PRE>
        <I>x</I>: <I>offset</I>(<I>p</I>, <I>b</I>)
</PRE>
and to: 
<PRE>
        <I>sh = bitfield</I>(<I>bfvar_bits(s, n)</I>)
</PRE>
where  <I>alignment(sh)</I> is included in <I>b</I>. The constraint
is as follows:<P>
There will exist a <CODE>VARIETY</CODE>, <I>v</I>, and 
<I>r</I>: <I>offset</I>(<I>p</I>, <I>q</I>) where <I>v</I> is in <I>q</I>.
<PRE>
        <I>offset_pad</I>(<I>b, r</I>) &lt;= <I>x</I>
</PRE>
and: 
<PRE>
        <I>offset_pad</I>(<I>b, r</I> + <I>sz</I>(<I>v</I>)) &gt;= <I>offset_pad</I>( <I>b</I>, <I>x</I> + <I>sz</I>(<I>sh</I>))
</PRE>
where the comparisons are in the sense of <I>offset_test</I>, + is
<I>offset_add</I> and <I>sz</I> is <I>shape_offset</I>. 
<P>
<A NAME=S412>

<HR>
<H2>7.25. <A NAME=68>Permitted limits</H2>
<A NAME=69>An installer may specify limits on the sizes of some of
the data <CODE>SHAPE</CODE>s which it implements. In each case there
is a minimum set of limits such that all installers shall implement
at least the specified <CODE>SHAPE</CODE>s. Part of the description
of an installer shall be the limits it imposes. Installers are encouraged
not to impose limits if possible, though it is not expected that this
will be feasible for floating point numbers. 
<P>
<A NAME=S413>

<HR>
<H2>7.26. <A NAME=70>Least Upper Bound</H2>
<A NAME=71>The LUB of two <CODE>SHAPE</CODE>s, <I>a</I> and <I>b</I>
is defined as follows: 
<UL>
<LI>If <I>a</I> and <I>b</I> are equal shapes, then <I>a</I>. 
<LI>If <I>a</I> is <CODE>BOTTOM</CODE> then <I>b</I>. 
<LI>If <I>b</I> is <CODE>BOTTOM</CODE> then <I>a</I>. 
<LI>Otherwise <CODE>TOP</CODE>. 
</UL>
<P>
<A NAME=S414>

<HR>
<H2>7.27. Read-only areas</H2>
Consider three scenarios in increasingly static order: 
<UL>
<LI>Dynamic loading. A new module is loaded, initialising procedures
are obeyed and the results of these are then marked as read-only.<P>
<LI>Normal loading. An <I>ld</I> program is obeyed which produces
various (possibly circular) structures which are put into an area
which will be read-only when the program is obeyed.<P>
<LI>Using ROM. Data structures are created (again possibly circular)
and burnt into ROM for use by a separate program.  
</UL>
In each case program is obeyed to create a structure, which is then
frozen. The special case when the data is, say, just a string is not
sufficiently general. 
<P>
This TDF specification takes the attitude that the use of read-only
areas is a property of how TDF is used - a part of the installation
process - and there should not be TDF constructions to say that some
values in a <CODE>CAPSULE</CODE> are read-only. Such constructions
could not be sufficiently general. 
<P>
<A NAME=S415>

<HR>
<H2>7.28. <A NAME=72>Tag and Token signatures</H2>
In a TDF program there will usually be references to <CODE>TAG</CODE>s
which are not defined in TDF; their definitions are intended to be
supplied by a host system in system specific libraries. 
<P>
These <CODE>TAG</CODE>s will be declared (but not defined) in a TDF
<CODE>CAPSULE</CODE> and will be specified by external linkages of
the 
<CODE>CAPSULE</CODE> with <CODE>EXTERNAL</CODE>s containg either 
<CODE>TDFIDENT</CODE>s or <CODE>UNIQUE</CODE>s. In previous versions
of TDF, the external names required by system linking could only be
derived from those <CODE>EXTERNAL</CODE>s. 
<P>
Version 4.0 gives an alternative method of constructing extra-TDF
names. Each global <CODE>TAG</CODE> declaration can now contain a
<CODE>STRING</CODE> signature field which may be used to derive the
external name required by the system. 
<P>
This addition is principally motivated by the various &quot;name mangling&quot;
schemes of C++. The <CODE>STRING</CODE> signature can be constructed
by concatenations and token expansions. Suitable usages of 
<CODE>TOKEN</CODE>s can ensure that the particular form of name-mangling
can be deferred to installation time and hence allow, at least conceptually,
linking with different C++ libraries. 
<P>
As well as <CODE>TAG</CODE> declarations, <CODE>TAG</CODE> definitions
are allowed to have signatures.  The restriction that the signature
(if present) of a <CODE>TAG</CODE> definition being identical to its
corresponding definition could allow type checking across seperately
compiled <CODE>CAPSULE</CODE>s. 
<P>
Similar considerations apply to <CODE>TOKEN</CODE>s; although token
names are totally internal to TDF, it would allow one to check that
a token declared in one <CODE>CAPSULE</CODE> has the same &quot;type&quot;
as its definition in another. 
<P>
<P>
<A NAME=S416>

<HR>
<H2>7.29. <A NAME=73>Dynamic initialisation</H2>
The dynamic initialisation of global variables is required for languages
like C++. Previous to version 4.0, the only initialisations permissable
were load-time ones; in particular no procedure calls were allowed
in forming the initialising value. Version 4.0 introduces the constructor
<I>initial_value</I> to remedy this situation. 
<P>
Several different implementation strategies could be considered for
this. Basically, one must ensure that all the initial_value expressions
are transformed into assignments to globals in some procedure. One
might expect that there would be one such procedure invented for each
<CODE>CAPSULE</CODE> and that somehow this procedure is called before
the main program. 
<P>
This raises problems on how we can name this procedure so that it
can be identified as being a special initialising procedure. Some
UNIX linkers reserve a name like <I>__init</I> specially so that all
instances of it from different modules can be called before the main
procedure. Other cases may require a pre-pass on the <I>.o</I> files
prior to system linking. 
<P>
<HR>
<P><I>Part of the <A HREF="../index.html">TenDRA Web</A>.<BR>Crown
Copyright &copy; 1998.</I></P>
</BODY>
</HTML>