perm filename SAIL.DOC[DOC,AIL]5 blob sn#126743 filedate 1974-10-24 generic text, type T, neo UTF8


STANFORD ARTIFICIAL INTELLIGENCE LABORATORY              OCTOBER 1974






                          SAIL USER MANUAL

                               UPDATE



                            James R. Low
                           John F. Reiser
                           Hanan J. Samet
                          Robert F. Sproull
                         Daniel C. Swinehart
                          Russell H. Taylor
                           Kurt A. VanLehn










                              ABSTRACT

This document describes recent changes to the SAIL language since the
"new" manual (AIM-204) was  published in July 1973.  It  reflects the
various  new  features implemented  as  of 26  March,  1974  for SAIL
version  7 and  corrects  a number  of  minor errors  in  the earlier
manual.
SAIL Addendum  1                                    TABLE OF CONTENTS


  
                  T A B L E   O F   C O N T E N T S
                  _ _ _ _ _   _ _   _ _ _ _ _ _ _ _



SECTION                                                          PAGE



1    INTRODUCTION                                                   1



2    NUMERICAL ROUTINES                                             2

     1    OVERFLOW                                                  3
     2    ENTRY POINTS                                              4


3    NEW PROCESS FEATURES                                           5

     1    SPROUT APPLY                                              5
     2    SPROUT_DEFAULTS                                           5
     3    SUSPEND                                                   7
     4    FAIL AND SUCCEED                                          7


4    ERROR HANDLING                                                 8

     1    ERROR MODES                                               8
     2    USER ERROR PROCEDURES                                     8


5    INEXHAUSTIBLE STRING SPACE                                    11



6    RECORD STRUCTURES                                             13

     1    INTRODUCTORY REMARKS                                     13
     2    RECORD CLASS DECLARATIONS                                14
     3    RECORD POINTER DECLARATIONS                              14
     4    ALLOCATION                                               15
     5    SUBFIELDS                                                16
     6    INTERNAL REPRESENTATIONS AND IMPLEMENTATION NOTES        17
SAIL Addendum  1                                    TABLE OF CONTENTS


7    MISCELLANEOUS NEW FEATURES                                    19

     1    NEW MTAPE OPTIONS                                        19
     2    INITIALIZATION PHASES                                    19
     3    CHNCDB                                                   20
     4    ARRCLR                                                   20
     5    SETPL                                                    20
     6    EVALREDEFINE                                             21
     7    CVPS                                                     21
     8    EXPRESSIONS IN REQUIRES                                  21
     9    RELEASE                                                  21
     10   TTYUP                                                    21
     11   BREAKSET MODES "K" AND "F"                               22
     12   INOUT                                                    22
     13   GETSTS & SETSTS                                          22
     14   CHANGES TO "OPEN" ERROR HANDLING                         23
     15   ASH                                                      23
     16   ARG_LIST                                                 23
SAIL Addendum  1                                         INTRODUCTION


                             SECTION  1
                             _______  _

                            INTRODUCTION
                            ____________





The following short manual  describes the changes that  have happened
to  SAIL  since  the  publishing  of  the  Manual  in  July  1973. It
accurately reflects the state of SAIL, version 7, which was put up on
December 4, 1973.  The reader should be warned that many of these new
features were designed for veteran SAIL hackers.

The reader may also want  to refer to the following  documents, which
are usually kept updated.

MACLIE.WRU[DOC,AIL] A  summary  of commonly  made  errors  when using
                    macros and what to do about them.

TUTOR.DOC[DOC,AIL]  In introduction to LEAP.

LEAP.WRU[DOC,AIL]   A detailed description of the runtime environment
                    of LEAP for the  hardy few who want  to interface
                    to LEAP in assembly language.

SAIL.DOC[AIM,DOC]   The  July  '73  manual  (AIM-204)  in  LPT  form.
                    Warning: this  version is the  Stanford character
                    set.  It is also almost 300 pages long.   You can
                    get a  120 page  version, set  in two  columns of
                    nice type from the National Technical Information
                    Service, Springfield, Virginia 22151.

LIES[DOC,AIL]       This  file  contains  the  know  mistakes  in the
                    Manual.  Soon  it  will  also  contain  the known
                    mistakes in this document.













                                  1
SAIL Addendum  1                                   NUMERICAL ROUTINES


                             SECTION  2
                             _______  _

                         NUMERICAL ROUTINES
                         _________ ________





A collection of numerical routines has been added to SAIL.  These are
pre-declared in the compiler,  and are loaded from the  standard SAIL
library.   The  functions  are  quite  standard;  following  are  the
equivalent definitions:

