perm filename SAIL.PUB[DOC,AIL] blob sn#261592
filedate 1977-02-08 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00004 PAGES
C REC PAGE DESCRIPTION
C00002 00002 .require "pubmac[doc,ail]" source!file
C00009 00003 .ss|Declarations and Scope|
C00014 00004 .sec|Documentation Errors|
.require "pubmac[doc,ail]" source!file;
This section describes changes and additions to Sail since the August 1976
Double precision floating-point arithmetic is available.
Use the <type_qualifier> LONG in declarations. For example,
LONG REAL X, Y, Z;
LONG REAL ARRAY XA[0:N];
Currently LONG has meaning only when it appears as part of LONG REAL.
(At some future time LONG INTEGERs may also exist.)
The runtime routines LREALIN and LREALSCAN operate the same as REALIN and
REALSCAN, except for returning LONG REAL values. The routine CVEL takes a
LONG REAL value and returns a string representation like that of CVE,
except that "@@" is used to signify LONG when delimiting the exponent.
Any of "@", "@@", "E", or "D" are acceptable exponent delimiters to
LREALIN and LREALSCAN.
Variables which are declared LONG REAL are represented in KI10 hardware
format double precision, take two consecutive words of storage, and
provide 62 bits of precision (approximately 18 decimal digits) to
represent the fraction part of a floating-point number. Regular REAL
variables occupy a single word and have 27 bits (8 decimal digits) of
precision. The exponent range of both REAL and LONG REAL variables
is from -128 to 127, where 2↑127 is approximately 10↑38.
LONG REAL is a dominant type in arithmetic operations +-*/%↑ MAX MIN and
arithmetic relationals <>=≠≤≥. If one operand is LONG REAL then both
operands will be converted to LONG REAL (if necessary) before performing
the operation. An exponentiation involving a LONG REAL raised to a positive
integer constant is an exception to this rule. The type coercion path is
linear: STRING ↔ INTEGER ↔ REAL ↔ LONG REAL. Conversion from REAL to
LONG REAL is performed by assigning the (only) word of the REAL to the
most significant word of the LONG REAL and setting the second (least
significant) word of the LONG REAL to zero. Conversion from LONG REAL to
REAL is by UUO which rounds.
Arithmetic and assignment operations are compiled into DFAD, DFSB, DFMP,
DFDV, DMOVE, DMOVEM instructions. The Sail operations ASH, LSH, ROT,
LAND, LOR, EQV, XOR are performed on both words (ASHC, LSHC, ROTC, 2 ANDs,
2 IORs, etc.). LOCATION of a LONG REAL variable gives an address E such
that DMOVE AC,E fetches the appropriate words of memory. When passed by
value as an actual parameter to a procedure, both words are placed on the
P stack: PUSH P,X ↔ PUSH P,X+1. LONG REAL fields in record classes are
handled much like STRING fields, except that the address in the record
field points to the first word of a 2-word block (rather than to the
second word as in the case with STRINGs).
LONG REAL ARRAYs are stored as contiguous blocks of 2-word values.
ARRTRAN done on two LONG REAL arrays is a transparent operation, but for
ARRYIN, ARRYOUT, or ARRBLT the actual word count is specified; think about
whether you should multiply by 2! At runtime the array descriptor for a
LONG ARRAY has bit 12 (40,,0 bit) set in MULT(n), the multiplier for the
last dimension (which would otherwise be =1). Similarly, a LONG ARRAY is
allocated by setting bit 12 (40,,0) bit in the parameter which specifies
the number of dimensions to ARMAK.
Runtime support for LEAP items with LONG REAL datums does not yet
exist, although the compiler does generate suitable code.
Runtime support for double precision exponentiation is also limited
for the moment. Any exponentiation X↑K where K is a positive
integer constant is compiled inline using the binary ("Russian peasant")
method, regardless of the type of X. Other exponentiations involving
LONG REALs are merely translated into procedure calls on
LONG REAL PROCEDURE DPOW (INTEGER EXPONENT; LONG REAL BASE);
LONG REAL PROCEDURE DLOGS (LONG REAL EXPONENT, BASE);
depending on the type of the exponent. The Sail runtime system
does not yet contain such procedures, so you will have to roll your own.
.ss|Declarations and Scope|
Sail declarations must occur
before use. For example, in the following program the argument to PRINT
is interpreted as the K on line 2, even though by the ALGOL60 notion of
scope it should be interpreted as the K on line 5.
INTEGER K; COMMENT this is line 2;
PROCEDURE BAR; BEGIN PRINT(K) END;
INTEGER K; COMMENT this is line 5;
The compiler now recognizes "**" for "↑", ":=" for "←",
"<=" for "≤", and ">=" for "≥".
REQUIRE OVERLAP_OK; will suppress the message which occurs at initialization
when two programs have declared items.
REQUIRE VERIFY_DATUMS; causes the compiler to generate three additional instructions
for each DATUM reference, to make sure (dynamically, at run time) that the type
of the item in the DATUM construct is the same as the compiler expected.
This is similar to (the unimplimented effect of) declaring all itemvars CHECKED.
It is planned that VERIFY_DATUMS will soon be a bit in the /A switch
and that the corresponding REQUIRE will disappear.
REQUIRE PROCESSES; insures that MAINPR, the main process, is initialized.
You need not specify this REQUIRE if you use APPLY or SPROUT, but if the
only use of processes is via INTSET then you must REQUIRE PROCESSES;.
In an explicitly numbered CASE statement the word ELSE can appear where
a bracketed case number is normally used. The statement following the ELSE is a
catch-all for any case number not mentioned, including anything which
would otherwise generate a CASE index error. For example,
CASE K OF BEGIN  J←3; ELSE J←4;  J←5 END
is another way of accomplishing
IF K=3 THEN J←3
ELSE IF K=5 THEN J←5
A CASE statement containing an ELSE case does not generate a call to the CSERR
runtime routine, and in addition the jump table usually contains only
max_case - min_case +1 words (rather than max_case +1).
To define two record classes, both of which contain RECORD_POINTER fields
refering to the other class, say
FORWARD RECORD_CLASS BAR (RECORD_POINTER (ANY_CLASS) Q2);
RECORD_CLASS FOO (RECORD_POINTER (BAR) Q1);
RECORD_CLASS BAR (RECORD_POINTER (FOO) Q2);
In general, declare one class to be FORWARD and list its RECORD_POINTER
fields as pointers to ANY_CLASS. This breaks the circularity and allows
maximum compile-time type checking.
.require "lies[doc,ail]" source_file;