GLISP USER'S MANUAL
                            GLISP USER'S MANUAL
                            GLISP USER'S MANUAL






                            Gordon S. Novak Jr.
                       Heuristic Programming Project
                        Computer Science Department
                            Stanford University
                        Stanford, California  94305









                                 d:
                                 d:
                                 d: 8 Mar
                           ReviseHPP-82-1
                           ReviseHPP-82-1
                           ReviseHPP-82-1ch 1983

                         STAN-CS-82-895, Revised.
                         STAN-CS-82-895, Revised.
                         STAN-CS-82-895, Revised.













This  research  was supported in part by NSF Grant SED-7912803 in the Joint
National Science Foundation - National Institute of  Education  Program  of
Research  on  Cognitive Processes and the Structure of Knowledge in Science
and Mathematics and in part  by  the  Defense  Advanced  Research  Projects
Agency under Contract MDA-903-80-c-007.
                                                                          1


                                 CHAPTER 1
                                 CHAPTER 1
                                 CHAPTER 1

                               INTRODUCTION
                               INTRODUCTION
                               INTRODUCTION



1.1. Overview of GLISP
1.1. Overview of GLISP
1.1. Overview of GLISP

     GLISP  is  a  Lisp-based  language  that  provides high-level language

features not found in ordinary Lisp.  The GLISP language is implemented  by

means  of a compiler that accepts GLISP as input and produces ordinary Lisp

as output; this output can be further compiled to machine code by the  Lisp

compiler.    GLISP  is  available  for  several  Lisp  dialects,  including

Interlisp, Maclisp, UCI Lisp, ELISP,  Franz  Lisp,  and  Portable  Standard

Lisp.

     The  goal  of  GLISP  is to make programming easier by allowing design

decisions to be expressed in  a  single  place  and  letting  the  compiler

generate  code according to those design decisions.  This philosophy allows

source program code to be shorter  and  more  readable  and  allows  design

decisions to be changed without requiring that program code be rewritten.

     GLISP provides both Pascal-like and English-like syntaxes; much of the

power  and brevity of GLISP derives from the compiler features necessary to

support the relatively informal, English-like  language  constructs.    The

following  example  of  a  GLISP  function  illustrates the use of definite

reference to structured objects.



    (HourlySalaries (GLAMBDA (D:DEPARTMENT)
       (for each EMPLOYEE who is HOURLY
          (PRIN1 NAME) (SPACES 3) (PRINT SALARY) )  ))



The features provided by GLISP include the following:
                                                                          2


   1. GLISP  maintains  knowledge of object types and of the "context"
      of the computation as the program  is  compiled.    Features  of
      objects  that  are  in  context  may be referenced directly; the
      compiler will determine how to reference the objects  given  the
      current context and will add the newly referenced objects to the
      context.    In  the  example  above, the function's argument, an
      object whose class is DEPARTMENT, establishes an initial context
      relative to which EMPLOYEEs can be found.  In the context of  an
      EMPLOYEE, NAME and SALARY can be found.

   2. GLISP  supports  flexible object definition and reference with a
      powerful abstract data type facility.  Object classes are easily
      declared to the  system.    An  object  declaration  includes  a
      definition   of   the   storage  structure  of  the  object  and
      declarations of properties of the object; these may be  declared
      in  such  a  way  that they compile open, resulting in efficient
      object code.

   3. GLISP supports object-centered programming, in  which  processes
      are  invoked  by  means  of  "messages" sent to objects.  Object
      structures  may  be  Lisp  structures   (for   which   code   is
                                      ←←←←←
      automatically  compiled)  or    units    in  the user's favorite
      representation  language  (for  which  the   user   can   supply
      compilation functions).

   4. Pascal-like  control  statements  and  loop  constructs, such as
       (FOR EACH <item> WITH <property> DO  . . .) , are compiled into
      Lisp code of the appropriate form.

   5. Compilation of infix expressions is provided for the  arithmetic
      operators  and  for  additional  operators  that facilitate list
      manipulation.  Operators are interpreted appropriately for  Lisp
      data  types  as  well  as  for numbers; operator overloading for
      user-defined objects is provided by the message facility.

   6. The GLISP compiler infers the types of objects when possible and
      uses this knowledge to  generate  efficient  object  code.    By
                    ←←←←←←←←←←← ←←←←←←←← ←← ← ←←←←←←←←← ←←←←
      performing    compilation relative to a knowledge base, GLISP is
      able to perform certain computations (e.g.,  inheritance  of  an
      attached  procedure  from  a  parent  class  of  an  object in a
      knowledge base)  at  compile  time  rather  than  at  run  time,
      resulting in much faster execution.

   7. By  separating  object definitions from the code that references
      objects, GLISP permits radical changes to object structures with
      no changes to code.
                                                                          3


1.2. Implementation
1.2. Implementation
1.2. Implementation

     GLISP  is  implemented by means of a compiler, which produces a normal

Lisp EXPR from the GLISP code.  When a  GLISP  function  is  compiled,  the

original  GLISP  code  is  saved  on  the function's property list, and the

compiled code is stored as the function definition.  Use of  GLISP  entails

the  cost  of  a  single compilation but otherwise is about as efficient as

normal Lisp.  The Lisp code produced by GLISP can be  further  compiled  to

machine code by the Lisp compiler.

     GLISP  functions are defined in such a way that they are automatically

compiled the first time they are referenced.  In some Lisp dialects,  GLISP

functions  are  indicated  by  the  use of GLAMBDA instead of LAMBDA in the

function definition.  In other dialects, a  special  defining  function  is

used;  this  function  sets up a macro definition which invokes compilation

the first time the function is referenced.  The user can explicitly  invoke

compilation  of  GLISP  functions  by calling the compiler function GLCC or

GLCP.

     To use GLISP, it is first necessary to load  the  compiler  file  into

Lisp.    Users'  files containing structure descriptions and GLISP code are