1.  The standard trigonometric functions.  ASIN, ACOS, ATAN and ATAN2
    return results in radians.   The ATAN2 call takes  arc-tangent of
    the  quotient  of  its  arguments;  in  this  way,  it  correctly
    preserves sign information.

        REAL PROCEDURE SIN (REAL RADIANS);
        REAL PROCEDURE COS (REAL RADIANS);
        REAL PROCEDURE SIND (REAL DEGREES);
        REAL PROCEDURE COSD (REAL DEGREES);

        REAL PROCEDURE ASIN (REAL ARGUMENT);
        REAL PROCEDURE ACOS (REAL ARGUMENT);
        REAL PROCEDURE ATAN (REAL ARGUMENT);
        REAL PROCEDURE ATAN2 (REAL NUMERATOR,DENOMINATOR);


2.  The hyperbolic trigonometric functions.

        REAL PROCEDURE SINH (REAL ARGUMENT);
        REAL PROCEDURE COSH (REAL ARGUMENT);
        REAL PROCEDURE TANH (REAL ARGUMENT);

3.  The square-root function:

        REAL PROCEDURE SQRT (REAL ARGUMENT);

4.  A pseudo-random number  generator.  The argument specifies  a new
    value for the seed (If the  argument is 0, the old seed  value is
    used.  Thus to get differing random numbers, this argument should
    be zero.)  Results are normalized to lie in the range [0,1].

        REAL PROCEDURE RAN (INTEGER SEED);




                                  2
SAIL Addendum  1                                   NUMERICAL ROUTINES


5.  Logarithm and exponentiation functions.  These functions  are the
    same ones used by the SAIL exponentiation operator.  The  base is
    e  (2.71828182845904).  The  logarithm  to the  base 10  of  e is
    .4342944819.

        REAL PROCEDURE LOG (REAL ARGUMENT);
        REAL PROCEDURE EXP (REAL ARGUMENT);

These functions may occasionally be asked to compute numbers that lie
outside the range of legal floating-point numbers on the  PDP-10.  In
these cases,  the routines  issue sprightly  error messages  that are
continuable.



2.1 - OVERFLOW
      ________


In order  to better  perform their tasks,  these routines  enable the
system interrupt facility  for floating-point overflow  and underflow
errors.  If  an underflow is  detected, the results  are set to  0 (a
feat not  done by  the PDP-10  hardware, alas).   Be aware  that such
underflow fixups will be done to every underflow that occurs  in your
program.

If you would like to be informed of any numerical exceptions, you can
call the runtime:

        TRIGINI ( LOCATION(simple-procedure-name) );

Every floating-point exception that is not expected by  the interrupt
handler (the numerical routines use a special convention  to indicate
that  arithmetic exception  was  expected) will  cause  the specified
simple procedure to  be called.  This  procedure may look  around the
world as  described in  the Manual  for 'export'  interrupt handlers,
page 79.   If no  TRIGINI call  is done,  the interrupt  routine will
simply dismiss unexpected floating-point interrupts.












                                  3
SAIL Addendum  1                                   NUMERICAL ROUTINES


2.2 - ENTRY POINTS
      _____ ______


In order to avoid confusion (by the loader) with older trig packages,
the  entry points  of the  SAIL arithmetic  routines all  have  a "$"
appended  to the  end.   Thus, SIN  has  the entry  point  SIN$, etc.
WARNING:  If a  program  plans to  use the  SAIL  intrinsic numerical
routines, it should NOT include external declarations to  them, since
this will probably cause the FORTRAN library routines to be loaded.








































                                  4
SAIL Addendum  1                                 NEW PROCESS FEATURES


                             SECTION  3
                             _______  _

                        NEW PROCESS FEATURES
                        ___ _______ ________







3.1 - SPROUT APPLY
      ______ _____


The <procedure call> in a SPROUT statement may be an APPLY construct.
In  this case SPROUT will  do the "right" thing  about setting up the
static link  for  the  APPLY. That is,  "up-level" references  by the
process will  be made to  the same variable  instances that  would be
used if the APPLY did not  occur in a SPROUT statement. (See  page 77
of the manual.)

However, there  is a glitch.  The sprout mechanism  is not  yet smart
enough to find out the block of the declaration of the procedure used
to define the procedure item. It would be nice if it did,  since then
it could warn the user when that block was exited and yet the process
was still alive,  and thus potentially  able to refer  to deallocated
arrays and etc. What the sprout does instead is assume  the procedure
was declared in the outer  block. This may be fixed   eventually, but
in the meantime  some extra  care should be taken  when  using  apply
in   sprouts  to    avoid    exiting  a    block    with  dependents.
Similarly,  be warned   that the  "DEPENDENTS  (<blockid>)" construct
may  not give  the  "right"  result  for  sprout applies. Page  68 of
the Manual contains the description of this protection  mechanism for
non-APPLY Sprouts.



3.2 - SPROUT_DEFAULTS
      _______________


SAIL  now provides  a mechanism  by which  the user  may specify  the
"default" options to be used when individual procedures are sprouted.








                                  5
SAIL Addendum  1                                 NEW PROCESS FEATURES



Syntax:
        PROCEDURE <procid> ...
         BEGIN
         <some declarations>;
         SPROUT_DEFAULTS <integer constant>;
         <perhaps some more declarations>;
         :
         :
         <statements>
         :
         END;


In other words, SPROUT_DEFAULTS is a declaration.

Semantics:

If  one of the "allocation" fields of  the options word passed to the
SPROUT routine -- i.e. QUANTUM,STRINGSTACK,PSTACK, or  PRIORITY -- is
zero,   then  SPROUT  will look  at  the corresponding  field of  the
specified <integer constant> for the procedure being sprouted. If the
field is  non-zero,   then  that value  will be  used; otherwise  the
current "system" default will be used.

NOTE:  SPROUT_DEFAULTS  only  applies  to  "allocations",  i.e.   the
process status control bits (e.g. SUSPME) are not affected.
Example:

        RECURSIVE PROCEDURE FOO;
         BEGIN
         SPROUT_DEFAULTS STRINGSTACK(10);
         INTEGER XXX;
         :
         :
         END;
        :
        SPROUT(P1,FOO,STRINGSTACK(3));
        SPROUT(P2,FOO);
        COMMENT P1 will have a string stack of 3*32 words.
         P2 will have a string stack of 10*32 words;








                                  6
SAIL Addendum  1                                 NEW PROCESS FEATURES


3.3 - SUSPEND
      _______


SUSPEND now behaves like RESUME in that it returns an item.

        itm ← SUSPEND(<process item>)

Frequently, one is suspending some other process than the one that is
executing the SUSPEND statement.  In this case, the item  returned is
ANY.   However, in cases like:

        X ← SUSPEND(MYPROC);

where the process suspends itself, it might happen that  this process
is  made running  by a  RESUME from  another process.  If so,  then X
receives the <return_item>  that was an argument to the RESUME.



3.4 - FAIL AND SUCCEED
      ____ ___ _______


FAIL and SUCCEED now behave like RESUME and SUSPEND in that they also
return  an  item.   The  item returned  is  ANY  unless  the Matching
Procedure  containing  the FAIL  or  SUCCEED was  (1)  sprouted  as a
process, and (2) made running  by a RESUME construct.  In  the latter
case, the item returned is the <return_item> that was an  argument to
the RESUME.  [Note that the  only case in which a  Matching Procedure
can be reactivated at a FAIL is by being RESUMEd.]




















                                  7
SAIL Addendum  1                                       ERROR HANDLING


                             SECTION  4
                             _______  _

                           ERROR HANDLING
                           _____ ________







4.1 - ERROR MODES
      _____ _____


SAIL's error  handler has at  long last been  modified to do  what is
claimed it will do  in Section 20 of the manual (pgs 95 - 97), and in
the description of USERERR (pg 42).  In brief, it allows one to  have
error  messages automatically  sent  to  a "log"  file  while one  is
compiling, and to use USERERR as a trace statement.

The description given in the manual differs from reality in two ways:
"Keep" mode has not  been implemented (the error handler   will flush
all type-ahead except  a <lf>);   all  of the  other  modes ("Quiet",
"Logging",  and "Numbers")  are  implemented ONLY   IN  THE COMPILER.
However, one  can get the effect of error modes at runtime by using a
brand new feature called user error procedures.



4.2 - USER ERROR PROCEDURES
      ____ _____ __________


A  user error  procedure is a  user procedure  that is run  before or
instead of  the  SAIL error  handler  everytime  an error  occurs  at
runtime.  This  includes all array errors, IO  errors, Leapish errors
and all USERERRs.  It does not include system errors, such as Ill Mem
Ref or Ill UUO.

The  procedure one uses  for a  user error procedure  must be  of the
following type:

    SIMPLE INTEGER PROCEDURE proc (INTEGER loc; STRING msg, rsp);


Only the names  proc, loc,  msg, and rsp  may vary  from the  example
above, except  that one  may declare  the procedure  INTERNAL if  one
wishes to use it across files.



                                  8
SAIL Addendum  1                                       ERROR HANDLING