then loaded.  Compilation of a GLISP function is requested by:



     (GLCC '<fn>)     Compile the function <fn>.

     (GLCP '<fn>)     Compile <fn> and "prettyprint" the result.

     (GLP '<fn>)      Print the compiled version of <fn>.


In Interlisp, all the GLISP functions (beginning with GLAMBDA)  in  a  file

can  be  compiled  by invoking (GLCOMPCOMS <file>COMS), where <file>COMS is

the list of file package commands for the file.
                                                                          4


     Properties  of  compiled  functions are stored on the property list of

the function name:


                                                               1
     GLORIGINALEXPR   Original (GLISP) version of the function. 
     GLCOMPILED       GLISP-compiled version of the function.
     GLRESULTTYPE     Type of the result of the function.
     GLARGUMENTTYPES  Types of the arguments of the function.


Functions are provided to call the Lisp editor for examination and  editing

of GLISP functions and object descriptions:



     (GLED '<name>)   Edit the property list of <name>.
     (GLEDF '<fn>)    Edit the GLISP definition of <fn>.
     (GLEDS '<str>)   Edit the structure <str>.



1.3. Error Messages
1.3. Error Messages
1.3. Error Messages

     GLISP  provides  detailed  error  messages when compilation errors are

detected; many careless errors, such as misspellings, will be caught by the

compiler.  When the source  program  contains  errors,  the  compiled  code

generates run time errors upon execution of the erroneous expressions.



1.4. Interactive Features of GLISP
1.4. Interactive Features of GLISP
1.4. Interactive Features of GLISP

     Several  features  of  GLISP are available interactively as well as in

compiled functions:  


   1. The A function, which creates structured objects from a readable
      property-value list, is available as  an  interactive  function.
      See Section 3.2.


←←←←←←←←←←←←←←←

  1
   The original definition is saved as EXPR in Interlisp.
                                                                          5


   2. Messages  to objects can be executed interactively.  See Section
      5.5

   3. A display-oriented editor and inspector, GEV, is  available  for
                                             2
      use  with  bitmap  graphics  terminals.   GEV interprets objects
      according to their GLISP structure descriptions; it  allows  the
      user  to  inspect  objects,  edit  them, interactively construct
      programs that operate on them, display computed properties, send
      messages to objects, and zoom in on features of interest.






































←←←←←←←←←←←←←←←

  2
   GEV is currently implemented only for Xerox Lisp machines.
                                                                          6


                                 CHAPTER 2
                                 CHAPTER 2
                                 CHAPTER 2

                            OBJECT DESCRIPTIONS
                            OBJECT DESCRIPTIONS
                            OBJECT DESCRIPTIONS



2.1. Declaration of Object Descriptions
2.1. Declaration of Object Descriptions
2.1. Declaration of Object Descriptions

        ←←←←←← ←←←←←←←←←←←
     An object description in GLISP is a description of the structure of an

object  in  terms of named substructures, together with definitions of ways

                                                    ←←←←←←←←←←
of referencing the object.  The latter may include  properties  (i.e., data

whose values are not stored but are computed  from  the  values  of  stored

                                  ←←←←←←←←
data), adjectival predicates, and messages that the object can receive; the

messages   can   be  used  to  implement  operator  overloading  and  other

compilation features.

     Object descriptions are obtained by GLISP in several ways:


   1. The  descriptions  of  basic  data-types  (e.g.,  INTEGER)   are
      automatically known to the compiler.

   2. Structure descriptions (but not full object descriptions) may be
                       ←←←←←
      used directly as types in function definitions.

   3. The  user  may  declare object descriptions to the system by the
      function GLISPOBJECTS; the names of the object types may then be
      used as types in function definitions and definitions  of  other
      structures.

   4. Object  descriptions  may  be  included  as  part of a knowledge
      representation language and are then furnished to GLISP  by  the
      interface package written for that representation language.


                                                                   3
     Lisp data structures are declared by the function GLISPOBJECTS , which


←←←←←←←←←←←←←←←

  3
   Once  declared, object descriptions may be included in Interlisp program
files  by  including  in  the  <file>COMS  a   statement   of   the   form:

(GLISPOBJECTS <object-name > ... <object-name >).
                          1                  n
                                                                          7


takes   one   or  more  object  descriptions  as  arguments  (assuming  the

descriptions to be quoted).  Since GLISP compilation is performed  relative

to  the knowledge base of object descriptions, the object descriptions must

be  declared  prior  to  GLISP  compilation  of   functions   using   those

descriptions.  The format of each description is as follows:



    (<object name>
         <structure description>
              PROP   <property descriptions>
              ADJ    <adjective descriptions>
              ISA    <isa-adjective descriptions>
              MSG    <message descriptions>
              SUPERS <list of superclasses>
              VALUES <list of values>              )



The  <object  name>  and  <structure  description>  are required; the other

property-value pairs are optional  and  may  appear  in  any  order.    The

following  example  illustrates some of the declarations that might be made

to describe the object type VECTOR.
                                                                          8



    (GLISPOBJECTS

       (VECTOR   (CONS (X NUMBER) (Y NUMBER))

          PROP   ( (MAGNITUDE  ((SQRT X*X + Y*Y))) )

          ADJ    ( (ZERO       (X IS ZERO AND Y IS ZERO))
                   (NORMALIZED (MAGNITUDE = 1.0)) )

          ISA    ( (UNITVECTOR (self IS NORMALIZED)) )

          MSG    ( (+          VECTORPLUS OPEN T)
                   (-          VECTORDIFFERENCE) ) )


       (PLANET   (LISTOBJECT (NAME ATOM) (MASS REAL) (RADIUS REAL))

          SUPERS (PHYSICAL-OBJECT SPHERE) )

    )



2.1.1. Property Descriptions
2.1.1. Property Descriptions
2.1.1. Property Descriptions

     The  PROP,  ADJ, ISA, and MSG descriptions specify computed properties

of the object; the four kinds of properties differ in the way in which they

are referenced in GLISP program code.   PROPerties  are  properties  of  an

object  which  are  computed  rather  than  being stored directly; they are

referenced within code in the same way as  stored  values.    ADJ  and  ISA

specify  adjectival predicates which are used to test properties of objects

within conditional statements (see Section 3.4).   MSG  properties  specify

messages  which  the object can receive (see Section 5).  Messages may take

arguments, and may have side-effects.

     Each <description> specified with PROP,  ADJ,  ISA,  or  MSG  has  the

following format:
                                                                          9



    (<name>  <response>  <prop > <value > ... <prop > <value >)
                              1        1           n        n



where <name> is the (atomic) name of the property, <response> is a function

name  or  a list of GLISP code to be compiled in place of the property, and

the <prop> <value> pairs are optional properties that  affect  compilation.

All  four  kinds  of  properties  are  compiled  in  a  similar fashion, as

described in Section 5.1.  The uses of each kind of property are  described

below.
                                                                         10


2.1.1.1. PROP Descriptions
2.1.1.1. PROP Descriptions
2.1.1.1. PROP Descriptions

                                 ←←←←←←←←←←
     PROP  descriptions  specify properties of an object, that is, features

of the object which are treated as if they were stored data but  which  are

in  fact  computed from stored data.  By convention, properties are assumed

to be functional, that is, to have no side-effects.


2.1.1.2. ADJ and ISA Descriptions
2.1.1.2. ADJ and ISA Descriptions
2.1.1.2. ADJ and ISA Descriptions

                                                 ←←←←←←←←←←
     ADJ and ISA descriptions specify adjectival predicates  which  may  be

used  to  test  features  of  an  object.  The ISA form is used for nominal

adjectives, that is, those which would normally be written with "a" or "an"

in English.  Adjectives are normally implemented by  code  that  returns  a

BOOLEAN value.


2.1.1.3. MSG Descriptions
2.1.1.3. MSG Descriptions
2.1.1.3. MSG Descriptions

                                 ←←←←←←←←
     MSG  descriptions  specify  messages  which  can be sent to an object.

Messages can take arguments, and may have side effects.


2.1.2. SUPERS Description
2.1.2. SUPERS Description
2.1.2. SUPERS Description

                                          ←←←←←←←←←←←←
     The SUPERS list specifies a list of  superclasses, that is, the  names

of  other  object descriptions from which the object may inherit PROP, ADJ,

ISA, and MSG properties.  Inheritance from superclasses can  be  recursive,

as described in Section 5.1.


2.1.3. VALUES Description
2.1.3. VALUES Description
2.1.3. VALUES Description

     The VALUES list is a list of pairs, (<name> <value>), which is used to

associate  symbolic  names  with  constant  values  for an object type.  If

                                       ←←←←←←←←
VALUES are defined for the type of the selector of a  CASE  statement,  the

corresponding  symbolic  names  may be used as the selection values for the
                                                                         11


clauses of the CASE statement.



2.2. Structure Descriptions
2.2. Structure Descriptions
2.2. Structure Descriptions

     Much  of  the  power  of  GLISP  is  derived from its use of structure

descriptions.  A structure description (abbreviated "<sd>") is a  means  of

describing  a  Lisp  data  structure  and  giving  names  to  parts  of the

structure; it is similar in concept to  a  record  declaration  in  Pascal.

Structure  descriptions  are used by the GLISP compiler to generate code to

retrieve and store parts of structures.


2.2.1. Syntax of Structure Descriptions
2.2.1. Syntax of Structure Descriptions
2.2.1. Syntax of Structure Descriptions

     The syntax of structure descriptions is recursively defined  in  terms

of basic types and composite types that are built up from basic types.  The
                                               4
syntax of structure descriptions is as follows: 


   1. The following basic types are known to the compiler:


           ATOM
           ATOM
           ATOM
           INTEGER
           INTEGER
           INTEGER
           REAL
           REAL
           REAL
           NUMBER
           NUMBER
           NUMBER    (either INTEGER or REAL)
           STRING
           STRING
           STRING
           BOOLEAN
           BOOLEAN
           BOOLEAN   (either T or NIL)
           ANYTHING
           ANYTHING
           ANYTHING  (an arbitrary structure)


   2. An  object  type  that  is  known to the compiler, either from a
      GLISPOBJECTS declaration or because it is a class  of  units  in


←←←←←←←←←←←←←←←

  4
   The  names  of the basic types and the structuring operators must be all
upper case or lower case, depending on the case  which  is  usual  for  the
underlying  Lisp system.  In general, other GLISP keywords and user program
names may be in upper case, lower case, or mixed case, if mixed  cases  are
permitted by the Lisp system.
                                                                         12


      the  user's  knowledge  representation language, is a valid type
      for use in a structure description.   The  <name>   of  such  an
      object  type  may  be  specified  directly  as  <name>  or,  for
                                                   5
                       (A       )      (AN       )
                       (A       )      (AN       )
      readability, as  (A <name>)  or  (AN <name>).

   3. Any substructure can be named by enclosing it in a list prefixed
                       (            )
                       (            )
      by  the  name:   (<name>  <sd>) .     This   allows   the   same
      substructure  to  have multiple names.  "A", "AN", and the names
      used in forming composite types (given  below)  are  treated  as
      reserved words and may not be used as names.

   4. Composite  structures:   Structured data types composed of other
      structures  are  described  using  the   following   structuring
      operators:


             CONS
             CONS
         a. (CONS  <sd >  <sd >)
                      1      2
            The  CONS  of  two structures whose descriptions are <sd >
                                                                    1
            and <sd >.
                   2
             LIST
             LIST
         b. (LIST  <sd >  <sd >  . . .  <sd >)
                      1      2             n
            A list of exactly  the  elements  whose  descriptions  are

            <sd > <sd > . . . <sd >.
               1     2           n
             LISTOF
             LISTOF
         c. (LISTOF  <sd>)
            A  list  of  zero  or more elements, each of which has the
            description <sd>.

             ALIST
             ALIST
         d. (ALIST  (<name > <sd >) . . . (<name > <sd >))
                          1     1               n     n
            An association list in which the atom <name >, if present,
                                                       i
            is associated with a structure whose description is <sd >.
                                                                   i
             PROPLIST
             PROPLIST
         e. (PROPLIST  (<name > <sd >) . . . (<name > <sd >))
                             1     1               n     n
            An association list in "property-list format" (alternating
            names and values) in which the atom <name >,  if  present,
                                                     i
            is associated with a structure whose description is <sd >.
                                                                   i

←←←←←←←←←←←←←←←

  5
                      (A . . .)                               (AN . . .)
                      (A . . .)                               (AN . . .)
   Whenever  the form (A . . .) is allowed in GLISP, the form (AN . . .) is
also allowed.
                                                                         13


         f. 

             ATOM    PROPLIST                                               BINDING
             ATOM    PROPLIST                                               BINDING
            (ATOM   (PROPLIST  (<pname > <sd >) . . . (<pname > <sd >) )   (BINDING  <sd>))
                                      1     1                n     n
            This  describes  an  atom  with  its  binding  and/or  its
            property  list;  either  the BINDING or the PROPLIST group
            may be omitted.  Each property name <pname > is treated as
                                                      i
            a property-list indicator as  well  as  the  name  of  the
            substructure.    When  creation  of  such  a  structure is
            specified, GLISP will compile  code  to  create  a  GENSYM
            atom.

         g. 

             RECORD
             RECORD
            (RECORD  <record-name>  (<name > <sd >)  ...  (<name > <sd >))
                                          1     1               n     n
            RECORD specifies the use of contiguous  records  for  data
            storage.  <record-name> is the name of the record type; it
                                                              6
            is optional and is not used in some Lisp dialects. 

             TRANSPARENT
             TRANSPARENT
         h. (TRANSPARENT  <type>)
            An   object  of  type  <type>  is  incorporated  into  the
                                       ←←←←←←←←←←← ←←←←
            structure being defined in transparent mode,  which  means
            that  all  fields  and  properties  of  the object of type
            <type>  can  be  directly  referenced  as  if  they   were
            properties  of  the  object being defined.  A substructure
                            ←←←←
            that is a named type  and  that  is  not  declared  to  be
            TRANSPARENT is assumed to be opaque; that is, its internal
            structure  cannot be seen unless an access path explicitly
                               7
            names the subrecord .  The object of type <type> may  also
            contain  TRANSPARENT  objects;  the  graph  of TRANSPARENT


←←←←←←←←←←←←←←←

  6
   RECORDs are implemented using RECORDs in Interlisp, HUNKs in Maclisp and
Franz Lisp, VECTORs in Portable Standard Lisp, and lists in  UCI  Lisp  and
ELISP.    In Interlisp, appropriate RECORD declarations must be made to the
system by the user in addition to the GLISP declarations.

  7
   For example, a PROFESSOR record  might  contain  some  fields  that  are
unique  to  professors,  plus  a  pointer  to  an  EMPLOYEE record.  If the
declaration in the PROFESSOR record  were  (EMPREC (TRANSPARENT EMPLOYEE)),
then  a  field  of  the  employee  record, say, SALARY, could be referenced
directly from a variable P that points to a PROFESSOR record  as  P:SALARY;
if  the  declaration  were  (EMPREC EMPLOYEE), it would be necessary to say
P:EMPREC:SALARY.
                                                                         14


            object references must, of course, be acyclic.

             OBJECT
             OBJECT
         i. (OBJECT  (<name > <sd >) . . . (<name > <sd >))
                           1     1               n     n
             ATOMOBJECT
             ATOMOBJECT
            (ATOMOBJECT  (<name > <sd >) . . . (<name > <sd >))
                               1     1               n     n
             LISTOBJECT
             LISTOBJECT
            (LISTOBJECT  (<name > <sd >) . . . (<name > <sd >))
                               1     1               n     n
                                             ←←←←←←←
            These   declarations   describe  objects,  that  is,  data
            structures which can receive messages at run time.   These
            three  types of objects are implemented as records, atoms,
            or lists, respectively.  In each case, the system adds  to
            the  object  a  CLASS datum that points to the name of the
            type of the object.  An object declaration may only appear
            as the top-level declaration of a named object type.

             TYPEOF
             TYPEOF
         j. (TYPEOF  <expression>)
            This declaration specifies the same type that <expression>
            would have if it were evaluated.  The  TYPEOF  declaration
            can  only  be  used  within  functions  (not within object
            descriptions), and it can only be used where  <expression>
            is  a  valid  expression whose type can be inferred by the
                                                   ←←←←←←←  ←←←←←←←←←
            compiler.  TYPEOF is useful in writing generic  functions,
            that  is,  abstract functions which are defined over a set
            of object types.


2.2.2. Examples of Structure Descriptions
2.2.2. Examples of Structure Descriptions
2.2.2. Examples of Structure Descriptions

     The following examples illustrate the use of structure descriptions.



    (GLISPOBJECTS

        (CAT (LIST (NAME ATOM)
                   (PROPERTIES (LIST (CONS (SEX ATOM)
                                           (WEIGHT INTEGER))
                                     (AGE INTEGER)
                                     (COLOR ATOM)))
                   (LIKESCATNIP BOOLEAN)))

        (PERSON (ATOM
                  (PROPLIST
                    (CHILDREN (LISTOF (A PERSON)))
                    (AGE INTEGER)
                    (PETS (LIST (CATS (GATOS (LISTOF CAT)))
                                (DOGS (LISTOF (A DOG))) ))
                 )))
       )
                                                                         15


The  first  structure,  CAT, is entirely composed of list structure.  A CAT

structure might look like:


    (PUFF ((MALE . 10) 5 CALICO) T)


Given a CAT object X, we could ask for its WEIGHT  [equivalent  to  (CDAADR

X)] or for a subrecord such as PROPERTIES [equivalent to (CADR X)].  Having

set a variable Y to the PROPERTIES, we could also ask for the WEIGHT from Y

[equivalent  to  (CDAR  Y)].  In general, whenever a subrecord is accessed,

the structure description of the subrecord is associated  with  it  by  the

compiler,  enabling  further accesses to parts of the subrecord.  Thus, the

meaning of a subrecord name depends on the type of record  from  which  the

subrecord  is retrieved.  The subrecord AGE has two different meanings when

applied to PERSONs and to CATs.  The second structure, PERSON,  illustrates

a  description  of  an object that is a Lisp atom with properties stored on

its property list.  Whereas no structure names  appear  in  an  actual  CAT

structure,  the substructures of a PROPLIST operator must be named, and the

names appear in the actual structures.  For  example,  if  X  is  a  PERSON

structure,  retrieval of the AGE of X is equivalent to (GETPROP X 'AGE).  A

subrecord of a PROPLIST record can be referenced directly; for example, one

can ask for the DOGS of a PERSON directly, without cognizance of  the  fact

that  DOGS  is part of the PETS property.  A substructure can have multiple

names; for example, CATS and GATOS name the same subrecord of a PERSON.
                                                                         16


2.3. Editing of Object Descriptions
2.3. Editing of Object Descriptions
2.3. Editing of Object Descriptions

     An  object  description  can  be edited by calling (GLEDS TYPE), where

TYPE is the name of the object type.  This will cause the Lisp editor to be

called on the object description of TYPE.



2.4. Interactive Editing of Objects
2.4. Interactive Editing of Objects
2.4. Interactive Editing of Objects

     An interactive structure inspector and editor, GEV, is  available  for

the  Xerox  1100-series  Lisp machines.  GEV allows the user to inspect and

edit any structures that are described by  GLISP  object  descriptions,  to

zoom in on substructures of interest, and to display the values of computed

properties  automatically  or  on  demand.   GEV is described in a separate

document [3].



2.5. Global Variables
2.5. Global Variables
2.5. Global Variables

     The types of free variables can be declared within the functions  that

reference  them.    Alternatively,  the  types  of  global variables can be
                                        8
declared to the compiler using the form: 



    (GLISPGLOBALS  (<name> <type>) ... )



Following such a declaration, the compiler will assume that a free variable

<name> is of the corresponding <type>.  A GLOBAL object does  not  have  to



←←←←←←←←←←←←←←←

  8
   (GLISPGLOBALS <name > ... <name >)  is defined as a file-package command
                      1           n
for Interlisp.
                                                                         17


actually  exist  as  a  storage  structure; for example, one could define a

global object "MOUSE" or "SYSTEM" whose properties are actually implemented

by calls to the operating system.



2.6. Compile Time Constants
2.6. Compile Time Constants
2.6. Compile Time Constants

     The values and types of compile-time constants can be declared to  the
                        9
compiler using the form:  



    (GLISPCONSTANTS  (<name> <value-expression> <type>) ... )



The   <name>   and   <type>   fields   are  assumed  to  be  quoted.    The

<value-expression>  field  is  a  GLISP  expression  that  is  parsed   and

evaluated;  this  allows  constants  to be defined by expressions involving

previously defined constants.



2.7. Conditional Compilation
2.7. Conditional Compilation
2.7. Conditional Compilation

     The  GLISP  compiler  will  perform  many  kinds  of  computations  on

constants  at  compile  time,  reducing  the  size of the compiled code and









←←←←←←←←←←←←←←←

  9
   (GLISPCONSTANTS <name > ... <name >)  is  defined  as   a   file-package
                        1           n
command  for  Interlisp.   The GLISPCONSTANTS expressions written to a file
will contain the original  <value-expression>  entries  rather  than  their
evaluated values.
                                                                         18


                              10
improving   execution   speed.    In  particular,  arithmetic,  comparison,

logical,  conditional,  and  CASE  function  calls  are   optimized,   with

elimination  of dead code.  This permits conditional compilation in a clean

form.  Code can be written that tests the values of flags in the usual way;

if the  flag  values  are  declared  to  be  compile-time  constants  using

GLISPCONSTANTS,  the  tests  will  be  performed  at  compile time, and the

unneeded code will vanish.































←←←←←←←←←←←←←←←

  10
    Ordinary Lisp functions are evaluated  on  constant  arguments  if  the
property  GLEVALWHENCONST  is set to T on the property list of the function
name.  This property is set  by  the  compiler  for  the  basic  arithmetic
functions.
                                                                         19


                                 CHAPTER 3
                                 CHAPTER 3
                                 CHAPTER 3

                           REFERENCE TO OBJECTS
                           REFERENCE TO OBJECTS
                           REFERENCE TO OBJECTS



3.1. Accessing Objects
3.1. Accessing Objects
3.1. Accessing Objects

     The problem of reference is the problem of determining what object, or

feature  of a structured object, is referred to by some part of a statement

in a language.  Most programming languages solve the problem  of  reference

by  unique naming: Each distinct object in a program unit has a unique name

and is referenced by that name.  Reference to a part of a structured object

is done by giving the name of the variable denoting the object and  a  path

specification that tells how to get to the desired part from the whole.

     GLISP  permits  reference by unique naming and path specification but,

                     ←←←←←←←← ←←←←←←←←← ←←←←←←←←  ←←  ←←←←←←←
in addition, permits definite reference relative  to  context.  A  definite

reference  is  a  reference to an object that has not been explicitly named

before but that can be  understood  relative  to  the  current  context  of

computation.    If,  for  example,  an  object  of  type VECTOR (as defined

earlier) is in context, the program statement


    (IF X IS NEGATIVE ... )


contains a definite reference to "X", which may be  interpreted  as  the  X

substructure  of  the  VECTOR  which  is in context.  The definition of the

computational context and the way in which definite references are resolved

are covered in Section 6.

     In the following section, which describes the syntaxes of reference to

objects in GLISP, the following notation is used.    "<var>"  refers  to  a

variable  name  in  the  usual Lisp sense, that is, a LAMBDA variable, PROG
                                                                         20


variable, or GLOBAL variable; the variable is assumed to point to (i.e., be

bound to) an object.  "<type>" refers to the type of object pointed to by a

variable.  "<property>" refers to a property or subrecord of an object.

     Two  syntaxes  are available for reference to objects: an English-like

syntax and a Pascal-like syntax.    The  two  are  equivalent  and  may  be

intermixed  freely  within  a  GLISP  function.    The  allowable  forms of

references in the two syntaxes are shown in the table below.  


 ←←←←←←  ←←←←←←           ←←←←←←←  ←←←←←←         ←←←←←←←
"Pascal" Syntax          "English" Syntax         Meaning

<var>                    <var>                    The object denoted
                                                  by <var>
:                        The
:                        The
:<type>                  The <type>               The object whose type
                                                  is <type>
:                        The
:                        The
:<property>              The <property>           The <property> of
←←
or  <property>                                    some object

     :                   The            of
     :                   The            of
<var>:<property>         The <property> of <var>  The <property> of the
                                                  object denoted by <var>


     These forms can be extended to specify longer  paths  in  the  obvious

way,   as   in   "The   SPECIALTY   of  the  HEAD  of  the  DEPARTMENT"  or

"DEPARTMENT:HEAD:SPECIALTY".  Note that there  is  no  distinction  between

reference to substructures and reference to properties as far as the syntax

of  the referencing code is concerned; this facilitates hiding the internal

structures of objects.



3.2. Creation of Objects
3.2. Creation of Objects
3.2. Creation of Objects

     GLISP allows the creation of structures to be specified by expressions

of the form:


                 ←←←←
                 ←←←←
                 ←←←←
     (A          with               =            ,       ,                =
     (A          with               =            ,       ,                =
     (A  <type>  with  <property >  =  <value >  , . . . ,  <property >   =
                                1            1                       n
        )
        )
<value >)
      n
                                                                         21




                        ←←←←
In  this  expression,  "with", "=", and "," are allowed for readability but
                          11
may be omitted if desired;   if present, they must all be delimited on both

sides by blanks.  In response to such an expression,  GLISP  will  generate

code  to  create a new instance of the specified structure.  The <property>

names may be specified in any order.  Unspecified properties are  defaulted

according to the following rules:


   1. Basic  types  are defaulted to 0 for INTEGER and NUMBER, 0.0 for
      REAL, and NIL for other types.

   2. Composite structures are created  from  the  defaults  of  their
      components,  except  that  missing PROPLIST and ALIST items that
      would default to NIL are omitted.


Except for missing PROPLIST and ALIST elements, as  noted  above,  a  newly

created structure will contain all of the fields specified in its structure

description.



3.3. Interpretive Creation of Objects
3.3. Interpretive Creation of Objects
3.3. Interpretive Creation of Objects

     The  "A"  function  is defined for interpretive use as well as for use

within GLISP functions.  For example, one could say:



    (SETQ EARTH (A PLANET WITH MASS = 5.98E24 RADIUS = 6.37E6))





←←←←←←←←←←←←←←←

  11
    Some Lisp dialects, e.g., Maclisp, will interpret commas as "backquote"
commands and generate error messages.  In such dialects, the commas must be
omitted or be "slashified", i.e., preceded by a slash.  It may be desirable
to avoid commas in all GLISP forms to aid transportability.
                                                                         22


3.4. Predicates on Objects
3.4. Predicates on Objects
3.4. Predicates on Objects

     Adjectives defined for structures using the ADJ and ISA specifications

                                                     If     For
                                                     If     For
may  be  used in predicate expressions on objects in If and For statements.

The syntax of basic predicate expressions is:


             is
             is
    <object> is <adjective>
             is a
             is a
    <object> is a <isa-adjective>


                                                                   12
Basic predicate expressions may be combined using AND, OR, NOT or ~  ,  and

grouping parentheses.

     The  compiler  automatically  recognizes  the  Lisp adjectives ATOMIC,

NULL, NIL, INTEGER, REAL, ZERO, NUMERIC, NEGATIVE, MINUS, and BOUND and the

ISA-adjectives ATOM, LIST, NUMBER,  INTEGER,  SYMBOL,  STRING,  ARRAY,  and
       13
BIGNUM;     user   definitions   have   precedence  over  these  predefined

adjectives.


3.4.1. Self-Recognition Adjectives
3.4.1. Self-Recognition Adjectives
3.4.1. Self-Recognition Adjectives

     If the ISA-adjective self is defined for an object type, the type name

may be used as an ISA-adjective to test whether a given object is a  member

of  that  type.    Given  a  predicate  phrase  of the form "X is a Y", the

compiler first looks at the definition of the object type of X to see if  Y

is  defined as an ISA-adjective for such objects.  If no such ISA-adjective

is found, and Y is a type name, the  compiler  looks  to  see  if  self  is



←←←←←←←←←←←←←←←

  12
    The operators "NOT" and "~" are equivalent.

  13
    where applicable
                                                                         23


defined as an ISA-adjective for Y and, if so, compiles it.

                                                                        If
                                                                        If
     If  a  self  ISA-adjective predicate is compiled as the test of an If,

While     For
While     For
While, or For statement, and the tested object is a  simple  variable,  the

variable  will  be  known  to be of that type within the scope of the test.

For example, in the statement



       (If X is a FOO then (Send X Print) ... )



the compiler will know that X is a  FOO  if  the  test  succeeds  and  will

compile  the Print message appropriate for a FOO, even if the type of X was

declared as something other than FOO earlier.  This feature  is  useful  in

implementing disjunctive types, as discussed in a later section.


3.4.2. Testing Object Classes
3.4.2. Testing Object Classes
3.4.2. Testing Object Classes

     For  those  data  types  that  are  defined  using  one  of the OBJECT

structuring operators, the  class  name  is  automatically  defined  as  an

ISA-adjective.   The ISA test is implemented by run-time examination of the

CLASS datum of the object.
                                                                         24


                                 CHAPTER 4
                                 CHAPTER 4
                                 CHAPTER 4

                           GLISP PROGRAM SYNTAX
                           GLISP PROGRAM SYNTAX
                           GLISP PROGRAM SYNTAX



4.1. Function Syntax
4.1. Function Syntax
4.1. Function Syntax

     GLISP function syntax is essentially the same as that of Lisp with the

addition of type information and RESULT and GLOBAL declarations.  The basic
                   14
function syntax is:  



                      GLAMBDA
                      GLAMBDA
    (<function-name> (GLAMBDA (<arguments>)
                              ←←←←←←
                              ←←←←←←
                              ←←←←←←
                             (RESULT                     )
                             (RESULT                     )
                             (RESULT <result-description>)
                              ←←←←←←
                              ←←←←←←
                              ←←←←←←
                             (GLOBAL                               )
                             (GLOBAL                               )
                             (GLOBAL <global-variable-descriptions>)
          (PROG (<prog-variables>)
                <code>   )))



The  RESULT declaration is optional; in many cases, the compiler will infer

the result type automatically.  The main use of the RESULT  declaration  is

to  allow  the  compiler to determine the result type without compiling the

function, which may be useful when compiling another  function  that  calls

it.    The  <result-description>  is  a  standard  structure description or

<type>.

     The GLOBAL declaration is used to inform the compiler of the types  of

free variables.  The function GLISPGLOBALS can be used to declare the types

of global variables, making GLOBAL declarations within individual functions



←←←←←←←←←←←←←←←

  14
    This  diagram  illustrates  function syntax used within Interlisp.  For
other dialects, the defining syntax is similar to the defining syntax  used
for  ordinary Lisp functions; see Section 8.5.  The PROG, of course, is not
required.  In Lisp dialects other than Interlisp and Franz Lisp, LAMBDA may
be used instead of GLAMBDA.
                                                                         25


unnecessary.

     The  major  difference  between  a  GLISP  function  definition  and a

standard  Lisp  definition  is  the  presence  of  type  declarations   for

variables, which are in Pascal-like syntax of the following forms:



    <variable>
              :
              :
    <variable>:<type>
              :(A       )
              :(A       )
    <variable>:(A <type>)
              ,          ,   :
              ,          ,   :
    <variable>,<variable>,...:<type>
              ,          ,   :(A       )
              ,          ,   :(A       )
    <variable>,<variable>,...:(A <type>)
              :
              :
              :<type>
               (A       )
               (A       )
               (A <type>)
                       ←←
               <type>  if <type> is a non-atomic structure description




In  addition  to  declared  <type>s,  a  structure  description may be used

directly as a <type> in a variable declaration.    The  following  examples

illustrate legal forms of variable declarations:



         X
         V:VECTOR
         C:(A CAT)
         X,Y,Z:REAL
         BUYER,SELLER:(A PERSON)
         BUYER,SELLER:PERSON
         (A COMPANY)
         :COMPANY
         (CONS (FIRST ATOM) (SECOND INTEGER))
         EXPR:(CONS (FN ATOM) (ARGS (LISTOF ANYTHING)))



     Type  declarations are required only for variables whose subrecords or

properties will be referenced.  In general, if the value of a  variable  is

computed  in  such  a  way  that the type of the value can be inferred, the

variable will receive the appropriate type automatically; in such cases, no

                                                           ←←←←←←←
type declaration is necessary.  Since GLISP  maintains  a  context  of  the
                                                                         26


computation, it is often unnecessary to name a variable that is an argument

of a function; in such cases, it is only necessary to specify the <type> of

the  argument,  as  shown  in  the latter two syntax forms above.  PROG and

GLOBAL declarations must  always  specify  variable  names  (with  optional

types);  the  ability to directly reference features of objects reduces the

number of PROG variables needed in many cases.

     Initial values for PROG variables may be specified, as  in  Interlisp,
                                                          15
by enclosing the variable and its initial value in a list:   



    (PROG (X (N 0) Y:REAL) ...)


In this example, the variable N will be initialized to the value 0 when the

PROG  is  entered.  The syntax of variable declarations does not permit the

type of a variable and its initial value both to be specified.



4.2. Expressions
4.2. Expressions
4.2. Expressions

     GLISP provides translation of infix expressions of  the  kind  usually

found  in programming languages. It also provides additional operators that

facilitate  list  manipulation  and  other  operations.    Overloading   of

                                                                    ←←←←←←←
operators  for  user-defined  types  is  provided  by  means of the message

facility.

     Expressions may be written directly in-line within function calls,  as

in  (SQRT  X*X  +  Y*Y),  or  they  may  be  written  as  statements within

parentheses, as in (AREA ← PI*R↑2).  Parentheses may be used  for  grouping


←←←←←←←←←←←←←←←

  15
    This feature is available in all Lisp dialects.
                                                                         27



in  the  usual  way.    Operators may be written with or without delimiting
       16                                                                17
                                             ←←←←
                                             ←←←←
                                             ←←←←
                                             must
          ←←←←←← ←←← ←←←     ←←←←←←←←  ←←←←← must ←← ←←←←←←←←← ←← ←←←←←←
spaces,   except for the "-" operator, which must be delimited by spaces.

Expression parsing is done by an operator precedence parser, using the same
                                  18
precedence ordering as in FORTRAN.    The operators that are recognized are
           19
as follows:  


                        ←←
     Assignment     ←   or   :=
     Arithmetic     +   -   *   /   ↑
     Comparison     =   ~=  <>  <   <=   >   >=
     Logical        AND   OR   NOT   ~
     Compound       ←+   ←-   +←   -←


The operator "←" is equivalent to the operator ":="; "~" is  equivalent  to

"NOT", and "~=" is equivalent to "<>".











←←←←←←←←←←←←←←←

  16
                                          ←←←←←←
    However,  numeric  constants  should  always be surrounded by spaces to
avoid misinterpretation by the Lisp reader.
  17
    The "-" operator is required to be delimited by spaces,  since  "-"  is
often  used  as  a  hyphen within variable names.  The "-" operator will be
recognized within "atom" names if the flag GLSEPMINUS is set to T. 

  18
    The precedence of compound operators  is  higher  than  assignment  but
lower  than  that  of  all  other operators.  The operators "↑", "←", "←+",
"+←",  "←-",  and  "-←"  are  right-associative;  all  others   are   left-
associative.

  19
    On  many  terminals,  the  operator  "←" is represented as "underscore"
("shift-minus").  In Maclisp, the operator "/" must be written "//".
                                                                         28


4.2.1. Interpretation of Operators
4.2.1. Interpretation of Operators
4.2.1. Interpretation of Operators

     In  addition  to  the usual interpretation of operators when used with

numeric arguments, some of the operators are interpreted appropriately  for

other Lisp types.


4.2.1.1. Operations on Strings
4.2.1.1. Operations on Strings
4.2.1.1. Operations on Strings

     For  operands of type STRING, the operator "+" performs concatenation.

All of the comparison operators are defined for STRINGs.


4.2.1.2. Operations on Lists
4.2.1.2. Operations on Lists
4.2.1.2. Operations on Lists

     Several operators are defined in such a  way  that  they  perform  set

operations on lists of the form (LISTOF <type>), where <type> is considered

to  be  the element type.  The following table shows the interpretations of

the operators:


     <list> + <list>          Set Union
     <list> - <list>          Set Difference
     <list> * <list>          Set Intersection

     <list>    +  <element>   CONS
     <element> +  <list>      CONS
     <list>    -  <element>   REMOVE
     <element> <= <list>      MEMBER or MEMB
     <list>    >= <element>   MEMBER or MEMB


4.2.1.3. Compound Operators
4.2.1.3. Compound Operators
4.2.1.3. Compound Operators

     Each compound operator performs an operation involving  the  arguments

of  the  operator  and  assigns a value to the left-hand argument; compound

operators are therefore thought of as "destructive change" operators.   The

meaning  of  a  compound  operator  depends  on  the  type of its left-hand

argument, as shown in the following table:
                                                                         29



             ←←←←←←←←     ←←←←←←←←     ←←←←←←       ←←←←←←       ←←←←←←←
             Operator     Mnemonic     NUMBER       LISTOF       BOOLEAN
             ←+
             ←+           ←←←←←←←←←←
             ←+           Accumulate   PLUS         NCONC1       OR
             ←-
             ←-           ←←←←←←
             ←-           Remove       DIFFERENCE   REMOVE       AND NOT
             +←
             +←           ←←←←
             +←           Push         PLUS         PUSH         OR
                                                       20
             -←
             -←           ←←←
             -←           Pop                       POP


     As  an aid in remembering the list operators, the arrow may be thought

of as representing the list, with the head of the arrow being the front  of

the list and the operation (+ or -) appearing where the operation occurs on

the  list.    Thus, for example, ←+ adds an element at the end of the list,

while +← adds an element at the front of the list.

     Each of the compound operators performs an assignment to its left-hand

side; the table above shows  an  abbreviation  of  the  operation  that  is

performed prior to the assignment.  The following examples show the effects

of the operator "←+" on local variables of different types:


     ←←←←           ←←←←←← ←←←←    ←←←←←←←← ←←←←
     Type           Source Code    Compiled Code

     INTEGER        I ←+ 5         (SETQ I (IPLUS I 5))
     BOOLEAN        P ←+ Q         (SETQ P (OR P Q))
     LISTOF         L ←+ ITEM      (SETQ L (NCONC1 L ITEM))


     When  the  compound operators are not specifically defined for a type,

they are interpreted as specifying the operation ("+" or "-")  on  the  two

operands, followed by assignment of the result to the left-hand operand.






←←←←←←←←←←←←←←←

  20
    For  the  Pop  operator,  the arguments are in the reverse of the usual
order, i.e., (TOP -← STACK) will pop the top element off STACK  and  assign
the element removed to TOP.
                                                                         30


4.2.1.4. Assignment
4.2.1.4. Assignment
4.2.1.4. Assignment

     Assignment  of  a  value  to  the  left-hand argument of an assignment

operator is relatively flexible in GLISP.  The following kinds of  operands

are allowed on the left-hand side of an assignment operator:


   1. Variables.

   2. Stored substructures of a structured type.

   3. PROPerties  of a structured type, whenever the interpretation of
      the PROPerty would be a legal left-hand side.

                                                      ←←←←←←←←
   4. Algebraic expressions involving numeric types,  provided    that
      the  expression  ultimately  involves  only  one occurrence of a
                               21
      variable or stored value.  

   5. Standard Lisp data access functions which could be used  to  get
      an item.


For example, consider the following object description for a CIRCLE:  



    (CIRCLE (LIST (START VECTOR) (RADIUS REAL))
      PROP  ((PI            (3.1415926))
             (DIAMETER      (RADIUS*2))
             (CIRCUMFERENCE (PI*DIAMETER))
             (AREA          (PI*RADIUS↑2))) )


Given  this  description,  and  a  CIRCLE    C,  the  following  are  legal

assignments:








←←←←←←←←←←←←←←←

  21
    For example, (X↑2 ← 2.0) is acceptable but (X*X ← 2.0) is  not  because
the variable X occurs twice.
                                                                         31



    (C:RADIUS ← 5.0)
    (C:AREA ← 100.0)
    (C:AREA ← C:AREA*2)
    (C:AREA ←+ 100.0)
    ((CADR C:START) ←+ 3)


4.2.1.5. Self-assignment Operators
4.2.1.5. Self-assignment Operators
4.2.1.5. Self-assignment Operators
     22
       There are some cases in which it would be desirable to let an object

perform  an  assignment of its own value.  For example, the user might want

to define PropertyList as an abstract  data-type,  with  messages  such  as

GETPROP  and  PUTPROP, and use PropertyLists as substructures of other data

types.  However, a message such  as  PUTPROP  may  cause  the  PropertyList

object  to  modify  its  own structure, perhaps even changing its structure

from NIL to a non-NIL value.   If  the  function  that  implements  PUTPROP

performs  a  normal  assignment to its "self" variable, the assignment will

affect only the  local  variable  and  will  not  modify  the  PropertyList

component  of the containing structure.  The purpose of the self-assignment

operators is to allow such modification of the value within the  containing

structure.

     The  self-assignment  operators  are  "←←",  "←←+",  "←+←", and "←←-",

corresponding to the operators "←", "←+",  "+←",  and  "←-",  respectively.

The  meaning  of these operators is that the assignment is performed to the

                                              ←← ←←←←  ←←←←  ←←←  ←←←←←←←←←
object on the left-hand side of the operator, as seen  from  the  structure

←←←←←←←←←← ←←← ←←←←←←
containing the object.

     The  use  of  these  operators  is  highly  restricted.   Any use of a



←←←←←←←←←←←←←←←

  22
    This section may be skipped by the casual user of GLISP.
                                                                         32


self-assignment operator must meet all of the following conditions:


   1. A  self-assignment  operator  can  only be used within a message
      function that is compiled OPEN.

   2. The left-hand side of the assignment must be a  simple  variable
      that is an argument of the function.

   3. The  left-hand-side  variable  must  be given a unique (unusual)
      name to prevent accidental aliasing with a user variable name.


     As an example, the PUTPROP message for a PropertyList  datatype  could

be implemented as follows:



     (PropertyList.PUTPROP (GLAMBDA (PropertyListPUTPROPself prop val)
          (PropertyListPUTPROPself ←←
                    (LISTPUT PropertyListPUTPROPself prop val)) ))




4.3. Control Statements
4.3. Control Statements
4.3. Control Statements

     GLISP   provides   several   Pascal-like   control  statements;  these

statements are bounded  by  parentheses,  so  that  the  keyword  for  each

statement  appears  in  the  position  of  a  Lisp  function  name.  In the

descriptions below, required keywords are shown in boldface,  and  optional

keywords are shown in bold italics.


4.3.1. IF Statement
4.3.1. IF Statement
4.3.1. IF Statement

     The syntax of the IF statement is as follows:


                             ←←←←
                             ←←←←
                             ←←←←
     IF                      THEN
     IF                      THEN
    (IF         <condition > THEN <action  > ... <action  >
                          1              11             1i
        ←←←←←←               ←←←←
        ←←←←←←               ←←←←
        ←←←←←←               ←←←←
        ELSEIF               THEN
        ELSEIF               THEN
        ELSEIF  <condition > THEN <action  > ... <action  >
                          2              21             2j
        ...
        ←←←←
        ←←←←
        ←←←←
        ELSE
        ELSE
        ELSE    <action  > ... <action  >)
                       m1             mk
                                                                         33


Such  a  statement is translated to a COND of the obvious form.  The "THEN"

keyword is  optional,  as  are  the  "ELSEIF"  and  "ELSE"  clauses.    The

<condition>s may be adjectival phrases.


4.3.2. CASE Statement
4.3.2. CASE Statement
4.3.2. CASE Statement

     The  CASE  statement  selects  a  set  of  actions  based on an atomic

selector value; its syntax is:


     CASE                OF
     CASE                OF
    (CASE     <selector> OF
              (<case > <action  > ... <action  >)
                    1         11             1i
              (<case > <action  > ... <action  >)
                    2         21             2j
              ...
              ←←←←
              ←←←←
              ←←←←
              ELSE
              ELSE
              ELSE   <action  > ... <action  >)
                            m1             mk

The  <selector>  is  evaluated  and  is  compared  with  the  given  <case>

specifications.    Each  <case>  specification  is  either a single, atomic

specification  or  a  list  of   atomic   specifications.      All   <case>

specifications  are  assumed  to be quoted.  The "ELSE" clause is optional;

the "ELSE" actions are executed if <selector> does not match any <case>.

            ←←←←
     If the type of the  <selector>  has  a  VALUES  specification,  <case>

specifications  that match the VALUES for that type will be translated into

the corresponding values.


4.3.3. FOR Statement
4.3.3. FOR Statement
4.3.3. FOR Statement

     The  FOR  statement  generates  a  loop  through  a  set  of  elements

(typically a list).  Two syntaxes of the FOR statement are provided:



                    ←←
                    ←←
                    ←←
     FOR EACH       DO
     FOR EACH       DO
    (FOR EACH <set> DO <action > ... <action >)
                              1             n

                             ←←
                             ←←
                             ←←
     FOR            IN       DO
     FOR            IN       DO
    (FOR <variable> IN <set> DO <action > ... <action >)
                                       1             n
                                                                         34


The  keyword "DO" is optional.  In the first form of the FOR statement, the

singular form of the <set> is specified; GLISP will convert the  given  set
                          23
name  to  the plural form.    The <set> may be qualified by an adjective or

predicate phrase in  the  first  form;  the  allowable  syntaxes  for  such

qualifying phrases are shown below:


          WITH
          WITH
    <set> WITH <predicate>
          WHICH IS
          WHICH IS
    <set> WHICH IS <adjective>
          WHO IS
          WHO IS
    <set> WHO IS   <adjective>
          THAT IS
          THAT IS
    <set> THAT IS  <adjective>


The  <predicate> and <adjective> phrases may be combined with AND, OR, NOT,

and grouping parentheses.  These phrases may be followed  by  a  qualifying

phrase of the form:


    WHEN
    WHEN
    WHEN <expression>


The  "WHEN"  expression  is  ANDed with the other qualifying expressions to

determine when the loop body will be executed.

     Within the FOR loop, the current member of the  <set>  that  is  being

                                        ←←←←←←←
examined  is  automatically  put  into  context  at  the  highest  level of

priority.  For  example,  suppose  that  the  current  context  contains  a

substructure whose description is:


    (PLUMBERS (LISTOF EMPLOYEE))


Assuming  that EMPLOYEE contains the appropriate definitions, the following


←←←←←←←←←←←←←←←

  23
    For names with irregular plurals, the plural form should be put on  the
property  list  of  the singular form under the property name PLURAL, e.g.,
(PUTPROP 'MAN 'PLURAL 'MEN).
                                                                         35


FOR loop could be written:


    (FOR EACH PLUMBER WHO IS NOT A TRAINEE DO SALARY ←+ 1.50)


     To  simplify  the  collection  of  features of a group of objects, the

<action>s in the FOR loop may be replaced by the CLISP-like construct:


                COLLECT
                COLLECT
          ( ... COLLECT <form>)


4.3.4. WHILE Statement
4.3.4. WHILE Statement
4.3.4. WHILE Statement

     The format of the WHILE statement is as follows:



                          ←←
                          ←←
                          ←←
        WHILE             DO
        WHILE             DO
       (WHILE <condition> DO <action > ... <action >)
                                    1             n



The actions <action > through <action > are executed repeatedly as long  as
                   1                 n
                                      DO
                                      DO
<condition>  is  true.   The keyword "DO" may be omitted.  The value of the

expression is NIL.


4.3.5. REPEAT Statement
4.3.5. REPEAT Statement
4.3.5. REPEAT Statement

     The format of the REPEAT statement is as follows:



        REPEAT                         UNTIL
        REPEAT                         UNTIL
       (REPEAT <action > ... <action > UNTIL <condition>)
                      1             n



The actions <action > through <action > are repeated (always at least once)
                   1                 n
until <condition> is true.  The value  of  the  expression  is  NIL.    The

        UNTIL
        UNTIL
keyword UNTIL is required.
                                                                         36


4.4. Definite Reference to Particular Objects
4.4. Definite Reference to Particular Objects
4.4. Definite Reference to Particular Objects

     In  order  to  simplify  reference to particular member(s) of a group,

definite reference may be used.  Such an expression is  written  using  the

      THE                                                 THOSE
      THE                                                 THOSE
word  THE  followed by the singular form of the group, or THOSE followed by

the plural form of the group, and qualifying phrases (as described for  the

FOR
FOR
FOR statement).  The following examples illustrate these expressions.


       (THE SLOT WITH SLOTNAME = NAME)
       (THOSE EMPLOYEES WITH JOBTITLE = 'ELECTRICIAN)


                THE
                THE
The  value  of  THE  is  a single object (or NIL if no object satisfies the

                       THOSE
                       THOSE
specified conditions); THOSE produces a list of all objects satisfying  the
           24
conditions.  
























←←←←←←←←←←←←←←←

  24
    In  general,  nested loops are optimized so that intermediate lists are
not actually constructed.  Therefore,  the  use  of  nested  THE  or  THOSE
statements is not inefficient.
                                                                         37


                                 CHAPTER 5
                                 CHAPTER 5
                                 CHAPTER 5

                                 MESSAGES
                                 MESSAGES
                                 MESSAGES

                           ←←←←←←←
     GLISP  supports  the  message  metaphor,  which  has  its roots in the

                                                            ←←←←←← ←←←←←←←←
languages SIMULA and SMALLTALK.  These  languages  provide  object-centered

←←←←←←←←←←←
programming,  in which objects are thought of as being active entities that

                                  ←←←←←←←←
communicate by sending each other messages.   The  internal  structures  of

objects  are  hidden;  a  program  that  wishes to access "variables" of an

object does so by sending messages to  the  object  requesting  the  access
                                 25
                                              ←←←←←←←←←
desired.    Each  object contains   a list of selectors, which identify the

                                                    ←←←←←←←
messages to which  the  object  can  respond.    A  message  specifies  the

destination  object,  the  selector,  and any arguments associated with the

message.  When a message is executed at run time, the selector is looked up

for the destination object; associated with the selector  is  a  procedure,

which  is executed with the destination object and message arguments as its

arguments.

     GLISP treats  reference  to  properties,  adjectives,  and  predicates

associated  with  an  object  similarly to the way it treats messages.  The

                                                     ←←←←←←←←←
compiler is able to perform much of the  lookup  of  selectors  at  compile

time,  which results in efficient code while maintaining the flexibility of

the message metaphor.  Messages can be defined in  such  a  way  that  they

compile  open, compile as function calls to the function that is associated

with the selector, or compile as messages to be interpreted at run time.

                      ←←←←←←←
     The sending of a message in GLISP is  specified  using  the  following



←←←←←←←←←←←←←←←

  25
    typically by inheritance from some parent in a class hierarchy
                                                                         38


syntax:


    (SEND                                      )
    (SEND                                      )
    (SEND <object> <selector> <arg > ... <arg >)
                                  1          n

                                       ←
                                       ←
The keyword "SEND" may be replaced by "←".  The <selector> is assumed to be

quoted.   Zero or more arguments may be specified; the arguments other than

<selector> are  evaluated.    <object>  is  evaluated;  if  <object>  is  a

non-atomic  expression,  it  must  be  enclosed  in  at  least  one  set of

parentheses, so that the <selector> will always be the third element of the

list.



5.1. Compilation of Messages
5.1. Compilation of Messages
5.1. Compilation of Messages

     When GLISP encounters a message statement, it looks up the  <selector>

in  the  MSG  definition  of the type of the object to which the message is
                                         26
sent or in one of the SUPERS of the type.    Each <selector> is paired with

the appropriate <response> to the message.  Code is compiled  depending  on
                                                                      27
the form of the <response> associated with the <selector>, as follows:  


   1. If  the <response> is an atom, that atom is taken as the name of
      a function that is to be called in response to the message.  The
      code that is compiled is a direct call to this function,


          (<response> <object> <arg > ... <arg >)
                                   1          n

←←←←←←←←←←←←←←←

  26
    If an appropriate representation language is provided,  the  <selector>
and  its  associated <response> may be inherited from a parent class in the
class hierarchy of the representation language.

  27
    If the type of the destination object is unknown, or if the  <selector>
cannot  be  found,  GLISP compiles the (SEND ...) statement as if it were a
normal function call.
                                                                         39


      For  example,  if  the message list for the type of the variable
      OBJ contained the entry:



          (EDIT         EDITV)



      the source code (SEND OBJ EDIT) would generate the  object  code
      (EDITV OBJ).

   2. If  the  <response>  is  a  list,  the  contents of the list are
      recursively compiled in-line as GLISP code, with the name "self"
      artificially "bound" to the <object> to which  the  message  was
      sent.    Because  the compilation is recursive, a message may be
      defined  in  terms  of   other   messages,   substructures,   or
                                                               28
      properties,  which may themselves be defined as messages.    The
      outer pair of parentheses of the <response> serves only to bound
      its contents; thus, if the <response> is a  function  call,  the
      function   call  must  be  enclosed  in  an  additional  set  of
      parentheses.  For example, suppose that the type of the variable
      J contained the PROPerty entry:



          (SUCCESSOR    (self + 1))



      The source code J:SUCCESSOR would generate the object code (ADD1
      J).   The  object  description  for  a  VECTOR,  given  earlier,
      contains the PROPerty entry:



          (MAGNITUDE    ((SQRT X*X + Y*Y)))



      This  example  illustrates  a  call  to  a  function, SQRT, with
      arguments containing definite references to X and Y,  which  are
      defined  as  stored  fields  of  the  VECTOR.    Note that since
      MAGNITUDE is defined by a function  call,  an  "extra"  pair  of
      parentheses  is required around the function call to distinguish


←←←←←←←←←←←←←←←

  28
    Such recursive definitions must, of course, be acyclic.
                                                                         40


      it from in-line code.  Given this definition and a VECTOR object
      V, the source code V:MAGNITUDE would generate the object code:



          (SQRT (IPLUS (ITIMES (CAR V) (CAR V))
                       (ITIMES (CADR V) (CADR V))))



     The  user  can  determine  whether  a  message is to be compiled open,

compiled as a function call, or  compiled  as  a  message  that  is  to  be

executed  at  run  time.    When  a  GLISP  expression  is  specified  as a

<response>, the <response> is always compiled open; open compilation can be

requested by using the OPEN property when  the  <response>  is  a  function

name.  Open compilation operates like macro expansion; since the "macro" is

a  GLISP  expression, it is easy to define messages and properties in terms

of other messages and  properties.    The  combined  capabilities  of  open

compilation,  message  inheritance,  conditional  compilation, and flexible

assignment provide a great deal of power.   The  ability  to  use  definite

reference  in GLISP makes the definition and use of the "macros" simple and

natural.



5.2. Compilation of Properties and Adjectives
5.2. Compilation of Properties and Adjectives
5.2. Compilation of Properties and Adjectives

     Properties, adjectives, and ISA-adjectives are compiled  in  the  same

way  as messages.  Since the syntax of the use of properties and adjectives

does not permit specification of any arguments, the only argument available

to the code or function that implements the <response> for  a  property  or

adjective  is  the  self  argument,  which  denotes the object to which the

property or adjective applies.  A <response> that is  written  directly  as
                                                                         41


                                             29
GLISP  code  may  use the name self directly,   as in the SUCCESSOR example

above; a function that is specified as the <response> will be  called  with

the self object as its single argument.



5.3. Declarations for Message Compilation
5.3. Declarations for Message Compilation
5.3. Declarations for Message Compilation

     Declarations  that  affect  compilation  of  messages,  adjectives, or

properties may be specified following the <response> for a  given  message;

such    declarations    are    in    (Interlisp)    property-list   format,

<prop > <value >  ...  <prop > <value >.  The following declarations may be
     1        1             n        n
specified:


      RESULT
      RESULT
   1. RESULT <type>
                                     ←←←←
      This declaration specifies the type of the result of the message
      or other property.  Specification  of  result  types  helps  the
      compiler  to perform type inference, thus reducing the number of
      type declarations needed in user programs.  The RESULT type  for
      simple  GLISP  expressions will be inferred by the compiler; the
      RESULT declaration should be used if the <response> is a complex
                                          30
      GLISP expression or a function name.    

      OPEN  T
      OPEN  T
   2. OPEN  T
      This declaration specifies that the function that  is  specified
      as  the  <response> is to be compiled open at each reference.  A
      <response> that is a list of GLISP code is always compiled open;
      however, such a <response> can have only the self argument.   If
      it  is  desired  to  compile  open a message <response> that has
      arguments besides self,  the  <response>  must  be  coded  as  a
      function   (in  order  to  bind  the  arguments)  and  the  OPEN
      declaration must be used.  Functions that are compiled open  may


←←←←←←←←←←←←←←←

  29
    The  name   self  is "declared" by the compiler and does not have to be
specified in the structure description.

  30
    Alternatively, the result of a function may be specified by the  RESULT
declaration within the function itself.
                                                                         42


      not be recursive via any chain of open-compiled functions.

      MESSAGE  T
      MESSAGE  T
   3. MESSAGE  T
      This  declaration  specifies  that  a run-time message should be
      generated for messages with this <selector> sent to  objects  of
      this  class.    Typically, such a declaration would be used in a
      higher-level class whose subclasses have different responses  to
      the same message <selector>.

      ARGTYPES  (<type > ... <type >)
      ARGTYPES  (<type > ... <type >)
   4. ARGTYPES  (<type > ... <type >)
                      2           n
                      2           n
                      2           n
      This  declaration  specifies  the  argument  types for a Message
      entry.  The message entry will only be effective  for  arguments
                                         31
      which  match  the  specified  types  .    The type of the object
      itself is not included in the ARGTYPES list.  The ARGTYPES  list
      allows  different  interpretations  of the same message selector
      depending on the argument types at compile time.   For  example,
      the      interpretations      of     <vector> * <vector>     and
      <vector> * <number> could be different.

      SPECIALIZE T
      SPECIALIZE T
   5. SPECIALIZE T
      This declaration is used where a property is  implemented  by  a
      named  closed generic function.  If the property is inherited by
      a subclass of the class in which it is defined, a version of the
      function that is specialized for the particular  argument  types
      involved will be created and stored with the subclass.



5.4. Operator Overloading
5.4. Operator Overloading
5.4. Operator Overloading

     GLISP provides operator overloading for user-defined objects using the

                                                                ←←←←←←←←
message  facility.  If an arithmetic operator is defined as the selector of

a message for a user data-type,  an  arithmetic  subexpression  using  that

operator  will be compiled as if it were a message call with two arguments.

For example, the type  VECTOR  might  have  the  declaration  and  function

definitions below:




←←←←←←←←←←←←←←←

  31
    An  argument  matches  a  type if it is of the specified type or if its
type has the specified type as a SUPER.
                                                                         43



    (GLISPOBJECTS
       (VECTOR  (CONS (X INTEGER) (Y INTEGER))
          MSG  ((+  VECTORPLUS OPEN T)
                (←+ VECTORINCR OPEN T)) )    )

    (DEFINEQ

       (VECTORPLUS (GLAMBDA (U,V:VECTOR)
           (A VECTOR WITH X = U:X + V:X , Y = U:Y + V:Y) ))

       (VECTORINCR (GLAMBDA (U,V:VECTOR)
           (U:X ←+ V:X)
           (U:Y ←+ V:Y) ))    )



With  these  definitions, an expression involving the operators "+" or "←+"

will be compiled by open compilation of the respective functions.

     The compound operators ("←+", "+←",  "←-",  "-←")  are  conventionally

thought  of  as  "destructive  replacement" operators; thus, the expression

(U ← U + V) will create a new VECTOR structure and assign the new structure

to U, while the expression (U ←+ V) will modify the existing  structure  U,

given  the  definitions  above.    The  convention  of letting the compound

operators specify "destructive replacement" allows the user to specify both

the destructive  and  nondestructive  cases.    However,  if  the  compound

operators  are  not overloaded but the arithmetic operators "+" and "-" are

overloaded, the compound operators are compiled using  the  definitions  of

"+"  for  "←+"  and "+←", and "-" for "←-" and "-←".  Thus, if only the "+"

operator were overloaded for  VECTOR,  the  expression  (U ←+ V)  would  be

compiled as if it were (U ← U + V).
                                                                         44


5.5. Run-time Interpretation of Messages
5.5. Run-time Interpretation of Messages
5.5. Run-time Interpretation of Messages

     In  some  cases,  the  type  of  the  object that will receive a given

message is not known at compile time; in such cases, the  message  must  be

executed  interpretively,  at run time.  Interpretive execution is provided

for all types of GLISP messages.

     An interpretive message call (i.e., a call to the  function  SEND)  is

generated  by  the  GLISP compiler in response to a message call in a GLISP

program when the  specified  message  selector  cannot  be  found  for  the

declared  type of the object receiving the message or when the MESSAGE flag

is set for that selector.  Alternatively, a call to  SEND  may  be  entered

interactively  by  the  user or may be contained in a function that has not

been compiled by GLISP.

     SEND messages are interpreted for those objects that  are  represented

as  one  of  the  OBJECT  types; variants of SEND are provided for use with

other data types.  The <selector> of the message is looked up  in  the  MSG

declarations  of  the  CLASS;  if  it is not found there, the SUPERS of the

CLASS are examined  (depth  first)  until  the  selector  is  found.    The

<response>  associated  with  the  <selector>  is  then  examined.   If the

<response> is a function name, that function  is  simply  called  with  the
                     32
specified  arguments.    If  the  <response>  is  a  GLISP  expression, the

expression is compiled as a LAMBDA form and cached for future use.

     For convenience of interactive use, the interactive SEND function will

accept the names of PROP, ADJ, and ISA entries or names of substructures in


←←←←←←←←←←←←←←←

  32
    The object to which the message is sent is always inserted as the first
argument, followed by the other arguments specified in the message call.
                                                                         45


                                33
addition  to  message  selectors  .   While acceptably fast for interactive

use, this feature is not recommended  for  use  within  functions.    If  a

PROPerty  or  substructure  name is suffixed with a colon and followed by a

value, the specified value will be "stored" into  the  specified  property.

For  example,  if DC is a DCIRCLE object, the message (SEND DC AREA: 100.0)

may be used to set the AREA of DC to the value 100.

     Several  variants  of  the  SEND  function  are  provided   to   allow

specification  of the property type (PROP, ADJ, ISA, MSG, STR) and to allow

messages to be used with data objects  which  are  not  defined  as  Object

types:



    (SEND      <object>         <selector>            <args>)

    (SENDC     <object> <class> <selector>            <args>)

    (SENDPROP  <object>         <selector> <proptype> <args>)

    (SENDPROPC <object> <class> <selector> <proptype> <args>)

    (GLSENDB   <object> <class> <selector> <proptype> <args>)



GLSENDB  evaluates  all of its arguments; the other forms all call GLSENDB.

The SEND forms do not evaluate <class>, <selector>,  or  <proptype>  (where

<proptype>  is  PROP, ADJ, ISA, MSG, or STR).  <object> and <args>, if any,

are evaluated.






←←←←←←←←←←←←←←←

  33
    The order of searching for names is MSG, STR, PROP, ADJ, ISA.
                                                                         46


                                 CHAPTER 6
                                 CHAPTER 6
                                 CHAPTER 6

                        CONTEXT RULES AND REFERENCE
                        CONTEXT RULES AND REFERENCE
                        CONTEXT RULES AND REFERENCE

     The  ability to use definite reference to features of objects that are

   ←←←←←←←
in context is the key to much of GLISP's power.  At the same time, definite

reference introduces the possibility of ambiguity; that is, there could  be

more  than  one object in context that has a feature with a specified name.

In this section, guidelines are presented for the use of definite reference

to allow the user to avoid ambiguity.



6.1. Organization of Context
6.1. Organization of Context
6.1. Organization of Context

     The context maintained by the compiler is organized in levels, each of

which may have multiple  entries;  the  sequence  of  levels  is  a  stack.

Searching of the context proceeds from the top (nearest) level of the stack

to  the bottom (farthest) level.  The bottom level of the stack is composed

of the LAMBDA variables of the function being compiled.    New  levels  are

added to the context in the following cases:


   1. When  a  PROG is compiled.  (The PROG variables are added to the
      new level.)

             For
             For
   2. When a For loop is compiled.  (The "loop index" variable,  which
      may  be  either a user variable or a compiler variable, is added
      to the new level, so that it is in context during the loop.)

             While
             While
   3. When a While loop is compiled.

                              If
                              If
   4. When a new clause of an If statement is compiled.


     When a message, property, or adjective is compiled,  that  compilation

                 ←←←
takes place in a new context consisting only of the self argument and other

message arguments.
                                                                         47


6.2. Rules for Using Definite Reference
6.2. Rules for Using Definite Reference
6.2. Rules for Using Definite Reference

     The  possibility  of  referential  ambiguity  is  easily controlled in

practice.  First, it should be noted that the traditional methods of unique

naming and complete path specification ("Pascal style") are  available  and

should  be  used  whenever  there is any possibility of ambiguity.  Second,

there are several cases that are guaranteed to be unambiguous:


   1. In compiling GLISP code that implements a message, property,  or
      adjective,  only  the  self  argument  is  in context initially;
      definite reference to any substructure or property of the object
                               34
      is therefore unambiguous.    

               For
               For
   2. Within a For loop, the loop variable is  the  closest  thing  in
      context.

   3. In  many  cases,  a  function will have only a single structured
      argument; in such cases, definite reference is unambiguous.


If "Pascal" syntax (or  the  equivalent  English-like  form)  is  used  for

references other than the above cases, no ambiguities will occur.



6.3. Type Inference
6.3. Type Inference
6.3. Type Inference

     To  interpret definite references to features of objects, the compiler

              ←←←←←
must know the types of the objects.  However, explicit  type  specification

can  be burdensome and makes it difficult to change types without rewriting

existing type declarations.  The GLISP compiler performs type inference  in

many cases, thus relieving the programmer of the burden of specifying types


←←←←←←←←←←←←←←←

  34
    This  holds  true  unless  there  are  duplicated  names  in the object
definition.  However, if the same name is used as both a  property  and  an
adjective,  for  example, it is not considered a duplicate since properties
and adjectives are specified by different source-language constructs.
                                                                         48


explicitly.    The  following rules allow the programmer to know when types

will be inferred by the compiler.


   1. Whenever a variable is set to a value whose type is  known,  the
      type  of the variable is inferred to be the type of the value to
      which it was set.

   2. If a variable whose initial type was NIL (e.g., an untyped  PROG
      variable)  appears  on  the left-hand side of the "←+" operator,
      its type is inferred to be (LISTOF <type>), where <type> is  the
      type of the right-hand side of the "←+" expression.

   3. Whenever a substructure of a structured object is retrieved, the
      type of the substructure is retrieved also.

   4. Types of infix expressions are inferred.

   5. Types of properties, adjectives, and messages are inferred if:


         a. The <response> is GLISP code whose type can be inferred;

         b. The  <response>  has  a RESULT declaration associated with
            it;

         c. The <response> is a function whose definition  includes  a
            RESULT  declaration,  or  whose  property  list contains a
            GLRESULTTYPE declaration.


                                           For
                                           For
   6. The type of the "loop variable" in a For loop is inferred and is
      added to a new level of context by the compiler.

            If
            If
   7. If an If statement tests the type of a  variable  using  a  self
      adjective,  the  variable  is inferred to be of that type if the
      test is satisfied.  Similar type inference is performed  if  the
                                                                 While
                                                                 While
      test  of  the  type  of the variable is the condition of a While
      statement.

   8. When possible, GLISP infers the  type  of  the  function  it  is
      compiling  and  adds the type of the result to the property list
      of the function name under the indicator GLRESULTTYPE.

   9. The types returned by many standard Lisp functions are known  by
      the compiler.
                                                                         49


                                 CHAPTER 7
                                 CHAPTER 7
                                 CHAPTER 7

               GLISP AND KNOWLEDGE REPRESENTATION LANGUAGES
               GLISP AND KNOWLEDGE REPRESENTATION LANGUAGES
               GLISP AND KNOWLEDGE REPRESENTATION LANGUAGES

                                     ←←←←←←  ←←←←←←←←
     GLISP  provides  a  convenient  access  language  that  allows uniform

specification of access to objects, without regard to the way in which  the

objects   are   actually  stored;  in  addition,  GLISP  provides  a  basic

←←←←←←←←←←←←←← ←←←←←←←←
representation language, in which the structures and properties of  objects

can  be  declared.    Artificial Intelligence has given rise to a number of

powerful  representation  languages;  these  languages  provide  power   in

                                                                      ←←←←←
describing large numbers of object classes by allowing hierarchies of class

descriptions,  in  which  instances  of  classes can inherit properties and

                                     ←←←←←← ←←←←←←←←←
procedures from parent classes.  The access languages  provided  for  these

representation  languages,  however, have typically been rudimentary, often

being no more than variations of Lisp's GETPROP and PUTPROP.  In  addition,

by  performing inheritance of procedures and data values at run time, these

representation languages have often been computationally costly.

     Facilities are provided  for  interfacing  GLISP  with  representation

languages  of  the  user's  choice.    When  this is done, GLISP provides a

convenient  and  uniform  language  both  for  accessing  objects  in   the

representation language and for accessing Lisp objects.  In addition, GLISP

can   greatly   improve   the   efficiency  of  programs  that  access  the

representations by performing lookup of procedures and data  in  the  class

           ←←  ←←←←←←← ←←←←                                              ←←
hierarchy  at  compile time.  Finally, a Lisp structure can be specified as

←←← ←←←  ←←  ←←←←←←←←←←←←
the way  of  implementing  instances  of  a  class  in  the  representation

language,  so  that  while  the  objects in such a class appear the same as

other objects in the representation language and are accessed in  the  same

way,  they  are  actually implemented as Lisp objects that are efficient in
                                                                         50


both time and storage.

     A method for declaring an interface between GLISP and a representation

                                                             ←←←←←
language  is  provided.    With  such  an  interface,  each  class  in  the

                                                 ←←←←
representation language is acceptable as a GLISP type.   When  the  program

that is being compiled specifies an access to an object that is known to be

a  member  of  some  class,  the  interface  module  for the representation

language is called to generate code to perform the access.   The  interface

module  can  perform  inheritance  within  the class hierarchy; it can call

GLISP compiler functions to compile code for subexpressions.    Properties,

adjectives,  and messages in GLISP format can be added to class definitions

and can be inherited by subclasses at compile time.  In an  object-centered

representation  language  or  other  representation  language  that  relies

heavily on procedural inheritance, substantial  improvements  in  execution

speed  can be achieved by performing the inheritance lookup at compile time

and compiling direct procedure  calls  to  inherited  procedures  when  the

procedures  are  static  and  the  type  of  the  object  that inherits the

procedure is known at compile time.

     Specifications for an interface module for GLISP are  contained  in  a
                   35
separate  document.    To  date,  GLISP has been interfaced to the GIRL [2]

representation language and to LOOPS [1].









←←←←←←←←←←←←←←←

  35
    to be written
                                                                         51


                                 CHAPTER 8
                                 CHAPTER 8
                                 CHAPTER 8

                         OBTAINING AND USING GLISP
                         OBTAINING AND USING GLISP
                         OBTAINING AND USING GLISP

     GLISP  and  its  documentation  are  available free of charge over the

ARPANET.  The GLISP files are contained in the  directory  <GLISP>  on  the

host computer SUMEX-AIM; SUMEX will accept the login-name "ANONYMOUS GUEST"

for transferring files with FTP.



8.1. Documentation
8.1. Documentation
8.1. Documentation

     This  user's  manual, in line printer format, is contained in the file

GLUSER.LPT.  The Scribe source file is GLUSER.MSS.  Printed copies of  this

manual  can  be ordered from the Publications Coordinator, Computer Science

Department, Stanford University, Stanford, CA 94305, as technical report 

STAN-CS-82-895 ($3.15 prepaid); the printed version may not  be  as  up  to

date as the on-line version.



8.2. Compiler Files
8.2. Compiler Files
8.2. Compiler Files

     There  are  two files provided, GLISP (the compiler itself) and GLTEST

(a file of examples).  The files for the different Lisp dialects are:



     Interlisp:     GLISP.LSP and GLTEST.LSP

     Maclisp:       GLISP.MAC and GLTEST.MAC

     UCI Lisp:      GLISP.UCI and GLTEST.UCI

     ELISP:         the UCI version plus ELISP.FIX

     Franz Lisp:    GLISP.FRANZ and GLTEST.FRANZ

     PSL:           GLISP.PSL and GLTEST.PSL
                                                                         52


These files are updated periodically as new features are added and bugs are

fixed.  The file GLISP.NEWS contains news about recent additions.



8.3. Getting Started
8.3. Getting Started
8.3. Getting Started

     Useful functions for invoking GLISP are:


     (GLCC 'FN)     Compile FN.

     (GLCP 'FN)     Compile FN and prettyprint result.

     (GLP 'FN)      Prettyprint GLISP-compiled version of FN.

     (GLED 'NAME)   Edit the property list of NAME.

     (GLEDF 'FN)    Edit the original (GLISP) definition of FN.
                    (The original definition is saved under the property
                    "GLORIGINALEXPR" when the function is compiled,
                    and the compiled version replaces the function
                    definition.)

     (GLEDS 'STR)   Edit the structure declarations of STR.


The editing functions call the "BBN/Interlisp" structure editor.

     To  try  out  GLISP,  load  GLISP  and the GLTEST file and use GLCP to

compile the functions CURRENTDATE, GIVE-RAISE, MGO-TEST, TESTFN2, DRAWRECT,

PRINTLEAVES, GROWCIRCLE, and SQUASH.  To run  compiled  functions  on  test

data, do:


    (GIVE-RAISE 'COMPANY1)
    (PRINTLEAVES '(((A (B (C D (E (G H (I J (K))))))))))
    (GROWCIRCLE MYCIRCLE)
                                                                         53


8.4. Reserved Words and Characters
8.4. Reserved Words and Characters
8.4. Reserved Words and Characters

     GLISP  contains  ordinary  Lisp  as  a sublanguage.  However, to avoid

having code that was intended as "ordinary Lisp" interpreted as GLISP code,

it is necessary to follow certain conventions when writing "ordinary  Lisp"

code.


8.4.1. Reserved Characters
8.4.1. Reserved Characters
8.4.1. Reserved Characters

     The  colon  and the characters that represent the arithmetic operators

should not be used within atom names, since GLISP splits apart "atoms" that

contain operators.  The set of characters to be avoided within  atom  names

is:  



         +  *  /  ↑  ←  ~  =  <  >  :  '  ,



                                                                         36
                              -
                              -
The   character   "minus"   ("-")   is   permitted   within  atom  names;

                               -
                     ←←←←←←←←  -
correspondingly, the operator "-" must appear with a blank on each side.

     Some GLISP constructs permit (but do not require) use of the character

"comma" (","); since the comma is used as a "backquote" character  in  some

Lisp  dialects,  the user may wish to avoid its use.  In Lisp dialects that

use the comma as a backquote character, all commas  must  be  "escaped"  or

"slashified"; this makes GLISP code containing commas less portable.







←←←←←←←←←←←←←←←

  36
    unless the flag GLSEPMINUS is set
                                                                         54


8.4.2. Reserved Function Names
8.4.2. Reserved Function Names
8.4.2. Reserved Function Names

     Most  function,  variable,  and property used within GLISP names begin

with "GL" to avoid conflict with user names.  Those "function"  names  that

are used in GLISP constructs or in interpretive functions should be avoided

as names of user functions.  This set includes the following names:  



         A                  IF                 THE
         AN                 REPEAT             THOSE
         CASE               SEND               WHILE
         FOR                SENDPROP



8.4.3. Other Reserved Names
8.4.3. Other Reserved Names
8.4.3. Other Reserved Names

     Words  that  are  used  within  GLISP  constructs should be avoided as

variable names.  This set of names includes:  



         A                  ELSEIF             THAT
         AN                 IN                 THEN
         AND                IS                 UNTIL
         COLLECT            NOT                WHEN
         DO                 OF                 WHICH
         EACH               OR                 WHO
         ELSE               THE                WITH




8.5. Lisp Dialect Idiosyncrasies
8.5. Lisp Dialect Idiosyncrasies
8.5. Lisp Dialect Idiosyncrasies

     GLISP code passes through the Lisp reader before it is seen by  GLISP;

some  Lisp  readers  produce strange results for "atom" names which contain

special characters.  For this reason, operators in expressions may need  to

be  set  off  from  operands  by  blanks; the operator "-" should always be

surrounded by blanks, and the operator "+" should be separated from numbers

by blanks.  In most  Lisp  dialects,  floating-point  constants  should  be
                                                                         55


surrounded by blanks.


8.5.1. Interlisp
8.5.1. Interlisp
8.5.1. Interlisp

     GLISP  functions are written using GLAMBDA rather than LAMBDA to cause

automatic compilation.  GLISP declarations are  integrated  with  the  file

package.    The  system  flag  NORMALCOMMENTSFLG should be T when the GLISP

compiler is read in.

     An interactive display inspector and editor for GLISP  data,  GEV [3],

is available for use on Xerox Lisp machines.


8.5.2. UCI Lisp
8.5.2. UCI Lisp
8.5.2. UCI Lisp

     GLISP functions are defined using the defining function DG; DG sets up

a  macro definition which causes automatic GLISP compilation the first time

a function is called.  The following command is needed in UCI  Lisp  before

loading to make room for GLISP:  


    (REALLOC 3000 1000 1000 1000 35000)


                                                                 ~
                                                                 ~
The  compiler  file  modifies  the  syntax  of  the  character  "~"  to  be

"alphabetic" so it can be used as a GLISP operator.  The character "/" must

be "slashified" to "//".


8.5.3. ELISP
8.5.3. ELISP
8.5.3. ELISP

     GLISP functions are defined using the defining function DG; DG sets up

a macro definition which causes automatic GLISP compilation the first  time

a  function  is called.  For ELISP, the UCI Lisp version of the compiler is

used, together with a small compatibility file.  The REALLOC command is not

needed for ELISP.  The characters "/" and "," must be "slashified" to  "//"

and "/,", respectively.
                                                                         56


8.5.4. Maclisp
8.5.4. Maclisp
8.5.4. Maclisp

     In  Maclisp,  the  characters "/" and "," must be "slashified" to "//"

and "/,", respectively.  GLISP functions are  defined  using  the  function

"gldefun";  this  sets up a macro definition that causes the function to be

compiled automatically the first time it is called after being  defined  or

edited.


8.5.5. Franz Lisp
8.5.5. Franz Lisp
8.5.5. Franz Lisp

     In  Franz  Lisp,  GLISP functions are defined using glambda instead of

lambda; this causes automatic compilation the  first  time  a  function  is

called.   The defining function gldefun sets up a function definition using

glambda.  The character ","  and  the  operators  "+←"  and  "-←"  must  be

"slashified"  to "\,", "+\←", and "-\←", respectively.  If the "CMU Editor"

is to be used, something should be edited to cause the editor files  to  be
                              37
loaded before GLISP is loaded.  

     The Franz Lisp version of GLISP has been tested on Opus 38 Franz Lisp;

users  with  earlier  versions  of Franz Lisp might encounter difficulties.

The file FRANZ.FIX contains some function definitions for use with  earlier
                   38
Franz Lisp versions  .






←←←←←←←←←←←←←←←

  37
    Some versions of the "CMU editor" contain function definitions that may
conflict  with  those  of  GLISP;  if the editor is loaded first, the GLISP
versions override.

  38
    These functions were written  by  Ken  Anderson  of  Bolt  Beranek  and
Newman.
                                                                         57


8.5.6. Portable Standard Lisp
8.5.6. Portable Standard Lisp
8.5.6. Portable Standard Lisp

     In  Portable  Standard Lisp ("PSL"), GLISP functions are defined using

the function DG; this sets up a macro  definition  which  causes  automatic

compilation  the first time a function is called.  The PSL version of GLISP

has been tested on  the  DEC-2060,  VAX-11/780,  and  Hewlett-Packard  9836

(Motorola 68000) computers.



8.6. Bug Reports and Mailing List
8.6. Bug Reports and Mailing List
8.6. Bug Reports and Mailing List

     To  get  on  the  GLISP  mailing  list or to report bugs, send mail to

NOVAK@SUMEX-AIM.  Bug reports are  appreciated;  we  will  attempt  to  fix

reported bugs.
                                                                         58


                                 CHAPTER 9
                                 CHAPTER 9
                                 CHAPTER 9

                                GLISP HACKS
                                GLISP HACKS
                                GLISP HACKS

     This  chapter  discusses some ways of doing things in GLISP that might

not be entirely obvious at first glance.



9.1. Overloading Basic Types
9.1. Overloading Basic Types
9.1. Overloading Basic Types

     GLISP  provides  the  ability  to  define  properties  of   structures

described  in the structure description language; since the elementary Lisp

types are structures in this language, objects whose storage representation

is an elementary type can be  "overloaded"  by  specifying  properties  and

operators  for  them.    The  following examples illustrate how this can be

done.
                                                                         59



    (GLDEFSTRQ


    (ArithmeticOperator  (self ATOM)

       PROP ((Precedence OperatorPrecedenceFn  RESULT INTEGER)
             (PrintForm  ((GETPROP self 'PRINTFORM) or self)) )

       MSG  ((PRIN1      ((PRIN1 the PrintForm)))) )


    (IntegerMod7         (self INTEGER)

       PROP ((Modulus    (7))
             (Inverse    ((If self is ZERO then 0
                                else (Modulus - self))) ))

       ADJ  ((Even       ((ZEROP (LOGAND self 1))))
             (Odd        (NOT Even)))

       ISA  ((Prime      PrimeTestFn))

       MSG  ((+          IMod7Plus  OPEN T  RESULT IntegerMod7)
             (←          IMod7Store OPEN T  RESULT IntegerMod7)) )

    )
    (DEFINEQ

    (IMod7Store  (GLAMBDA (LHS:IntegerMod7 RHS:INTEGER)
             (LHS:self ←← (IREMAINDER RHS Modulus)) ))

    (IMod7Plus   (GLAMBDA (X,Y:IntegerMod7)
             (IREMAINDER (X:self + Y:self) X:Modulus) ))
    )



A  few  subtleties of the function IMod7Store are worth noting.  First, the

left-hand-side expression used in storing the  result  is  LHS:self  rather

than  simply  LHS.    LHS and LHS:self, of course, refer to the same actual

                        ←←←←
structure; however, the type of LHS  is  IntegerMod7,  while  the  type  of

LHS:self is INTEGER.  If LHS were used on the left-hand side, since the " ←

"  operator is overloaded for IntegerMod7, the function IMod7Store would be

invoked again to perform its own function; since the function  is  compiled
                                                                         60


OPEN,  this  would  be  an  infinite  loop.   A second subtlety is that the

assignment to LHS:self must use the self-assignment operator, " ←← ", since

it is  desired  to  perform  assignment  as  seen  "outside"  the  function

IMod7Store,  that  is,  in the environment in which the original assignment

operation was specified.



9.2. Disjunctive Types
9.2. Disjunctive Types
9.2. Disjunctive Types

     Lisp programming often  involves  objects  that  may  in  fact  be  of

different types but that are for some purposes treated alike.  For example,

Lisp  data  structures are typically constructed of CONS cells whose fields

may point to other CONS cells or to ATOMs.  The GLISP structure description

language does not permit the user to specify that  a  certain  field  of  a

                           ←←
structure  is  a CONS cell or an ATOM.  However, it is possible to create a

GLISP data type  that  encompasses  both.    Typically,  this  is  done  by

declaring  the structure of the object to be the complex structure and then

testing for the simpler structure explicitly.  This is illustrated for  the

case of the Lisp tree below.



       (LISPTREE  (CONS (CAR LISPTREE) (CDR LISPTREE))

          ADJ    ((EMPTY     (~self)))

          PROP   ((LEFTSON   ((If self is ATOMIC then NIL else CAR)))
                  (RIGHTSON  ((If self is ATOMIC then NIL else CDR)))))
                                                                         61


9.3. Generators
9.3. Generators
9.3. Generators

     Often,  one  would  like to define such properties of an object as the

way of enumerating its  parts  in  some  order.    Such  things  cannot  be

specified  directly  as properties of the object because they depend on the

previous state of the enumeration.  However, it is possible  to  define  an

object,  associated with the original data type, that contains the state of

the enumeration and responds to messages.  This is illustrated below by  an

object that searches a tree in preorder.



    (PreorderSearchRecord  (CONS (Node LISPTREE)
                                 (PreviousNodes (LISTOF LISPTREE)))

       MSG  ((NEXT  ((PROG (TMP)
                        (If TMP←Node:LEFTSON
                            then (If Node:RIGHTSON
                                     then PreviousNodes+←Node)
                                 Node←TMP
                            else TMP-←PreviousNodes
                                 Node←TMP:RIGHTSON) ))))


    (PRINTLEAVES (GLAMBDA ((A LISPTREE))
          (PROG (PSR)
             (PSR ← (A PreorderSearchRecord
                       with Node = (the LISPTREE)))
             (While Node (If Node is ATOMIC (PRINT Node))
                         (← PSR NEXT)) )))



The  object  class  PreorderSearchRecord  serves two purposes: It holds the

state of the enumeration, and it responds to messages to step  through  the

enumeration.    With  these  definitions,  it  is  easy  to write a program

involving enumeration of a LISPTREE, as illustrated by the function example

PRINTLEAVES above.  By being open-compiled, messages to an object can be as

efficient as in-line hand coding, yet the code for the messages has  to  be

written  only  once and can easily be changed without changing the programs
                                                                         62


that use the messages.
                                                                         63


                                CHAPTER 10
                                CHAPTER 10
                                CHAPTER 10

                              ACKNOWLEDGMENTS
                              ACKNOWLEDGMENTS
                              ACKNOWLEDGMENTS

     Many people have contributed help and useful comments about GLISP.

     Help  in  adapting  GLISP  to  particular Lisp dialects was generously

provided by Larry Masinter and Ron Kaplan  (Interlisp),  Dick  Fateman  and

Milt  Grinberg  (Franz  Lisp),  and  Martin Griss (Portable Standard Lisp).

Christopher Schmidt provided much help with the local Lisp environment.

     Early  users  of  GLISP  have  provided  many  helpful  bug   reports,

suggestions,  and  comments concerning this manual.  Special thanks are due

to Aaron Temin, Henry Sowizral, Keith Wescourt, Ken Anderson,  Bill  White,

and  Jay  Lark.    Helpful  comments have also been provided by Dan Bobrow,

Harold Brown, Phil Gerring, and Mark Stefik.

     Dianne  Kanerva  proofread  this   manual,   making   many   stylistic

improvements.

     Finally,  particular thanks are due Ed Feigenbaum, Bruce Buchanan, and

Tom Rindfleisch for their encouragement and support of this project.    Ira

Goldstein  and  Hewlett-Packard Co. have provided support in adapting GLISP

for Portable Standard Lisp.
                                                                         64


                                CHAPTER 11
                                CHAPTER 11
                                CHAPTER 11

                             PROGRAM EXAMPLES
                             PROGRAM EXAMPLES
                             PROGRAM EXAMPLES

     This  section  presents  examples  of  the use of GLISP.  The examples

include object descriptions, functions which use the objects,  creation  of

data  objects, and interactive use of GLISP.  The examples are shown in the

form appropriate for Interlisp; the test file GLTEST which is provided  for

each  Lisp  dialect  contains versions of these examples in the appropriate

form for that dialect.



11.1. Company Example
11.1. Company Example
11.1. Company Example

     The following set of object descriptions describes a company database.



    (GLISPOBJECTS

    (EMPLOYEE

       (LIST (NAME STRING)
             (DATE-HIRED (A DATE))
             (SALARY REAL)
             (JOBTITLE ATOM)
             (TRAINEE BOOLEAN))

       PROP   ((SENIORITY ((THE YEAR OF (CURRENTDATE))
                           -
                           (THE YEAR OF DATE-HIRED)))
               (MONTHLY-SALARY (SALARY * 174)))

       ADJ    ((HIGH-PAID (MONTHLY-SALARY > 2000)))

       ISA    ((TRAINEE (TRAINEE))
               (GREENHORN (TRAINEE AND SENIORITY < 2)))

       MSG    ((YOURE-FIRED (SALARY ← 0)))  )
                                                                         65



    (DATE
       (LIST (MONTH INTEGER)
             (DAY INTEGER)
             (YEAR INTEGER))
       PROP   ((MONTHNAME (CAR (NTH  '(JANUARY FEBRUARY MARCH APRIL
                                       MAY JUNE JULY AUGUST SEPTEMBER
                                       OCTOBER NOVEMBER DECEMBER)
                                 MONTH))))
               (PRETTYFORM ((LIST DAY MONTHNAME YEAR)))
               (SHORTYEAR (YEAR - 1900)))  )




    (COMPANY
       (ATOM (PROPLIST (PRESIDENT (AN EMPLOYEE))
                       (EMPLOYEES (LISTOF EMPLOYEE)  )))
       PROP  ((ELECTRICIANS
                   ((THOSE EMPLOYEES WITH JOBTITLE='ELECTRICIAN)))) )

    )


     The A function can be used either within functions or interactively to

create data objects:
                                                                         66



    (SETQ COMPANY1 (A COMPANY WITH
       PRESIDENT = (AN EMPLOYEE WITH NAME = "OSCAR THE GROUCH"
                                SALARY = 88.0
                                JOBTITLE = 'PRESIDENT
                                DATE-HIRED = (A DATE WITH MONTH = 3
                                                DAY = 15 YEAR = 1907))
       EMPLOYEES = (LIST
                   (AN EMPLOYEE WITH NAME = "COOKIE MONSTER"
                                SALARY = 12.50
                                JOBTITLE = 'ELECTRICIAN
                                DATE-HIRED = (A DATE WITH MONTH = 7
                                                DAY = 21 YEAR = 1947))
                   (AN EMPLOYEE WITH NAME = "BETTY LOU"
                                SALARY = 9.00
                                JOBTITLE = 'ELECTRICIAN
                                DATE-HIRED = (A DATE WITH MONTH = 5
                                                DAY = 15 YEAR = 1980))
                   (AN EMPLOYEE WITH NAME = "GROVER"
                                SALARY = 3.00
                                JOBTITLE = 'ELECTRICIAN
                                TRAINEE = T
                                DATE-HIRED = (A DATE WITH MONTH = 6
                                                DAY = 13 YEAR = 1978))
    )))



     The following program will give raises to the electricians.



        (GIVE-RAISE
           (GLAMBDA (:COMPANY)
               (FOR EACH ELECTRICIAN WHO IS NOT A TRAINEE
                  DO (SALARY ←+(IF SENIORITY > 1
                                   THEN 2.5
                                   ELSE 1.5))
                     (PRINT (THE NAME OF THE ELECTRICIAN))
                     (PRINT (THE PRETTYFORM OF DATE-HIRED))
                     (PRINT MONTHLY-SALARY) )))



The CURRENTDATE function returns a constant date.



        (CURRENTDATE
           (GLAMBDA ()    (RESULT DATE)
               (A DATE WITH YEAR = 1981   MONTH = 11   DAY = 30)))
                                                                         67


11.2. Vectors Example
11.2. Vectors Example
11.2. Vectors Example

     This section contains a set of object descriptions and functions which

describe  two-element vectors.  The vector functions are written as generic

functions, so that they can be used for several different kinds of vectors.

     First, the basic vector  object  is  described.    The  actual  stored

structure  for  a  vector  is  simple,  but  it  is  overloaded  with  many

properties.  The MAGNITUDE property contains a call to the  SQRT  function;

the argument of SQRT is an expression containing definite references to the

X  and  Y  substructures of the vector.  The DIRECTION property illustrates

the  use  of  conditional  code  in  defining  a  computed  property;   the

conditional  code  will  be  duplicated  in-line each time the DIRECTION is

referenced.  Defining arithmetic  operators  as  message  selectors  causes

automatic  overloading  of  the  operators for vector operands; this allows

vector arithmetic to be specified by arithmetic expressions.   The  use  of

the  ARGTYPES  specification for the "*" messages allows two meanings to be

assigned to the "*" operator:  multiplication of a vector by a  scalar  and

vector dot product.
                                                                         68



    (GLISPOBJECTS

      (VECTOR

         (LIST (X INTEGER)
               (Y INTEGER))

         PROP   ((MAGNITUDE ((SQRT X↑2 + Y↑2)))
                 (DIRECTION ((IF X IS ZERO
                                 THEN (IF Y IS NEGATIVE THEN -90.0
                                                        ELSE 90.0)
                                 ELSE (ATAN2D Y X)))
                              RESULT DEGREES))

         ADJ    ((ZERO (X IS ZERO AND Y IS ZERO))
                 (NORMALIZED (MAGNITUDE = 1.0)))

         MSG    ((+ VECTORPLUS OPEN T)
                 (- VECTORDIFF OPEN T)
                 (* VECTORTIMESSCALAR ARGTYPES (NUMBER) OPEN T)
                 (* VECTORDOTPRODUCT ARGTYPES (VECTOR) OPEN T)
                 (/ VECTORQUOTIENTSCALAR OPEN T)
                 (←+ VECTORMOVE OPEN T)
                 (PRIN1 ((PRIN1 "(")
                         (PRIN1 X)
                         (PRIN1 ",")
                         (PRIN1 Y)
                         (PRIN1 ")")))
                 (PRINT ((SEND SELF PRIN1)
                         (TERPRI)))  ) )
    )



     The  FVECTOR object differs from the VECTOR object in two ways: it has

a different structure (CONS instead of LIST),  and  its  components  are  a

STRING  and  a  BOOLEAN rather than INTEGERs.  Because the types of objects

are propagated by the GLISP compiler, the same generic function  VECTORPLUS

can be used for both VECTORs and FVECTORs.



      (FVECTOR (CONS (Y STRING) (X BOOLEAN))
         SUPERS (VECTOR))
                                                                         69


     The  DEGREES and RADIANS objects illustrate how an object whose stored

representation is a basic type  (in  this  case,  a  REAL  number)  can  be

overloaded  with  properties.   Such overloading is also useful for viewing

objects using the GEV inspector.



      (DEGREES REAL
         PROP ((RADIANS (self*(3.1415926 / 180.0)) RESULT RADIANS)))

      (RADIANS REAL
         PROP ((DEGREES (self*(180.0 / 3.1415926)) RESULT DEGREES)))



     The following  functions  define  arithmetic  operations  on  Vectors.

These  functions  are  generally  called  OPEN (macro-expanded) rather than

being called directly.  The use of  TYPEOF  as  the  type  within  the  "A"

                                              ←←←←←←←
function  calls  allows these functions to be generic; that is, they create

the same type of data they are "called" with, and therefore can be used for

a variety of vector types.



    (VECTORPLUS
       (GLAMBDA (V1:VECTOR V2:VECTOR)
          (A (TYPEOF V1) WITH X = V1:X + V2:X   Y = V1:Y + V2:Y)))

    (VECTORDIFF
       (GLAMBDA (V1:VECTOR V2:VECTOR)
          (A (TYPEOF V1) WITH X = V1:X - V2:X   Y = V1:Y - V2:Y)))

    (VECTORTIMESSCALAR
       (GLAMBDA (V:VECTOR N:NUMBER)
          (A (TYPEOF V) WITH X = X*N   Y = Y*N)))
                                                                         70


    (VECTORQUOTIENTSCALAR
       (GLAMBDA (V:VECTOR N:NUMBER)
          (A (TYPEOF V) WITH X = X/N   Y = Y/N)))

    (VECTORDOTPRODUCT
       (GLAMBDA (V1:VECTOR V2:VECTOR)
          (A (TYPEOF V1) WITH X = V1:X * V2:X   Y = V1:Y * V2:Y)))

    (VECTORMOVE
       (GLAMBDA (V:VECTOR DELTA:VECTOR)
          (V:X ←+ DELTA:X)
          (V:Y ←+ DELTA:Y)
          V))



     VECTORMOVE,  which  defines  the  "←+"  operator  for  vectors, does a

destructive addition to the vector which is its first argument.  Thus,  the

expression  "U←+V"  will  destructively change U, while "U←U+V" will make a

new vector with the value U+V and assign its value to U. 

     The following example  functions  use  the  vector  definitions  given

above.   The compiled versions of the functions are shown to illustrate how

the different object definitions produce different output code for  similar

"surface" code.



    (TVPLUS    (GLAMBDA (U:VECTOR V:VECTOR)   U+V))

      (GLCP 'TVPLUS)

        (GLCOMP TVPLUS)
        GLRESULTTYPE: VECTOR
        (LAMBDA (U V) (LIST (IPLUS (CAR U) (CAR V))
                            (IPLUS (CADR U) (CADR V))))
                                                                         71



    (TVMOVE    (GLAMBDA (U:VECTOR V:VECTOR)   U←+V))

        (LAMBDA (U V)
          (RPLACA U (IPLUS (CAR U) (CAR V)))
          (RPLACA (CDR U) (IPLUS (CADR U) (CADR V)))
          U)




    (TVTIMESV  (GLAMBDA (U:VECTOR V:VECTOR)   U*V))

        (LAMBDA (U V) (LIST (ITIMES (CAR U) (CAR V))
                            (ITIMES (CADR U) (CADR V))))




    (TVTIMESN  (GLAMBDA (U:VECTOR N:NUMBER)  U*N))

        (LAMBDA (U N) (LIST (TIMES (CAR U) N)
                            (TIMES (CADR U) N)))




    (TFVPLUS   (GLAMBDA (U:FVECTOR V:FVECTOR)  U+V))

        (LAMBDA (U V) (CONS (CONCAT (CAR U) (CAR V))
                            (OR (CDR U) (CDR V))))




11.3. GraphicsObject Example
11.3. GraphicsObject Example
11.3. GraphicsObject Example


     The  following  object descriptions are used in a graphics object test
       39
program  .  The definition of GraphicsObject builds on that of Vector.  The

property LEFT is defined as being equivalent to  the  X  component  of  the

START  vector.   Vector arithmetic is used in defining the property CENTER.


←←←←←←←←←←←←←←←

  39
    This program is derived from one written by D.G. Bobrow as a  LOOPS [1]
example.
                                                                         72


The  messages  DRAW  and ERASE illustrate a way to obtain different runtime

behavior for objects with different SHAPEs; this could also be  done  using

the interpretive message mechanism.



    (GRAPHICSOBJECT

       (LIST (SHAPE ATOM)
             (START VECTOR)
             (SIZE VECTOR))

       PROP   ((LEFT (START:X))
               (BOTTOM (START:Y))
               (RIGHT (LEFT+WIDTH))
               (TOP (BOTTOM+HEIGHT))
               (WIDTH (SIZE:X))
               (HEIGHT (SIZE:Y))
               (CENTER (START+SIZE/2))
               (AREA (WIDTH*HEIGHT)))

       MSG    ((DRAW ((APPLY* (GETPROP SHAPE 'DRAWFN)
                              self
                              'PAINT)))
               (ERASE ((APPLY* (GETPROP SHAPE 'DRAWFN)
                               self
                               'ERASE)))
               (MOVE GRAPHICSOBJECTMOVE OPEN T))  )



     An object moves itself by erasing itself, changing its starting point,

and then redrawing itself.



    (GRAPHICSOBJECTMOVE
       (GLAMBDA (self:GRAPHICSOBJECT DELTA:VECTOR)
          (SEND self ERASE)
          (START ←+ DELTA)
          (SEND self DRAW)))



     A  MovingGraphicsObject is a GraphicsObject which also has a VELOCITY.

The  GraphicsObject  is  declared  TRANSPARENT,  which  makes  all  of  its

properties  directly visible from a MovingGraphicsObject.  The STEP message
                                                                         73


causes  the  object to move itself by the amount specified as its VELOCITY;

the  MOVE  message  the  object  sents  to  itself  is   handled   by   its

GraphicsObject component.



    (MOVINGGRAPHICSOBJECT

       (LIST (TRANSPARENT GRAPHICSOBJECT)
             (VELOCITY VECTOR))

       Msg    ((STEP ((SEND self MOVE VELOCITY))))  )



     The  test  function  MGO-TEST  creates a MovingGraphicsObject and then
                                                       40
moves it across the screen by sending it MOVE messages.      Everything  in

this  example  is  compiled open; the STEP message involves a great deal of

message inheritance, and generates a large amount of in-line Lisp code from

a relatively small amount of GLISP code.  The  WHILE  loop  illustrates  an

easy way to construct "Pascal-style" FOR loops.



    (MGO-TEST (GLAMBDA ()
       (PROG (MGO N)
             (MGO ←(A MOVINGGRAPHICSOBJECT WITH
                        SHAPE =    'RECTANGLE
                        SIZE =     (A VECTOR WITH X = 4   Y = 3)
                        VELOCITY = (A VECTOR WITH X = 3   Y = 4)))
             (N ← 0)
             (WHILE (N←+1)<100 (SEND MGO STEP))
             (SEND MGO:START PRINT))))



     The  following function draws a rectangle.  Computed properties of the



←←←←←←←←←←←←←←←

  40
    The test program MGO-TEST runs on a Xerox Lisp machine, but  won't  run
on other machines.
                                                                         74


rectangle  are  used  within  calls  to  the graphics functions, making the

MOVETO and DRAWTO code easy to write and understand.



    (DRAWRECT (GLAMBDA (self:GRAPHICSOBJECT DISPLAYOP:ATOM)
       (PROG (OLDDS)
             (OLDDS ←(CURRENTDISPLAYSTREAM DSPS))
             (DSPOPERATION DISPLAYOP)
             (MOVETO LEFT BOTTOM)
             (DRAWTO LEFT TOP)
             (DRAWTO RIGHT TOP)
             (DRAWTO RIGHT BOTTOM)
             (DRAWTO LEFT BOTTOM)
             (CURRENTDISPLAYSTREAM OLDDS) )))




11.4. Circle Example
11.4. Circle Example
11.4. Circle Example

     The  Circle  objects  illustrate  the  definition  of  a   number   of

mathematical  properties  of an object in terms of stored data and in terms

of other properties.  The property  PI  illustrates  the  definition  of  a

property  as  a  constant.   Many of the properties of a Circle are defined

using definite reference to other properties.  The messages defined  for  a

circle illustrate "storing into" a computed property, in this case the AREA

of a circle.
                                                                         75



    (GLISPOBJECTS

    (CIRCLE (LIST (START VECTOR) (RADIUS REAL))

        PROP ((PI            (3.1415926))
              (DIAMETER      (RADIUS*2))
              (CIRCUMFERENCE (PI*DIAMETER))
              (AREA          (PI*RADIUS↑2)) )

        ADJ  ((BIG           (AREA>120))
              (MEDIUM        (AREA >= 60 AND AREA <= 120))
              (SMALL         (AREA<60)))

        MSG  ((STANDARD      (AREA←100))
              (GROW          (AREA←+100))
              (SHRINK        (AREA←AREA/2)) )
         )


     The function GROWCIRCLE illustrates assignment to a computed property.



      (DEFINEQ
        (GROWCIRCLE (GLAMBDA (C:CIRCLE)
           (C:AREA←+100)
           C )))

      (GLCP 'GROWCIRCLE)
        (GLCOMP GROWCIRCLE)
        GLRESULTTYPE: CIRCLE
        (LAMBDA (C)
          (RPLACA (CDR C)
                  (SQRT (QUOTIENT (PLUS (TIMES 3.1415926
                                               (EXPT (CADR C) 2))
                                        100)
                                  3.1415926)))
          C)



     A  DCIRCLE  is  implemented  differently  from  a  CIRCLE:    the data

structure is different, and DIAMETER is  stored  instead  of  RADIUS.    By

defining  RADIUS  as  a  property,  all of the CIRCLE properties defined in

terms of RADIUS can be inherited.
                                                                         76



    (GLISPOBJECTS

    (DCIRCLE (LISTOBJECT (START VECTOR) (DIAMETER REAL))
        PROP ((RADIUS       (DIAMETER/2)))
       SUPERS (CIRCLE) )
    )



     The  following  transcript  of  an interactive session illustrates the

interactive use of messages and  the  "A"  function  with  circle  objects.

Since  DCIRCLE  is  an  Object type, instances of DCIRCLEs can be used with

interpreted  messages;  instances  of  CIRCLEs  can  also  be   used   with

interpreted  messages by using the function SENDC and including the name of

the class of the object in the SENDC call.



      (SETQ MYCIRCLE (A CIRCLE))
        ((0 0) 0.0)
      (GROWCIRCLE MYCIRCLE)
        ((0 0) 5.6418959)
      (SENDC MYCIRCLE CIRCLE AREA)
        100.0
      (SENDC MYCIRCLE CIRCLE AREA: 150)
        6.9098831
      (SENDC MYCIRCLE CIRCLE AREA)
        150.000002




      (SETQ DC (A DCIRCLE WITH DIAMETER = 10.0))
        (DCIRCLE (0 0) 10.0)
      (SEND DC AREA)
        78.539815
      (SEND DC AREA: 100)
        11.2837918
      (SEND DC AREA)
        100.0
      (SEND DC GROW)
        15.9576914
      (SEND DC AREA)
        200.0
                                                                         77


11.5. Square Root Example
11.5. Square Root Example
11.5. Square Root Example

     The  following definition of a simple square root function illustrates

the use of GLISP for traditional mathematical programming.



    (SQRT (GLAMBDA (X:REAL)
      (PROG ((S X))
        (IF X < 0 THEN (ERROR)
                  ELSE (WHILE (ABS S*S - X) > 0.000001
                           DO (S ← (S+X/S) * 0.5)))
        (RETURN S))))




11.6. Squash Example
11.6. Squash Example
11.6. Squash Example

     The  function  SQUASH,  shown  below,   illustrates   elimination   of

compile-time  constants.    Of  course,  nobody would write such a function

directly.  However, such forms can  arise  when  inherited  properties  are

compiled.    Conditional  compilation occurs automatically when appropriate

variables are defined to  the  GLISP  compiler  as  compile-time  constants

because  the  optimization  phase  of  the compiler makes the unwanted code

disappear.



    (SQUASH (GLAMBDA ()
      (IF 1>3 THEN 'AMAZING
          ELSEIF (SQRT 7.2)<2 THEN 'INCREDIBLE
          ELSEIF 2 + 2 = 4 THEN 'OKAY
          ELSE 'JEEZ)))

    (GLCP 'SQUASH)
      (GLCOMP SQUASH)
      GLRESULTTYPE: ATOM
      (LAMBDA NIL (QUOTE OKAY))
                                                                         78


11.7. Class Example
11.7. Class Example
11.7. Class Example

     The following object definitions describe a student records database.



    (GLISPOBJECTS

    (STUDENT (ATOM (PROPLIST (NAME STRING)
                             (SEX ATOM)
                             (MAJOR ATOM)
                             (GRADES (LISTOF INTEGER))))

       PROP ((AVERAGE STUDENT-AVERAGE)
             (GRADE-AVERAGE STUDENT-GRADE-AVERAGE))

       ADJ  ((MALE (SEX='MALE))
             (FEMALE (SEX='FEMALE))
             (WINNING (AVERAGE>=95))
             (LOSING (AVERAGE<60)))

       ISA  ((WINNER (SELF IS WINNING))))




    (STUDENT-GROUP (LISTOF STUDENT)

       PROP ((N-STUDENTS LENGTH)
             (AVERAGE STUDENT-GROUP-AVERAGE)))




    (CLASS (ATOM (PROPLIST (DEPARTMENT ATOM)
                           (NUMBER INTEGER)
                           (INSTRUCTOR STRING)
                           (STUDENTS STUDENT-GROUP)))

       PROP ((N-STUDENTS (STUDENTS:N-STUDENTS))
             (MEN ((THOSE STUDENTS WHO ARE MALE)))
             (WOMEN ((THOSE STUDENTS WHO ARE FEMALE)))
             (WINNERS ((THOSE STUDENTS WHO ARE WINNING)))
             (LOSERS ((THOSE STUDENTS WHO ARE LOSING)))
             (CLASS-AVERAGE (STUDENTS:AVERAGE))))

    )
                                                                         79



    (STUDENT-AVERAGE (GLAMBDA (S:STUDENT)
      (PROG ((SUM 0.0)(N 0.0))
        (FOR G IN GRADES DO  N ←+ 1.0    SUM←+G)
        (RETURN SUM/N) )))




    (STUDENT-GRADE-AVERAGE (GLAMBDA (S:STUDENT)
      (PROG ((AV S:AVERAGE))
        (RETURN (IF AV >= 90.0 THEN 'A
                    ELSEIF AV >= 80.0 THEN 'B
                    ELSEIF AV >= 70.0 THEN 'C
                    ELSEIF AV >= 60.0 THEN 'D
                    ELSE 'F)))))




    (STUDENT-GROUP-AVERAGE (GLAMBDA (SG:STUDENT-GROUP)
      (PROG ((SUM 0.0))
        (FOR S IN SG DO SUM←+S:AVERAGE)
        (RETURN SUM/SG:N-STUDENTS) )))



     Next, several functions which use the above definitions are given.



    (TEST1 (GLAMBDA (C:CLASS)
    (* Print name and grade average for each student.)
      (FOR S IN C:STUDENTS (PRIN1 S:NAME)
                           (SPACES 1)
                           (PRINT S:GRADE-AVERAGE))))

    (TEST1B (GLAMBDA (:CLASS)
    (* Another version of the above function.)
      (FOR EACH STUDENT (PRIN1 NAME)
                        (SPACES 1)
                        (PRINT GRADE-AVERAGE))))
                                                                         80


    (TEST2 (GLAMBDA (C:CLASS)
    (* Print name and average of the winners in the class.)
      (FOR S IN C:WINNERS (PRIN1 S:NAME)
                          (SPACES 1)
                          (PRINT S:AVERAGE))))

    (TEST3 (GLAMBDA (C:CLASS)
    (* The average of all the male students' grades.)
      C:MEN:AVERAGE))

    (TEST4 (GLAMBDA (C:CLASS)
    (* The name and average of the winning women.)
      (FOR S IN C:WOMEN WHEN S IS WINNING
                           (PRIN1 S:NAME)
                           (SPACES 1)
                           (PRINT S:AVERAGE))))



     Another way to print the names and averages of the winning women is to

use  the  * operator to intersect the sets of women and winners.  The GLISP

compiler optimizes the  code  so  that  these  intermediate  sets  are  not

actually constructed.



    (TEST4B (GLAMBDA (C:CLASS)
      (FOR S IN C:WOMEN*C:WINNERS
                           (PRIN1 S:NAME)
                           (SPACES 1)
                           (PRINT S:AVERAGE))))



     Next,  the "A" function is used to create some test data for the above

functions.
                                                                         81



    (SETQ CLASS1 (A CLASS WITH INSTRUCTOR = "A. PROF"
                               DEPARTMENT = 'CS
                               NUMBER = 102
                               STUDENTS =
     (LIST
       (A STUDENT WITH NAME = "JOHN DOE" SEX = 'MALE MAJOR = 'CS
           GRADES = '(99 98 97 93))
       (A STUDENT WITH NAME = "FRED FAILURE" SEX = 'MALE MAJOR = 'CS
           GRADES = '(52 54 43 27))
       (A STUDENT WITH NAME = "MARY STAR" SEX = 'FEMALE MAJOR = 'CS
           GRADES = '(100 100 99 98))
       (A STUDENT WITH NAME = "DORIS DUMMY" SEX = 'FEMALE MAJOR = 'CS
           GRADES = '(73 52 46 28))
       (A STUDENT WITH NAME = "JANE AVERAGE" SEX = 'FEMALE MAJOR = 'CS
           GRADES = '(75 82 87 78))
       (A STUDENT WITH NAME = "LOIS LANE" SEX = 'FEMALE MAJOR = 'CS
           GRADES = '(98 95 97 96)) )))




11.8. Density Example
11.8. Density Example
11.8. Density Example

     The  following object definitions illustrate inheritance of properties

from multiple parent classes.  The three "bottom"  classes  Planet,  Brick,

and  Bowling-Ball  all  inherit the same definition of the property Density

from the object class Physical-Object, although  they  are  represented  in

very  different  ways.   For Planets, the property Mass is stored directly,

while for Ordinary-Objects the Weight of the object is stored, and Mass  is

computed  by dividing the weight by the value of gravity.  (MKS measurement

units are assumed.)  Bowling-Balls are defined so that there are two  fixed

Radius values, depending on whether the Type of the Bowling-Ball is "Adult"

or "Child".
                                                                         82



    (GLISPOBJECTS

    (PHYSICAL-OBJECT ANYTHING
      PROP ((DENSITY (MASS/VOLUME))))

    (ORDINARY-OBJECT ANYTHING
      PROP ((MASS (WEIGHT / 9.88)))
      SUPERS (PHYSICAL-OBJECT))

    (SPHERE ANYTHING
      PROP ((VOLUME ((4.0 / 3.0) * 3.1415926 * RADIUS ↑ 3))))

    (PARALLELEPIPED ANYTHING
      PROP ((VOLUME (LENGTH*WIDTH*HEIGHT))))



    (PLANET (LISTOBJECT (MASS REAL)(RADIUS REAL))
      SUPERS (PHYSICAL-OBJECT SPHERE))

    (BRICK (OBJECT (LENGTH REAL)(WIDTH REAL)(HEIGHT REAL)(WEIGHT REAL))
      SUPERS (ORDINARY-OBJECT PARALLELEPIPED))

    (BOWLING-BALL (ATOMOBJECT (TYPE ATOM)(WEIGHT REAL))
      PROP ((RADIUS ((IF TYPE='ADULT THEN 0.1 ELSE 0.07))))
      SUPERS (ORDINARY-OBJECT SPHERE))

    )


     The   following  functions  demonstrate  inheritance  of  the  DENSITY

property.



    (DPLANET (GLAMBDA (P:PLANET) DENSITY))

    (DBRICK (GLAMBDA (B:BRICK) DENSITY))

    (DBB (GLAMBDA (B:BOWLING-BALL) DENSITY))



     The following code creates some objects to test the functions on.
                                                                         83



    (SETQ EARTH (A PLANET WITH MASS = 5.98E24 RADIUS = 6.37E6))

    (SETQ BRICK1 (A BRICK WITH WEIGHT = 20.0 WIDTH = 0.10 HEIGHT = 0.05
                    LENGTH = 0.20))

    (SETQ BB1 (A BOWLING-BALL WITH TYPE = 'ADULT WEIGHT = 60.0))



     Since  the object types Planet, Brick, and Bowling-Ball are defined as

Object types (i.e., they contain the Class name as  part  of  their  stored

data),  messages  can  be  sent  to  them  directly  from  the keyboard for

interactive examination of the objects:



    (SEND EARTH DENSITY)
      5523.24475
    (SEND BRICK1 DENSITY)
      2024.2915
    (SEND BRICK1 WEIGHT: 25.0)
      25.0
    (SEND BRICK1 DENSITY)
      2530.36438
    (SEND BRICK1 MASS: 2.0)
      19.76
    (SEND BRICK1 DENSITY)
      2000.00002



    (SEND BB1 DENSITY)
      1449.79204
    (SEND BB1 RADIUS)
      0.1
    (SEND BB1 TYPE)
      ADULT
    (SEND BB1 TYPE: 'CHILD)
      CHILD
    (SEND BB1 RADIUS)
      0.07
    (SEND BB1 DENSITY)
      4226.7988
                                                                         84


                                REFERENCES
                                REFERENCES
                                REFERENCES


[1]   Bobrow, D.G. and Stefik, M.
      ←←← ←←←←← ←←←←←←
      The LOOPS Manual.
      Technical Report KB-VLSI-81-13, Xerox Palo Alto Research Center,
         1981.

[2]   Novak, G. S.
      ←←←← ←←← ←←←←←  ←← ←←←←←←←←← ←←←←←←←←←←←←←← ←←←←←←←←
      GIRL and GLISP: An Efficient Representation Language.
      Technical Report TR-172, Computer Science Dept., Univ. of Texas at
         Austin, March, 1981.

[3]   Novak, G. S.
      ←←← ←←← ←←←←←←← ←←←←←←←←← ←←←←←←
      The GEV Display Inspector/Editor.
      Technical Report HPP-82-32, Heuristic Programming Project, Computer
         Science Dept., Stanford Univ., Nov., 1982.
                                                                         85


INDEX
INDEX
INDEX


          A/AN function   20
          ADJ descriptions   10
          Adjective compilation   40
          Adjective phrases   22
          Adjectives   22
          ARGTYPES declaration   42
          Assignment   30
          Assignment examples   30

          Basic data types   11
          Bug reports   57

          CASE statement   33
          Class testing   23
          Compilation of adjectives   40
          Compilation of messages   38
          Compilation of properties   40
          Compile time constants   17
          Compiler files   51
          Compiler functions   52
          Compound operators   28
          Conditional compilation   17
          Constants   17
          Context rules   46
          Control statements   32
          Creation of objects   20

          Data types   11
          Declarations   6, 24
          Declarations for messages   41
          Definite reference   36
          Documentation   51

          Editing data   16
          Editing object descriptions   16
          Editor functions   4, 52
          ELISP   55
          Example file   52
          Expressions   26

          Files   51
          FOR statement   33
          Franz Lisp   56
          Function syntax   24

          Getting started   52
          GLISP files   51
          GLISPOBJECTS example   7
          GLISPOBJECTS function   6
                                                                         86


          GLOBAL declaration   24
          Global variables   16
          GLSENDB function   45

          IF statement   32
          Initial values   26
          Interactive features   4, 21
          Interactive messages   44
          Interlisp   55
          Interpretive "A" function   21
          Interpretive messages   44
          ISA descriptions   10

          Knowledge representation languages   49

          Lisp adjectives   22
          Lisp dialects   54
          List operations   28

          Maclisp   56
          Mailing list   57
          Message compilation   38
          MESSAGE declaration   42
          Message declarations   41
          Message examples   39
          Messages   37
          MSG descriptions   10

          Object access   19
          Object creation   20
          Object description editing   16
          Object description examples   7
          Object descriptions   6
          Object types   14
          Obtaining GLISP   51
          OPEN declaration   41
          Operator overloading   42
          Operators   27, 28
          Optimization   17

          Parentheses   39
          Predicate phrases   22
          PROG variables   26
          PROP descriptions   10
          Property compilation   40
          Property descriptions   8
          Property examples   39

          Reference to objects   19
          REPEAT statement   35
          Reserved characters   53
          Reserved words   53, 54
                                                                         87


          RESULT declaration, for messages   41
          RESULT declaration, in functions   24
          Run time messages   44

          Self-assignment operators   31
          Self-recognition adjectives   22
          SEND function   44, 45
          SENDC function   45
          SENDPROP function   45
          SENDPROPC function   45
          Set operations   28
          SPECIALIZE declaration   42
          String operations   28
          Structure description editing   16
          Structure description examples   14
          Structure descriptions   11
          SUPERS description   10

          Testing object classes   23
          THE statement   36
          THOSE statement   36
          Type declarations   25
          Type inference   47
          TYPEOF type specification   14

          UCI Lisp   55

          VALUES description   10
          Variable declarations   25

          WHILE statement   35
                                                                          i


Table of Contents
Table of Contents
Table of Contents

1. Introduction
1. Introduction
1. Introduction                                                           1

     1.1. Overview of GLISP                                               1
     1.2. Implementation                                                  3
     1.3. Error Messages                                                  4
     1.4. Interactive Features of GLISP                                   4

2. Object Descriptions
2. Object Descriptions
2. Object Descriptions                                                    6

     2.1. Declaration of Object Descriptions                              6
          2.1.1. Property Descriptions                                    8
               2.1.1.1. PROP Descriptions                                10
               2.1.1.2. ADJ and ISA Descriptions                         10
               2.1.1.3. MSG Descriptions                                 10
          2.1.2. SUPERS Description                                      10
          2.1.3. VALUES Description                                      10
     2.2. Structure Descriptions                                         11
          2.2.1. Syntax of Structure Descriptions                        11
          2.2.2. Examples of Structure Descriptions                      14
     2.3. Editing of Object Descriptions                                 16
     2.4. Interactive Editing of Objects                                 16
     2.5. Global Variables                                               16
     2.6. Compile Time Constants                                         17
     2.7. Conditional Compilation                                        17

3. Reference to Objects
3. Reference to Objects
3. Reference to Objects                                                  19

     3.1. Accessing Objects                                              19
     3.2. Creation of Objects                                            20
     3.3. Interpretive Creation of Objects                               21
     3.4. Predicates on Objects                                          22
          3.4.1. Self-Recognition Adjectives                             22
          3.4.2. Testing Object Classes                                  23

4. GLISP Program Syntax
4. GLISP Program Syntax
4. GLISP Program Syntax                                                  24

     4.1. Function Syntax                                                24
     4.2. Expressions                                                    26
          4.2.1. Interpretation of Operators                             28
               4.2.1.1. Operations on Strings                            28
               4.2.1.2. Operations on Lists                              28
               4.2.1.3. Compound Operators                               28
               4.2.1.4. Assignment                                       30
               4.2.1.5. Self-assignment Operators                        31
     4.3. Control Statements                                             32
          4.3.1. IF Statement                                            32
          4.3.2. CASE Statement                                          33
          4.3.3. FOR Statement                                           33
          4.3.4. WHILE Statement                                         35
          4.3.5. REPEAT Statement                                        35
                                                                         ii


     4.4. Definite Reference to Particular Objects                       36

5. Messages
5. Messages
5. Messages                                                              37

     5.1. Compilation of Messages                                        38
     5.2. Compilation of Properties and Adjectives                       40
     5.3. Declarations for Message Compilation                           41
     5.4. Operator Overloading                                           42
     5.5. Run-time Interpretation of Messages                            44

6. Context Rules and Reference
6. Context Rules and Reference
6. Context Rules and Reference                                           46

     6.1. Organization of Context                                        46
     6.2. Rules for Using Definite Reference                             47
     6.3. Type Inference                                                 47

7. GLISP and Knowledge Representation Languages
7. GLISP and Knowledge Representation Languages
7. GLISP and Knowledge Representation Languages                          49

8. Obtaining and Using GLISP
8. Obtaining and Using GLISP
8. Obtaining and Using GLISP                                             51

     8.1. Documentation                                                  51
     8.2. Compiler Files                                                 51
     8.3. Getting Started                                                52
     8.4. Reserved Words and Characters                                  53
          8.4.1. Reserved Characters                                     53
          8.4.2. Reserved Function Names                                 54
          8.4.3. Other Reserved Names                                    54
     8.5. Lisp Dialect Idiosyncrasies                                    54
          8.5.1. Interlisp                                               55
          8.5.2. UCI Lisp                                                55
          8.5.3. ELISP                                                   55
          8.5.4. Maclisp                                                 56
          8.5.5. Franz Lisp                                              56
          8.5.6. Portable Standard Lisp                                  57
     8.6. Bug Reports and Mailing List                                   57

9. GLISP Hacks
9. GLISP Hacks
9. GLISP Hacks                                                           58

     9.1. Overloading Basic Types                                        58
     9.2. Disjunctive Types                                              60
     9.3. Generators                                                     61

10. Acknowledgments
10. Acknowledgments
10. Acknowledgments                                                      63

11. Program Examples
11. Program Examples
11. Program Examples                                                     64

     11.1. Company Example                                               64
     11.2. Vectors Example                                               67
     11.3. GraphicsObject Example                                        71
     11.4. Circle Example                                                74
     11.5. Square Root Example                                           77
     11.6. Squash Example                                                77
                                                                        iii


     11.7. Class Example                                                 78
     11.8. Density Example                                               81

Index
Index
Index                                                                    85