Whenever  the external integer _ERRP_  is loaded with LOCATION(proc),
the error handler will  call proc before it  does anything else.   It
will set loc to  the core location of the call  to the error handler.
Msg  will be  the message  that it  would have  printed.  Rsp will be
non-NULL only  if the  error was  from a  USERERR which  had response
string argument.  Proc can  do anything that  a simple  procedure can
do.  When it  exits, it should  return  an  integer which   tells the
error handler  if  it should do anything more.  If the integer  is 0,
the  error  handler will  (1)   print the   message,  (2)   print the
location,  and  (3)  query  the  tty  and  dispatch  on  the response
character (i.e ask for a <cr>, <lf>, etc.).  If the right half of the
integer is  non-zero, it  is taken as  the ascii  for a  character to
dispatch upon.  The left half may have two bits to  control printing.
If bit 17  in the integer is  on, message printing is  inhibited.  If
bit 16 is on, then  the location printing is inhibited.  For example,
"X"+(1 LSH 18) will cause the location to be printed and  the program
exited.  "C"+(3 LSH  18)  will cause  the error  handler  to continue
without printing anything.

Note that simple  procedures can not do  a non-local GOTO.   However,
the  effect of  a non-local  GOTO  can be  achieved in  a  user error
procedure by loading the external integer _ERRJ_ with the LOCATION of
a label. The label  should be a on  a call to a  non-simple procedure
which does the desired GOTO.  The error handler clears  _ERRJ_ before
calling the procedure  in  _ERRP_.  If  _ERRJ_  is non-zero  when the
user procedure returns, and continuing was specified, then  the error
handler's exit  consists of a simple transfer to  that location.

WARNING! Handling errors from strange places like the  string garbage
collector and  the core  management routines will  get you  into deep
trouble.

A  user error  procedure  has been  written which  gives  a traceback
through the run-time stack.  The traceback routine lists the  name of
each non-simple calling procedure and the location (in octal)  of the
PUSHJ it did,  starting with the  most recently called  procedure and
ending with the main procedure of the current process.

The  procedure  is currently  available  via  REQUIRE "LIBSA7[1,JFR]"
LIBRARY or via REQUIRE "WALK.REL[1,JFR]" LOAD_MODULE.   The procedure
will move to the system LIBSA7 as soon as possible.

To  use  the procedure  say  EXTERNAL PROCEDURE  _TRON_;  ... _TRON_;
COMMENT _TRON_ is for "trace on";.

Subsequent run-time errors will give the traceback, then  request the
usual  response.  To  get  the traceback  at any  time,  say EXTERNAL


                                  9
SAIL Addendum  1                                       ERROR HANDLING


PROCEDURE WALK; ... WALK;.  This can be useful in  checking recursion
level or in other debugging.

To  intercept the  trackback, say  EXTERNAL  PROCEDURE UMWALK(INTEGER
LOC);       ...        UMWALK(LOCATION(user_procedure));.        Then
user_procedure("NAME",LOC) is called once for every procedure  in the
traceback  chain,  instead  of  printing  "CALLED  FROM  "&NAME&"  AT
"&CVOS(LOC)&CRLF on the terminal.

To  discontinue  tracing  on errors:   EXTERNAL  INTEGER  _ERRP_; ...
_ERRP_←0;.






































                                 10
SAIL Addendum  1                           INEXHAUSTIBLE STRING SPACE


                             SECTION  5
                             _______  _

                     INEXHAUSTIBLE STRING SPACE
                     _____________ ______ _____





The string garbage collector has been modified to expand string space
(using discontiguous blocks) whenever necessary to satisfy the demand
for places to put strings. To take advantage  of  this  feature,  one
need not change his programs.

Here are some points which might be of interest, however:

1)  Although  we  are  going  to  provide  user control over all size
    parameters  eventually,  currently  only   the   initial   string
    space size  is   settable  by  the   user, either via  REQUIRE or
    the ALLOC  sequence, as  before.  The size  of each  string space
    increment will be  the same as the original size, which  need not
    be monstrous  any more  unless you   know that  all runs  of your
    program  will  need   a monstrous   string  space   anyhow.   The
    threshold  (see below)  for  expanding will  be set  at  1/8  the
    string  space  size  (increment size).

2)  One can, in his program, modify these values independently, if he
    is  willing  to use  the  USERCON function,  and  to  follow this
    format:

     USER TABLE ENTRY NAME              VALUE
        STINCR          lh: number of chars. in increment
                        rh: number of words in increment + 4

        STREQD          lh: number of chars. in threshold
                        rh: number of words in threshold.


3)  The threshold.   After garbage  collection, let  us say  that M-1
    discontiguous string spaces  are   full,  and  the  M'th   has  n
    free  characters in it (available for new strings).  The  garbage
    collector  was  called because   some routine wanted to  create a
    string R characters long, and there were not that many  available
    (free).      After    garbage  collection,   the   new  algorithm
    requires  that N  be greater  than R+LH(STREQD).   If it  is not,
    expansion  takes  place  (to  M+1  spaces),  to    satisfy   this
    requirement.    In other words, if STREQD is 1/8 the size  of the
    current space, that space  will not be  allowed  to  become  more


                                 11
SAIL Addendum  1                           INEXHAUSTIBLE STRING SPACE


    than   about   7/8   full.   This  helps  avoid  frequent, nearly
    useless calls on the garbage collector when  space is about gone.
    All  but the  current  space are  allowed  to become  as  full as
    possible, however.

4)  New  statistics  are  maintained  by  the    garbage   collector.
    Soon there   will  be  a built-in  routine you  can use  to print
    them.  For now, you may look at them using USERCON, although this
    document   does  not   say  what   they   are.      In   order to
    activate timing  of the  garbage collector  (slows it  down), set
    SGCTIME in the  user  table to -1.

5)  Future plans.  The  new  structure  not only allows  expansion of
    string  space,  it  also  will   allow   for    partial   garbage
    collections   (no   visible  benefits   except   increased speed,
    since  a partial  collection  will be  almost as  effective  as a
    complete one,  and  much   faster),  and  the  ability   to  move
    string  space  blocks, in order to compact memory.  Push  on your
    local representative  to  get  these  things done.






























                                 12
SAIL Addendum  1                                    RECORD STRUCTURES


                             SECTION  6
                             _______  _

                          RECORD STRUCTURES
                          ______ __________







6.1 - INTRODUCTORY REMARKS
      ____________ _______


Record structures are a fairly recent addition to SAIL.  Essentially,
they provide a means by  which a number of closely  related variables
may be allocated and manipulated  as a unit, without the  overhead or
limitations associated  with using parallel  arrays.  In  the current
implementation, each record is an instance of a  user-defined "record
class", which serves as  a template describing the  various subfields
of the record.  Internally, records are small blocks of storage which
contain space  for the  various subfields  and a  pointer to  a class
descriptor.  Subfields are allocated one per word and are accessed by
constant indexing off  the record pointer.  Deallocation  is perormed
by a garbage collector.

Records were originally  added to SAIL to  fullfill a number  of very
specific needs at Stanford, and were subsequently generalized  to the
form  seen  here.   The  structures  described  in  this  section are
implemented and, so far as is known, work correctly.  (They have been
used successfully over the past 3 months by several  different people
to produce a number of sizable programs).  However, a number  of fine
points  have  yet  to  be  cleaned  up  before  SAIL  records  can be
considered to be "finished".   Also, several aspects of  the existing
implementation  are  still  quite  ugly,  and  may  be  substantially
modified in the future, although the language constructs seen  by the
user are  apt to stay  about the same.   The material  presented here
should therefore be considered to be PRELIMINARY  DOCUMENTATION ONLY.
It is being supplied only  in response to numerous requests  for such
documentation, and with  the understanding that the  system described
is still  in an adolescent  -- though usable  -- stage.   Readers are
strongly  urged  to  look  at  the  file  RECAUX.SAI[CSP,SYS],  which
contains a number of useful examples and auxilliary functions.







                                 13
SAIL Addendum  1                                    RECORD STRUCTURES


6.2 - RECORD CLASS DECLARATIONS
      ______ _____ ____________


        RECORD_CLASS <classid> (<subfield declarations>)

For instance,

        RECORD_CLASS VECTOR (REAL X,Y,Z);
        RECORD_CLASS CELL (RECORD_POINTER(ANY_CLASS) CAR,CDR);
        RECORD_CLASS TABLEAU (REAL ARRAY A,B,C;INTEGER N,M);
        RECORD_CLASS FOO(LIST L;ITEMVAR A);


Generally,  the  <subfield  declarations> have  the  same  form  as a
procedure's formal  paramter list,  except that  the words  VALUE and
REFERENCE should  not be  used.  Also, STRING  subfields are  not yet
implemented.   Each  record  class  declaration  is  compiled  into a
"record  descriptor"  which  is  used  by  the  runtime   system  for
allocation, deallocation, garbage collection, etc.



6.3 - RECORD POINTER DECLARATIONS
      ______ _______ ____________


        RECORD_POINTER(<classid list>) <id list>
        RECORD_POINTER(ANY_CLASS) <id list>

For instance,

        RECORD_POINTER(VECTOR) V1,V2;
        RECORD_POINTER(VECTOR,TABLEAU) T1,T2;
        RECORD_POINTER(ANY_CLASS) R;


At  runtime, these  variables  either contain  the  value NULL_RECORD
(internally,  zero) or  else  contains a  pointer to  a  record.  The
<classid list> is  used to make  a compile-time check  on assignments
and  subfield  references.  The  pseudo-class  ANY_CLASS  matches all
classes,  and  effectively  disables  this  compile-time  check.  For
instance:

        RECORD_POINTER(FOO,BAR) FB1,FB2;
        RECORD_POINTER(FOO) FB3;
        RECORD_POINTER(CELL) C;
        RECORD_POINTER(ANY_CLASS) RP;
        :
        COMMENT the following are all ok syntactically;

                                 14
SAIL Addendum  1                                    RECORD STRUCTURES


        C←NEW_RECORD(CELL);
        RP←C;
        FB2←NEW_RECORD(FOO);
        FB1←FB3;
        FB3←RP; COMMENT Note that this is most likely a runtime bug
                        Since RP will contain a cell record.  SAIL
                        won't catch it, however;
        CELL:CAR[RP]←FB1;

        COMMENT The compiler will complain about these: ;
        FB1←C;
        FB3←NEW_RECORD(CELL);
        RP←CELL:CAR[FB3];

NO  runtime  class information  is  kept with  the  variable,  and no
runtime  class  checks  are made  on  record  assignment  or subfield
access.   Record  pointer  variables  are  allocated  quantities, and
should not appear inside SIMPLE procedures.   They resemble  lists in
that they are not given  any special value upon block entry  and they
are set to  a null value (NULL_RECORD)  when the block in  which they
are declared  is exited.  (This  is so that  any records  referred to
only in that block can be reclaimed by the garbage collector.)



6.4 - ALLOCATION
      __________


Records are allocated by means of the construct

        NEW_RECORD(<classid>)


which returns a new record of the specified class.  All  subfields of
the  new  record are  set  to the  "null"  or "zero"  value  for that
subfield -- i.e., real & integer subfields will be set to  0, itemvar
subfields will be set to ANY, lists will be set to PHI,  etc.  Again,
note that entry into a block with local record pointer variables does
NOT cause records to be allocated and assigned to those variables.










                                 15
SAIL Addendum  1                                    RECORD STRUCTURES


6.5 - SUBFIELDS
      _________


Record subfields are referenced by means of the construct

        <classid>:<fieldid>[<record pointer expression>]


and may be used wherever an array element may be used.  For example

        RECORD_POINTER(VECTOR) V;
        RECORD_POINTER(CELL) C;
        RECORD_POINTER(FOO) F;

        :
        VECTOR:X[V]←VECTOR:Y[V];
        CELL:CAR[C←NEW_RECORD(CELL)]←V;
        VECTOR:Z[V]←VECTOR:X[CELL:CAR[C]];
        SUBLIS ← FOO:L[F][1 TO 3];
        :


If  the  <record pointer  expression>  gives a  null  record,  then a
runtime error message  will be generated.   This is the  only runtime
check that is made at  present.  I.e., no runtime checks are  made to
verify that the <classid> in the subfield statement matches the class
of the record whose subfield is being extracted.

An array subfield may be used as an array name, as in

        RECORD_POINTER(TABLEAU) T;
        :
        TABLEAU:A[T][I,J] ← 2.5;


provided  that you  have  stored a  valid array  descriptor  into the
subfield.  Unfortunately, SAIL does  not provide any clean way  to do
this.  One unclean way is
        INTEGER PROCEDURE NEWARY(INTEGER LB,UB);
                BEGIN
                INTEGER ARRAY A[LB:UB];
                INTEGER AA;
                AA←MEMORY[LOCATION(AA)];
                MEMORY[LOCATION(AA)]←0;
                         COMMENT defeats deallocation;
                RETURN(AA);
                END;
        :

                                 16
SAIL Addendum  1                                    RECORD STRUCTURES


        RECORD_CLASS FUBAR(INTEGER ARRAY A);
        RECORD_POINTER(FUBAR) FB;
        :
        MEMORY[LOCATION(FUBAR:A[FB])]←NEWARY(1,100);

(Warning: the  above "advice" is  primarily intended for  hackers; we
make no promisses that it  will never get you into  trouble, although
this  particular  trick  is  unlikely  to  be  made  obsolete  in the
forseeable future).



6.6 - INTERNAL REPRESENTATIONS AND IMPLEMENTATION NOTES
      ________ _______________ ___ ______________ _____


Records are allocated  by a "small  block" allocator that  gets large
buffers of storage  from the normal  SAIL free storage  system.  Each
record currently has the following form:

        -1:     <used by garbage collector & free storage system>
         0:     20,,<record class descriptor>
        +1:     <first subfield>
                      :
        +n:     <last subfield>

Record  pointer   variables  point  at   word  0  of   such  records.
Eventually, we may do away with "-1" word altogether.

Record class descriptors currently have the form:

        0:      byte(13)length(5)0(18)<record handler procedure>
        1:      <descriptor for first field>
                :
        n:      <descriptor for last field>
      n+1:      <SAIL-format string descriptor
      n+2:       for class name>
      n+3:      ascii text for class name


The normal  value for the  handler procedure is  $REC$, which  is the
standard procedure  for such  functions as  allocation, deallocation,
etc.  Currently, this  procedure is usually  called as the  result of
user uuo  RECUUO (=8).   which, in turn,  does a  pushj p,@<effective
address>.  Thus:

        RECUUO  OP,RV           ;OP = minor op code.  RV = record var

goes (roughly to)

                                 17
SAIL Addendum  1                                    RECORD STRUCTURES


        <save acs>
        PUSH    P,[OP]
        PUSH    P,RV
        PUSH    P,[0]           ;this extra argument is sort of rando
                                ;It was intended for expansions.  Ins
                                ;it may eventually be flushed.
        PUSHJ   P,@RV
        < restore acs (except ac1) >


It is possible for a user to substitute his own handler procedure for
a given class of records by including the procedure name  in brackets
after the record class declaration:

        RECORD_CLASS <id> (<subfields>) [<handler>]

This handler must have the form

        RECORD_POINTER(ANY_CLASS) PROCEDURE <procid>
                        (INTEGER OP;RECORD_POINTER(ANY_CLASS) R1,R2);


Where OP  will be a  small integer  saying what is  to be  done.  The
current assignments for OP are:

        OP value        meaning

        0               invalid
        1               allocate a new record with same type as R1
        2               not used
        3               not used
        4               Mark all subfields of record R1
        5               Delete all space for record R1


However,  NO promisses  are  made concerning  future  assignments or,
indeed, concerning the general structure.  This feature  is primarily
intended for use by wizards, and others use it at their peril.











                                 18
SAIL Addendum  1                           MISCELLANEOUS NEW FEATURES


                             SECTION  7
                             _______  _

                     MISCELLANEOUS NEW FEATURES
                     _____________ ___ ________







7.1 - NEW MTAPE OPTIONS
      ___ _____ _______


        MTAPE(chan,NULL)


will cause an MTAPE 0 to be issued for channel chan.  For mag. tapes,
this will  cause you to  wait until all  activity ceases.   For other
devices, various  random things can  happen, depending on  the device
and system.

In export SAIL, MTAPE(chnl,"I") sets the 'IBM compatible' mode  for a
tape drive.  (It does an MTAPE chnl,101.)



7.2 - INITIALIZATION PHASES
      ______________ ______


User initializations  are  now done  in successive  phases, with  all
initializations   required   for   one   phase   being  done   before
initializations required for the next phase.

Syntax:

        REQUIRE <procid> INITIALIZATION;
        REQUIRE <procid> INITIALIZATION [<phase no>];

where <phase no> is an integer constant.

Semantics:

<phase no> specifies  the number  of the user   initialization phase.
If  it is left out,   then one is used.   Currently, there  are three
phases,  numbered 0,  1, and   2.  If  the  demand  is  great enough,
additional phases may  be added later.   (Note for assembly  language
hackers: internally, user phases are numbered '400000, '400001, etc.)


                                 19
SAIL Addendum  1                           MISCELLANEOUS NEW FEATURES


7.3 - CHNCDB
      ______


        val←CHNCDB(channel)

This integer procedure returns a pointer to the three word block used
to open the  specified channel.   It is provided  for the benefit  of
assembly language procedures that may want to do I/O inside some fast
inner loop, but which may want to live in a SAIL core image & use the
SAIL OPEN, etc.



7.4 - ARRCLR
      ______


        ARRCLR(arry)

This new runtime routine clears any kind of array. That is, arthmetic
arrays get filled with  zeros, string arrays with NULLs,  and itemvar
arrays with ANYs.  One may  use ARRCLR with set and list  arrays, but
the set  and list space  will be lost  (i.e. un-garbage-collectable).
The alternative form:

        ARRCLR(arry,val)


where val is either an integer or a real number, will fill  arry with
that value.  Do not  do this to string  or list arrays unless  you do
not care whether  or not your program  works.  Also using a  real val
for an itemvar array is apt to cause strange results. (If you  use an
integer, arry will be filled with CVI(val).)



7.5 - SETPL
      _____


        SETPL(channel, @linnum, @pagnum, @sosnum)

This new runtime routine allows one to keep track of the string input
from CHANNEL.  Whenever a '12 is encountered, LINNUM  is incremented.
Whenever a '14 is  encountered, PAGNUM is incremented, and  LINNUM is
zeroed.  Whenever  an SOS  line number is  encountered, it  is placed
into SOSNUM.  When  fully implemented (soon),  this will work  on the
INPUT, INTIN, and REALIN functions as well.



                                 20
SAIL Addendum  1                           MISCELLANEOUS NEW FEATURES


7.6 - EVALREDEFINE
      ____________


EVALREDEFINE bears  the same relationship  to REDEFINE  as EVALDEFINE
does to DEFINE.  See pages 47 and 50 of the Manual.



7.7 - CVPS
      ____


CVPS(<macro_parameter>)  converts <macro_parameter>  to a  string and
returns the  string. See  about macro  parameters on  page 48  of the
manual.



7.8 - EXPRESSIONS IN REQUIRES
      ___________ __ ________


Previously,  all REQUIRE  constructs had  to have  only  constants in
them. Now  SAIL allows  compile time expressions  as well.  See about
compile time expressions on page 47 of the Manual.



7.9 - RELEASE
      _______


RELEASE  now takes  an optional  second argument,  the  CLOSE inhibit
bits.  These are described in the UUO manual (Stanford System). These
are defaulted to zero when  not specified so that old  programs which
did not specify them will work as before.



7.10 - TTYUP
       _____


        oldval←TTYUP(newval)


This  routine casuse  conversion of  lower case  characters  (a-z) to
their upper  case equivalents  for strings  read by  any of  the SAIL
teletype routines that do not  use break tables.  If newval  is TRUE,
then conversion will take place on all subsequent inputs  until TTYUP
is called with newval FALSE.  Oldval will always get set to the value


                                 21
SAIL Addendum  1                           MISCELLANEOUS NEW FEATURES


of newval used in the previous call. (If TTYUP has never been called,
then no conversions will take place, and the first call to TTYUP will
return FALSE).



7.11 - BREAKSET MODES "K" AND "F"
       ________ _____ ___ ___ ___


A "K" specification as a BREAKSET mode will cause lower to upper case
conversion when  that break  table is  used.  Conversion  takes place
before each character  is checked for  breaking or omission.   An "F"
specification turns off the conversion -- i.e. it undoes  the effects
of "K".



7.12 - INOUT
       _____


        INOUT(inchan,outchan,howmany)


INOUT reads howmany words from channel inchan and writes them  out on
channel outchan.  Each channel must  be open in a mode between  8 and
12.  on return,  the EOF variables for  the two channels will  be the
same as if ARRYIN & ARRYOUT  had been used.  If howmany is  less than
zero, then transfer  of data will  cease only upon  end of file  or a
device error.

(note: INOUT  uses BLTs  to transfer  data directly  from one  set of
buffers to the other)



7.13 - GETSTS & SETSTS
       ______ _ ______


        SETSTS(chan,new_status)

issues a SETSTS uuo on channel chan with the status value new_status.

        status←GETSTS(chan)


returns the results of a GETSTS uuo on channel chan.



                                 22
SAIL Addendum  1                           MISCELLANEOUS NEW FEATURES


7.14 - CHANGES TO "OPEN" ERROR HANDLING
       _______ __ ______ _____ ________


If the EOF variable supplied to OPEN is non-zero and the  device name
is  invalid, then  OPEN will  fail without  giving the  error message
"INVALID DEVICE NAME FOR OPEN", and the EOF value will  be unchanged.
If a device is unavailable, and EOF=0, then the user is now given the
options of trying  again or going on  without opening the  device, in
which case EOF will be set to non-zero as usual.



7.15 - ASH
       ___


ASH has  been added as  an arithmetic operator.   Its syntax  is just
like that of LSH, and  it generates similar code (except  for putting
out a PDP-10 ASH instruction instead of a LSH).



7.16 - ARG_LIST
       ________


        ARG_LIST(<arg1>,...,<argn>)


where each <arg> may be any valid argument to the REF_ITEM construct,
assembles a list of "temporary" reference items that will  be deleted
by APPLY after the applied procedure returns.  Thus

        APPLY(proc,ARG_LIST(foo,bar,VALUE baz))

is roughly equivalent to

        tmplst←{{REF_ITEM(foo),REF_ITEM(bar),REF_ITEM(VALUE baz)}};
        APPLY(proc,tmplst);
        WHILE LENGTH(tmplst) DO DELETE(LOP(tmplst));


but  is  somewhat easier  to  type.  Note  that  the  reference items
created by ARG_LIST are  just like those created by  REF_ITEM, except
that they are marked so that APPLY will know to kill them.






                                 23