axiom-developer
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Axiom-developer] 20080216.01.wxh.patch (hash tables to speed compiles)


From: daly
Subject: [Axiom-developer] 20080216.01.wxh.patch (hash tables to speed compiles)
Date: Sat, 16 Feb 2008 14:07:23 -0600

This code is a performance improvement by Waldek Hebisch.
(Fricas patches 232 and 233).

The essence of the speedup appears to be caused by two factors.
The original code was non-recursive and used union across lists.
The new code is recursive. It also uses a hashtable to reduce
the amount of redundant list construction.

Additionally, the code in these files was rearranged and commented
by me for documentation purposes.

Tim
======================================================================
diff --git a/changelog b/changelog
index 94eac53..0a7fe92 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,7 @@
+20082016 wxh src/interp/i-intern.boot use hashtable to speedup compiles
+20082016 wxh src/interp/g-util.boot use hashtable to speedup compiles
+20082016 wxh src/interp/compiler.boot use hashtable to speedup compiles
+20082016 wxh src/interp/category.boot use hashtable to speedup compiles
 20080215 tpd src/interp/format.boot add )d op documentation
 20080215 tpd src/algebra/plot add comment documentation
 20080210 tpd src/algebra/Makefile add plot help and input files for plot
diff --git a/src/interp/category.boot.pamphlet 
b/src/interp/category.boot.pamphlet
index d90e771..097ede9 100644
--- a/src/interp/category.boot.pamphlet
+++ b/src/interp/category.boot.pamphlet
@@ -9,9 +9,93 @@
 \eject
 \tableofcontents
 \eject
-\section{mkCategory}
-This code defines the structure of a category. 
-<<mkCategory>>=
+\section{Category}
+Functions for building categories.
+
+Sorry to say, this hack is needed by isCategoryType
+<<*>>=
+Category() == nil 
+ 
+@
+\subsection{CategoryPrint}
+<<*>>=
+CategoryPrint(D,$e) ==
+  SAY "--------------------------------------"
+  SAY "Name (and arguments) of category:"
+  PRETTYPRINT D.(0)
+  SAY "operations:"
+  PRETTYPRINT D.(1)
+  SAY "attributes:"
+  PRETTYPRINT D.2
+  SAY "This is a sub-category of"
+  PRETTYPRINT first D.4
+  for u in CADR D.4 repeat
+    SAY("This has an alternate view: slot ",rest u," corresponds to ",first u)
+  for u in CADDR D.4 repeat
+    SAY("This has a local domain: slot ",rest u," corresponds to ",first u)
+  for j in 6..MAXINDEX D repeat
+    u:= D.j
+    null u => SAY "another domain"
+    atom first u => SAY("Alternate View corresponding to: ",u)
+    PRETTYPRINT u
+ 
+@
+\subsection{sigParams}
+This code is a performance improvement by Waldek Hebisch.
+The essence of the speedup appears to be caused by two factors.
+The original code was non-recursive and used union across lists.
+The new code is recursive. It also uses a hashtable to reduce
+the amount of redundant list construction.
+
+We compute the list of parameters that occur in signatures on the 
+sigList, removing duplicates, and skipping the ``known'' constructors,
+Union, Mapping, List, and Record.
+
+\verb|$PrimitiveDomainNames| is a list of domains that we need not cache.
+It is set in init.lisp.pamphlet.
+<<*>>=
+sigParams(sigList) ==
+ result:=nil
+ myhash:=MAKE_-HASHTABLE 'EQUAL
+ NewLocals:=nil
+ for s in sigList repeat
+  (NewLocals:=Prepare(CADAR s,NewLocals)) where
+   Prepare(u,l)==for v in u repeat l:=Prepare2(v,l)
+   Prepare2(v,l)==
+    v is "$" => l
+    STRINGP v => l
+    atom v => [v,:l]
+    MEMQ(first v,$PrimitiveDomainNames) => l
+    v is ["Union",:w] =>
+     for x in stripUnionTags w repeat l:=Prepare2(x,l)
+     l
+    v is ["Mapping",:w] =>
+     for x in w repeat l:=Prepare2(x,l)
+     l
+    v is ["List",:w] => Prepare2(w,l)
+    v is ["Record",:w] =>
+     for x in w repeat l:=Prepare2(CADDR x,l)
+     l
+    [v,:l]
+ for s in NewLocals repeat
+  if null(HGET(myhash,s)) then
+   HPUT(myhash,s,true)
+   result:=[s,:result]
+ result
+
+@
+\subsection{mkCategory}
+This code defines the structure of a category. It creates a new category
+vector. The arguments are:
+\begin{itemize}
+\item domainOrPackage -- ``domain'' or ``package'' which marks the kind
+of category object.
+\item sigList -- list of all signatures
+\item attList -- list of all attributes
+\item domList 
+\item PrincipalAncestor -- principal ancestor (if any)
+\end{itemize}
+<<*>>=
 mkCategory(domainOrPackage,sigList,attList,domList,PrincipalAncestor) ==
   NSigList:= nil
   if PrincipalAncestor=nil then count:= 6 else count:= SIZE PrincipalAncestor
@@ -26,23 +110,7 @@ 
mkCategory(domainOrPackage,sigList,attList,domList,PrincipalAncestor) ==
          count:= count+1
          nsig
      else s for s in sigList]
-  NewLocals:= nil
-  for s in sigList repeat
-    ((NewLocals:= UNION(NewLocals,Prepare CADAR s)) where
-      Prepare u == "UNION"/[Prepare2 v for v in u]) where
-        Prepare2 v ==
-          v is "$" => nil
-          STRINGP v => nil
-          atom v => [v]
-          MEMQ(first v,$PrimitiveDomainNames) => nil
-            --This variable is set in INIT LISP
-            --It is a list of all the domains that we need not cache
-          v is ["Union",:w] =>
-            "UNION"/[Prepare2 x for x in stripUnionTags w]
-          v is ["Mapping",:w] => "UNION"/[Prepare2 x for x in w]
-          v is ["List",w] => Prepare2 w
-          v is ["Record",.,:w] => "UNION"/[Prepare2 CADDR x for x in w]
-          [v]
+  NewLocals:= sigParams(sigList)
   OldLocals:= nil
   if PrincipalAncestor then for u in (OldLocals:= CADDR PrincipalAncestor.4)
      repeat NewLocals:= DELETE(first u,NewLocals)
@@ -63,138 +131,23 @@ 
mkCategory(domainOrPackage,sigList,attList,domList,PrincipalAncestor) ==
   v
 
 @
-\section{hasCategoryBug}
-The hasCategoryBug (bug000001)\cite{2} manifests itself by causing a
-value stack overflow when compiling algebra code that uses conditions
-that read ``if R has ...'' when using GCL (but not CCL). Essentially
-the [[|Ring|]] category keeps getting added to the list each time
-[[|Ring|]] is processed. Camm Maguire's mail explains it thus:
-
-The bottom line is that [[(|Ring|)]] is totally correct until
-[[|Algebra|]] is executed, at which point the fourth element returned
-by [[(|Ring|)]] is overwritten by the result returned in the fourth
-element of the vector returned by [[|Algebra|]].  The point of this
-overwrite is at the following form of [[|JoinInner|]] from
-[[(int/interp/category.clisp)]]
-
-\begin{verbatim}
- (SETELT |$NewCatVec| 4 (CONS |c| (CONS |FundamentalAncestors| (CONS
- (CADDR (ELT |$NewCatVec| 4)) NIL))))
-\end{verbatim}
-
-called from [[|Algebra;|]] [[(int/algebra/ALGEBRA.nrlib/code.lsp)]] through 
-
-\begin{verbatim}
-(|Join| (|Ring|) (|Module| (QUOTE |t#1|)) (|mkCategory| (QUOTE
-|domain|) (QUOTE (((|coerce| ($ |t#1|)) T))) NIL (QUOTE NIL) NIL))
-\end{verbatim}
-
-I haven't parsed [[|JoinInner|]] yet, but my guess is that there is a
-copy-seq in there which is not getting executed in the assignment of
-[[|$NewCatVec|]] before the setelt.
-
-The original code failed to copy the NewCatVec before updating
-it. This code from macros.lisp\cite{1} checks whether the array is
-adjustable.
-
-\begin{verbatim}
-(defun lengthenvec (v n)
-  (if (adjustable-array-p v) (adjust-array v n)
-    (replace (make-array n) v)))
-\end{verbatim}
-At least in GCL, the code for lengthenvec need not copy the vec to a
-new location. In this case the FundamentalAncesters array is adjustable
-and in GCL the adjust-array need not, and in this case, does not do a 
-copy.
-<<hasCategoryBug>>=
-      if reallynew then
-        n:= SIZE $NewCatVec
-        FundamentalAncestors:= [[b.(0),condition,n],:FundamentalAncestors]
-        $NewCatVec:= LENGTHENVEC($NewCatVec,n+1)
--- We need to copy the vector otherwise the FundamentalAncestors
--- list will get stepped on while compiling "If R has ... " code
--- Camm Maguire July 26, 2003
---        copied:= true
-        copied:= false
-        originalvector:= false
-        $NewCatVec.n:= b.(0)
-  if not copied then $NewCatVec:= COPY_-SEQ $NewCatVec
-    -- It is important to copy the vector now,
-    -- in case SigListUnion alters it while
-    -- performing Operator Subsumption
-@ 
-\section{License}
-<<license>>=
--- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
--- All rights reserved.
---
--- Redistribution and use in source and binary forms, with or without
--- modification, are permitted provided that the following conditions are
--- met:
---
---     - Redistributions of source code must retain the above copyright
---       notice, this list of conditions and the following disclaimer.
---
---     - Redistributions in binary form must reproduce the above copyright
---       notice, this list of conditions and the following disclaimer in
---       the documentation and/or other materials provided with the
---       distribution.
---
---     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
---       names of its contributors may be used to endorse or promote products
---       derived from this software without specific prior written permission.
---
--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-@
+\subsection{isCategory}
 <<*>>=
-<<license>>
- 
--- Functions for building categories
- 
-Category() == nil --sorry to say, this hack is needed by isCategoryType
- 
-CategoryPrint(D,$e) ==
-  SAY "--------------------------------------"
-  SAY "Name (and arguments) of category:"
-  PRETTYPRINT D.(0)
-  SAY "operations:"
-  PRETTYPRINT D.(1)
-  SAY "attributes:"
-  PRETTYPRINT D.2
-  SAY "This is a sub-category of"
-  PRETTYPRINT first D.4
-  for u in CADR D.4 repeat
-    SAY("This has an alternate view: slot ",rest u," corresponds to ",first u)
-  for u in CADDR D.4 repeat
-    SAY("This has a local domain: slot ",rest u," corresponds to ",first u)
-  for j in 6..MAXINDEX D repeat
-    u:= D.j
-    null u => SAY "another domain"
-    atom first u => SAY("Alternate View corresponding to: ",u)
-    PRETTYPRINT u
- 
-<<mkCategory>>
 isCategory a == REFVECP a and #a>5 and a.3=["Category"]
  
---% Subsumption code (for operators)
- 
+@
+\subsection{DropImplementations}
+Subsumption code (for operators)
+<<*>>=
 DropImplementations (a is [sig,pred,:implem]) ==
   if implem is [[q,:.]] and (q="ELT" or q="CONST")
      then if (q="ELT")  then [sig,pred]
                         else [[:sig,:'(constant)],pred]
      else a
  
+@
+\subsection{SigListUnion}
+<<*>>=
 SigListUnion(extra,original) ==
   --augments original %with everything in extra that is not in original
   for (o:=[[ofn,osig,:.],opred,:.]) in original repeat
@@ -247,6 +200,9 @@ SigListUnion(extra,original) ==
     original:= [e,:original]
   original
  
+@
+\subsection{mkOr}
+<<*>>=
 mkOr(a,b) ==
   a=true => true
   b=true => true
@@ -268,6 +224,9 @@ mkOr(a,b) ==
   LENGTH l = 1 => CAR l
   ["OR",:l]
  
+@
+\subsection{mkOr2}
+<<*>>=
 mkOr2(a,b) ==
   --a is a condition, "b" a list of them
   MEMBER(a,b) => b
@@ -281,6 +240,9 @@ mkOr2(a,b) ==
     [a,:b]
   [a,:b]
  
+@
+\subsection{mkAnd}
+<<*>>=
 mkAnd(a,b) ==
   a=true => b
   b=true => a
@@ -298,6 +260,9 @@ mkAnd(a,b) ==
   LENGTH l = 1 => CAR l
   ["AND",:l]
  
+@
+\subsection{mkAnd2}
+<<*>>=
 mkAnd2(a,b) ==
   --a is a condition, "b" a list of them
   MEMBER(a,b) => b
@@ -311,15 +276,24 @@ mkAnd2(a,b) ==
     [a,:b]
   [a,:b]
  
+@
+\subsection{SigListMember}
+<<*>>=
 SigListMember(m,list) ==
   list=nil => false
   SigEqual(m,first list) => true
   SigListMember(m,rest list)
  
+@
+\subsection{SigEqual}
+<<*>>=
 SigEqual([sig1,pred1,:.],[sig2,pred2,:.]) ==
   -- Notice asymmetry: checks that arg1 is a consequence of arg2
   sig1=sig2 and PredImplies(pred2,pred1)
  
+@
+\subsection{PredImplies}
+<<*>>=
 PredImplies(a,b) ==
     --true if a => b in the sense of logical implication
 --a = "true" => true
@@ -328,6 +302,9 @@ PredImplies(a,b) ==
   false         -- added by RDJ: 12/21/82
 --error()       -- for the time being
  
+@
+\subsection{SigListOpSubsume}
+<<*>>=
 SigListOpSubsume([[name1,sig1,:.],:.],list) ==
   --does m subsume another operator in the list?
         --see "operator subsumption" in SYSTEM SCRIPT
@@ -339,16 +316,25 @@ SigListOpSubsume([[name1,sig1,:.],:.],list) ==
       ans:=[n,:ans]
   return ans
  
+@
+\subsection{SigOpsubsume}
+<<*>>=
 SigOpsubsume([[name1,sig1,:flag1],pred1,:.],[[name2,sig2,:flag2],pred2,:.]) ==
                     --flag1 = flag2 and :this really should be checked
   name1=name2 and LENGTH sig1=LENGTH sig2 and SourceLevelSubsume(sig1,sig2)
  
+@
+\subsection{SourceLevelSubsume}
+<<*>>=
 SourceLevelSubsume([out1,:in1],[out2,:in2]) ==
   -- Checks for source-level subsumption in the sense of SYSTEM SCRIPT
   --   true if the first signature subsumes the second
   SourceLevelSubset(out1,out2) and
-    (and/[SourceLevelSubset(inarg2,inarg1) for inarg1 in in1 for inarg2 in 
in2])
+   (and/[SourceLevelSubset(inarg2,inarg1) for inarg1 in in1 for inarg2 in in2])
  
+@
+\subsection{SourceLevelSubset}
+<<*>>=
 SourceLevelSubset(a,b) ==
   --true if a is a source-level subset of b
   a=b => true
@@ -359,14 +345,20 @@ SourceLevelSubset(a,b) ==
   a is [a1] and b is [b1] and ASSOC(a1,GET(b1,"Subsets")) => true
   nil
  
+@
+\subsection{MachineLevelSubsume}
+<<*>>=
 MachineLevelSubsume([name1,[out1,:in1],:flag1],[name2,[out2,:in2],:flag2]) ==
   -- Checks for machine-level subsumption in the sense of SYSTEM SCRIPT
   --  true if the first signature subsumes the second
   --  flag1 = flag2 and: this really should be checked, but
   name1=name2 and MachineLevelSubset(out1,out2) and
-    (and/[MachineLevelSubset(inarg2,inarg1) for inarg1 in in1 for inarg2 in 
in2]
+   (and/[MachineLevelSubset(inarg2,inarg1) for inarg1 in in1 for inarg2 in in2]
       )
  
+@
+\subsection{MachineLevelSubset}
+<<*>>=
 MachineLevelSubset(a,b) ==
   --true if a is a machine-level subset of b
   a=b => true
@@ -378,8 +370,10 @@ MachineLevelSubset(a,b) ==
              --we assume all subsets are true at the machine level
   nil
  
---% Ancestor chasing code
- 
+@
+\subsection{FindFundAncs}
+Ancestor chasing code
+<<*>>=
 FindFundAncs l ==
   --l is a list of categories and associated conditions (a list of 2-lists
   --returns a list of them and all their fundamental ancestors
@@ -406,23 +400,26 @@ FindFundAncs l ==
   -- descendant of something previously added which is therefore
   -- subsumed
  
+@
+\subsection{CatEval}
+<<*>>=
 CatEval x ==
   REFVECP x => x
   $InteractiveMode => CAR compMakeCategoryObject(x,$CategoryFrame)
   CAR compMakeCategoryObject(x,$e)
  
---RemovePrinAncs(l,leaves) ==
---  l=nil => nil
---  leaves:= [first y for y in leaves]
---               --remove the slot pointers
---  [x for x in l | not AncestorP(x.(0),leaves)]
- 
+@
+\subsection{AncestorP}
+<<*>>=
 AncestorP(xname,leaves) ==
   -- checks for being a principal ancestor of one of the leaves
   MEMBER(xname,leaves) => xname
   for y in leaves repeat
     MEMBER(xname,first (CatEval y).4) => return y
  
+@
+\subsection{CondAncestorP}
+<<*>>=
 CondAncestorP(xname,leaves,condition) ==
   -- checks for being a principal ancestor of one of the leaves
   for u in leaves repeat
@@ -433,6 +430,9 @@ CondAncestorP(xname,leaves,condition) ==
     xname = u' or MEMBER(xname,first (CatEval u').4) =>
       PredImplies(ucond,condition) => return u'
  
+@
+\subsection{DescendantP}
+<<*>>=
 DescendantP(a,b) ==
   -- checks to see if a is any kind of Descendant of b
   a=b => true
@@ -445,8 +445,53 @@ DescendantP(a,b) ==
   AncestorP(b,[first u for u in CADR a.4]) => true
   nil
  
---% The implementation of Join
- 
+@
+\subsection{JoinInner}
+The implementation of Join
+\subsubsection{hasCategoryBug}
+The hasCategoryBug (bug000001)\cite{2} manifests itself by causing a
+value stack overflow when compiling algebra code that uses conditions
+that read ``if R has ...'' when using GCL (but not CCL). Essentially
+the [[|Ring|]] category keeps getting added to the list each time
+[[|Ring|]] is processed. Camm Maguire's mail explains it thus:
+
+The bottom line is that [[(|Ring|)]] is totally correct until
+[[|Algebra|]] is executed, at which point the fourth element returned
+by [[(|Ring|)]] is overwritten by the result returned in the fourth
+element of the vector returned by [[|Algebra|]].  The point of this
+overwrite is at the following form of [[|JoinInner|]] from
+[[(int/interp/category.clisp)]]
+
+\begin{verbatim}
+ (SETELT |$NewCatVec| 4 (CONS |c| (CONS |FundamentalAncestors| (CONS
+ (CADDR (ELT |$NewCatVec| 4)) NIL))))
+\end{verbatim}
+
+called from [[|Algebra;|]] [[(int/algebra/ALGEBRA.nrlib/code.lsp)]] through 
+
+\begin{verbatim}
+(|Join| (|Ring|) (|Module| (QUOTE |t#1|)) (|mkCategory| (QUOTE
+|domain|) (QUOTE (((|coerce| ($ |t#1|)) T))) NIL (QUOTE NIL) NIL))
+\end{verbatim}
+
+I haven't parsed [[|JoinInner|]] yet, but my guess is that there is a
+copy-seq in there which is not getting executed in the assignment of
+[[|$NewCatVec|]] before the setelt.
+
+The original code failed to copy the NewCatVec before updating
+it. This code from macros.lisp\cite{1} checks whether the array is
+adjustable.
+
+\begin{verbatim}
+(defun lengthenvec (v n)
+  (if (adjustable-array-p v) (adjust-array v n)
+    (replace (make-array n) v)))
+\end{verbatim}
+At least in GCL, the code for lengthenvec need not copy the vec to a
+new location. In this case the FundamentalAncesters array is adjustable
+and in GCL the adjust-array need not, and in this case, does not do a 
+copy.
+<<*>>=
 JoinInner(l,$e) ==
   $NewCatVec: local := nil
   CondList:= nil
@@ -561,7 +606,21 @@ JoinInner(l,$e) ==
                     if c=true
                        then attl:= [[a,condition],:attl]
                        else attl:= [[a,["and",condition,c]],:attl]
-<<hasCategoryBug>>
+      if reallynew then
+        n:= SIZE $NewCatVec
+        FundamentalAncestors:= [[b.(0),condition,n],:FundamentalAncestors]
+        $NewCatVec:= LENGTHENVEC($NewCatVec,n+1)
+-- We need to copy the vector otherwise the FundamentalAncestors
+-- list will get stepped on while compiling "If R has ... " code
+-- Camm Maguire July 26, 2003
+--        copied:= true
+        copied:= false
+        originalvector:= false
+        $NewCatVec.n:= b.(0)
+  if not copied then $NewCatVec:= COPY_-SEQ $NewCatVec
+    -- It is important to copy the vector now,
+    -- in case SigListUnion alters it while
+    -- performing Operator Subsumption
   for b in l repeat
     sigl:= SigListUnion([DropImplementations u for u in b.(1)],sigl)
     attl:=
@@ -598,20 +657,48 @@ JoinInner(l,$e) ==
   $NewCatVec.4:= [c,FundamentalAncestors,CADDR $NewCatVec.4]
   mkCategory("domain",sigl,attl,globalDomains,$NewCatVec)
  
---ProduceDomainAlist(u,e) ==
---  -- Gives a complete Alist for all the functions in the Domain
---  not (sig:= get(u,"modemap",e)) => nil
---  sig:= CADAAR sig
---                       --an incantation
---  [c,.,.]:= compMakeCategoryObject(sig,e)
---  -- We assume that the environment need not be kept
---  c.(1)
- 
+@
+\subsection{isCategoryForm}
+<<*>>=
 isCategoryForm(x,e) ==
   x is [name,:.] => categoryForm? name
   atom x => u:= get(x,"macro",e) => isCategoryForm(u,e)
  
 @
+\section{License}
+<<license>>=
+-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+--     - Redistributions of source code must retain the above copyright
+--       notice, this list of conditions and the following disclaimer.
+--
+--     - Redistributions in binary form must reproduce the above copyright
+--       notice, this list of conditions and the following disclaimer in
+--       the documentation and/or other materials provided with the
+--       distribution.
+--
+--     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+--       names of its contributors may be used to endorse or promote products
+--       derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@
 \eject
 \begin{thebibliography}{99}
 \bibitem{1} [[pamphlet:src/interp/macros.lisp.pamphlet]]
diff --git a/src/interp/compiler.boot.pamphlet 
b/src/interp/compiler.boot.pamphlet
index ce51681..4deb2b2 100644
--- a/src/interp/compiler.boot.pamphlet
+++ b/src/interp/compiler.boot.pamphlet
@@ -9,92 +9,9 @@
 \eject
 \tableofcontents
 \eject
-\section{Bug fixes}
-The compMacro function does macro expansion during spad file compiles.
-If a macro occurs twice in the same file the macro expands infinitely
-causing a stack overflow. The reason for the infinite recursion is that
-the left hand side of the macro definition is expanded. Thus defining
-a macro:
-\begin{verbatim}
-name ==> 1
-\end{verbatim}
-will expand properly the first time. The second time it turns into:
-\begin{verbatim}
-1 ==> 1
-\end{verbatim}
-The original code read:
-\begin{verbatim}
-compMacro(form,m,e) ==
-  $macroIfTrue: local:= true
-  ["MDEF",lhs,signature,specialCases,rhs]:= form
-  rhs :=
-    rhs is ['CATEGORY,:.] => ['"-- the constructor category"]
-    rhs is ['Join,:.]     => ['"-- the constructor category"]
-    rhs is ['CAPSULE,:.]  => ['"-- the constructor capsule"]
-    rhs is ['add,:.]      => ['"-- the constructor capsule"]
-    formatUnabbreviated rhs
-  sayBrightly ['"   processing macro definition",'%b,
-    :formatUnabbreviated lhs,'" ==> ",:rhs,'%d]
-  ["MDEF",lhs,signature,specialCases,rhs]:= form:= macroExpand(form,e)
-  m=$EmptyMode or m=$NoValueMode =>
-    ["/throwAway",$NoValueMode,put(first lhs,"macro",rhs,e)]
-
-\end{verbatim}
-Juergen Weiss proposed the following fixed code. This does not expand
-the left hand side of the macro.
-<<compMacro>>=
-compMacro(form,m,e) ==
-  $macroIfTrue: local:= true
-  ["MDEF",lhs,signature,specialCases,rhs]:= form
-  prhs :=
-    rhs is ['CATEGORY,:.] => ['"-- the constructor category"]
-    rhs is ['Join,:.]     => ['"-- the constructor category"]
-    rhs is ['CAPSULE,:.]  => ['"-- the constructor capsule"]
-    rhs is ['add,:.]      => ['"-- the constructor capsule"]
-    formatUnabbreviated rhs
-  sayBrightly ['"   processing macro definition",'%b,
-    :formatUnabbreviated lhs,'" ==> ",:prhs,'%d]
-  m=$EmptyMode or m=$NoValueMode =>
-    ["/throwAway",$NoValueMode,put(first lhs,"macro",macroExpand(rhs,e),e)]
-
-@
-\section{License}
-<<license>>=
--- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
--- All rights reserved.
---
--- Redistribution and use in source and binary forms, with or without
--- modification, are permitted provided that the following conditions are
--- met:
---
---     - Redistributions of source code must retain the above copyright
---       notice, this list of conditions and the following disclaimer.
---
---     - Redistributions in binary form must reproduce the above copyright
---       notice, this list of conditions and the following disclaimer in
---       the documentation and/or other materials provided with the
---       distribution.
---
---     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
---       names of its contributors may be used to endorse or promote products
---       derived from this software without specific prior written permission.
---
--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-@
+\section{Compiler Top Level Functions}
+\subsection{compTopLevel}
 <<*>>=
-<<license>>
-
 compTopLevel(x,m,e) ==
 --+ signals that target is derived from lhs-- see NRTmakeSlot1Info
   $NRTderivedTargetIfTrue: local := false
@@ -103,6 +20,11 @@ compTopLevel(x,m,e) ==
   $compTimeSum: local := 0
   $resolveTimeSum: local := 0
   $packagesUsed: local := []
+  -- This hashtable is a performance improvement by Waldek Hebisch
+  $envHashTable: local := MAKE_-HASHTABLE 'EQUAL
+  for u in CAR(CAR(e)) repeat
+   for v in CDR(u) repeat
+    HPUT($envHashTable,[CAR u, CAR v],true)
   -- The next line allows the new compiler to be tested interactively.
   compFun := if $newCompAtTopLevel=true then 'newComp else 'compOrCroak
   x is ["DEF",:.] or x is ["where",["DEF",:.],:.] =>
@@ -110,6 +32,9 @@ compTopLevel(x,m,e) ==
         --keep old environment after top level function defs
   FUNCALL(compFun,x,m,e)
 
+@
+\subsection{compUniquely}
+<<*>>=
 compUniquely(x,m,e) ==
   $compUniquelyIfTrue: local:= true
   CATCH("compUniquely",comp(x,m,e))
@@ -128,7 +53,7 @@ CohenCategory(): Category == SetCategory with
   construct:(CExpr,CExpr)->CExpr
     ++ construct:(CExpr,CExpr)->CExpr
 
-@
+\end{verbatim}
 the resulting call looks like:
 \begin{verbatim}
  (|compOrCroak|
@@ -156,6 +81,7 @@ The third argument, {\tt e}, is the environment.
 
 In the call to {\tt compOrCroak1} the fourth argument {\tt comp}
 is the function to call.
+\subsection{compOrCroak}
 <<*>>=
 compOrCroak(x,m,e) == compOrCroak1(x,m,e,'comp)
 
@@ -211,6 +137,8 @@ The fourth argument {\tt comp} is the function to call.
 The inner function augments the environment with information
 from the compiler stack {\tt \$compStack} and
 {\tt \$compErrorMessageStack}.
+
+\subsection{compOrCroak1}
 <<*>>=
 compOrCroak1(x,m,e,compFn) ==
   fn(x,m,e,nil,nil,compFn) where
@@ -237,16 +165,25 @@ compOrCroak1(x,m,e,compFn) ==
       displayComp $level
       userError errorMessage
 
+@
+\subsection{tc}
+<<*>>=
 tc() ==
   $tripleCache:= nil
   comp($x,$m,$f)
 
 
+@
+\subsection{comp}
+<<*>>=
 comp(x,m,e) ==
   T:= compNoStacking(x,m,e) => ($compStack:= nil; T)
   $compStack:= [[x,m,e,$exitModeStack],:$compStack]
   nil
 
+@
+\subsection{compNoStacking}
+<<*>>=
 compNoStacking(x,m,e) ==
   T:= comp2(x,m,e) =>
     (m=$EmptyMode and T.mode=$Representation => [T.expr,"$",T.env]; T)
@@ -255,11 +192,17 @@ compNoStacking(x,m,e) ==
          --preferred to the underlying representation -- RDJ 9/12/83
   compNoStacking1(x,m,e,$compStack)
 
+@
+\subsection{compNoStacking1}
+<<*>>=
 compNoStacking1(x,m,e,$compStack) ==
   u:= get(if m="$" then "Rep" else m,"value",e) =>
     (T:= comp2(x,u.expr,e) => [T.expr,m,T.env]; nil)
   nil
 
+@
+\subsection{comp2}
+<<*>>=
 comp2(x,m,e) ==
   [y,m',e]:= comp3(x,m,e) or return nil
   if $LISPLIB and isDomainForm(x,e) then
@@ -272,6 +215,9 @@ comp2(x,m,e) ==
         --$bootStrapMode-test necessary for compiling Ring in $bootStrapMode
   [y,m',e]
 
+@
+\subsection{comp3}
+<<*>>=
 comp3(x,m,$e) ==
   --returns a Triple or %else nil to signalcan't do'
   $e:= addDomain(m,$e)
@@ -292,18 +238,27 @@ comp3(x,m,$e) ==
     [x',m',addDomain(m',e')]
   t
 
+@
+\subsection{compTypeOf}
+<<*>>=
 compTypeOf(x:=[op,:argl],m,e) ==
   $insideCompTypeOf: local := true
   newModemap:= EQSUBSTLIST(argl,$FormalMapVariableList,get(op,'modemap,e))
   e:= put(op,'modemap,newModemap,e)
   comp3(x,m,e)
 
+@
+\subsection{hasFormalMapVariable}
+<<*>>=
 hasFormalMapVariable(x, vl) ==
   $formalMapVariables: local := vl
   null vl => false
   ScanOrPairVec('hasone?,x) where
      hasone? x == MEMQ(x,$formalMapVariables)
 
+@
+\subsection{compWithMappingMode}
+<<*>>=
 compWithMappingMode(x,m is ["Mapping",m',:sl],oldE) ==
   $killOptimizeIfTrue: local:= true
   e:= oldE
@@ -400,6 +355,9 @@ compWithMappingMode(x,m is ["Mapping",m',:sl],oldE) ==
     ['LIST,fname]
   [uu,m,oldE]
 
+@
+\subsection{extractCodeAndConstructTriple}
+<<*>>=
 extractCodeAndConstructTriple(u, m, oldE) ==
   u is ["call",fn,:.] =>
     if fn is ["applyFun",a] then fn := a
@@ -407,12 +365,18 @@ extractCodeAndConstructTriple(u, m, oldE) ==
   [op,:.,env] := u
   [["CONS",["function",op],env],m,oldE]
 
+@
+\subsection{compExpression}
+<<*>>=
 compExpression(x,m,e) ==
   $insideExpressionIfTrue: local:= true
   atom first x and (fn:= GET(first x,"SPECIAL")) =>
     FUNCALL(fn,x,m,e)
   compForm(x,m,e)
 
+@
+\subsection{compAtom}
+<<*>>=
 compAtom(x,m,e) ==
   T:= compAtomWithModemap(x,m,e,get(x,"modemap",e)) => T
   x="nil" =>
@@ -428,6 +392,9 @@ compAtom(x,m,e) ==
     [x,primitiveType x or return nil,e]
   convert(t,m)
 
+@
+\subsection{primitiveType}
+<<*>>=
 primitiveType x ==
   x is nil => $EmptyMode
   STRINGP x => $String
@@ -438,6 +405,9 @@ primitiveType x ==
   FLOATP x => $DoubleFloat
   nil
 
+@
+\subsection{compSymbol}
+<<*>>=
 compSymbol(s,m,e) ==
   s="$NoValue" => ["$NoValue",$NoValueMode,e]
   isFluid s => [s,getmode(s,e) or return nil,e]
@@ -458,14 +428,23 @@ compSymbol(s,m,e) ==
   m = $Expression or m = $Symbol => [['QUOTE,s],m,e]
   not isFunction(s,e) => errorRef s
 
+@
+\subsection{convertOrCroak}
+<<*>>=
 convertOrCroak(T,m) ==
   u:= convert(T,m) => u
   userError ["CANNOT CONVERT: ",T.expr,"%l"," OF MODE: ",T.mode,"%l",
     " TO MODE: ",m,"%l"]
 
+@
+\subsection{convert}
+<<*>>=
 convert(T,m) ==
   coerce(T,resolve(T.mode,m) or return nil)
 
+@
+\subsection{mkUnion}
+<<*>>=
 mkUnion(a,b) ==
   b="$" and $Rep is ["Union",:l] => b
   a is ["Union",:l] =>
@@ -474,10 +453,16 @@ mkUnion(a,b) ==
   b is ["Union",:l] => ["Union",:setUnion([a],l)]
   ["Union",a,b]
 
+@
+\subsection{maxSuperType}
+<<*>>=
 maxSuperType(m,e) ==
   typ:= get(m,"SuperDomain",e) => maxSuperType(typ,e)
   m
 
+@
+\subsection{hasType}
+<<*>>=
 hasType(x,e) ==
   fn get(x,"condition",e) where
     fn x ==
@@ -485,12 +470,18 @@ hasType(x,e) ==
       x is [["case",.,y],:.] => y
       fn rest x
 
+@
+\subsection{compForm}
+<<*>>=
 compForm(form,m,e) ==
   T:=
     compForm1(form,m,e) or compArgumentsAndTryAgain(form,m,e) or return
       stackMessageIfNone ["cannot compile","%b",form,"%d"]
   T
 
+@
+\subsection{compArgumentsAndTryAgain}
+<<*>>=
 compArgumentsAndTryAgain(form is [.,:argl],m,e) ==
   -- used in case: f(g(x)) where f is in domain introduced by
   -- comping g, e.g. for (ELT (ELT x a) b), environment can have no
@@ -501,6 +492,9 @@ compArgumentsAndTryAgain(form is [.,:argl],m,e) ==
   u="failed" => nil
   compForm1(form,m,e)
 
+@
+\subsection{outputComp}
+<<*>>=
 outputComp(x,e) ==
   u:=comp(['_:_:,x,$Expression],$Expression,e) => u
   x is ['construct,:argl] =>
@@ -509,6 +503,9 @@ outputComp(x,e) ==
     [['coerceUn2E,x,v.mode],$Expression,e]
   [x,$Expression,e]
 
+@
+\subsection{compForm1}
+<<*>>=
 compForm1(form is [op,:argl],m,e) ==
   $NumberOfArgsIfInteger: local:= #argl --see compElt
   op="error" =>
@@ -537,11 +534,17 @@ compForm1(form is [op,:argl],m,e) ==
   (mmList:= getFormModemaps(form,e)) and (T:= compForm2(form,m,e,mmList)) => T
   compToApply(op,argl,m,e)
 
+@
+\subsection{compExpressionList}
+<<*>>=
 compExpressionList(argl,m,e) ==
   Tl:= [[.,.,e]:= comp(x,$Expression,e) or return "failed" for x in argl]
   Tl="failed" => nil
   convert([["LIST",:[y.expr for y in Tl]],$Expression,e],m)
 
+@
+\subsection{compForm2}
+<<*>>=
 compForm2(form is [op,:argl],m,e,modemapList) ==
   sargl:= TAKE(# argl, $TriangleVariableList)
   aList:= [[sa,:a] for a in argl for sa in sargl]
@@ -569,10 +572,16 @@ compForm2(form is [op,:argl],m,e,modemapList) ==
       compForm3(form,m,e,modemapList)
   compForm3(form,m,e,modemapList)
 
+@
+\subsection{compFormPartiallyBottomUp}
+<<*>>=
 compFormPartiallyBottomUp(form,m,e,modemapList,partialModeList) ==
   mmList:= [mm for mm in modemapList | compFormMatch(mm,partialModeList)] =>
     compForm3(form,m,e,mmList)
 
+@
+\subsection{compFormMatch}
+<<*>>=
 compFormMatch(mm,partialModeList) ==
   mm is [[.,.,:argModeList],:.] and match(argModeList,partialModeList) where
     match(a,b) ==
@@ -580,6 +589,9 @@ compFormMatch(mm,partialModeList) ==
       null first b => match(rest a,rest b)
       first a=first b and match(rest a,rest b)
 
+@
+\subsection{compForm3}
+<<*>>=
 compForm3(form is [op,:argl],m,e,modemapList) ==
   T:=
     or/
@@ -591,6 +603,9 @@ compForm3(form is [op,:argl],m,e,modemapList) ==
     T
   T
 
+@
+\subsection{getFormModemaps}
+<<*>>=
 getFormModemaps(form is [op,:argl],e) ==
   op is ["elt",domain,op1] =>
     [x for x in getFormModemaps([op1,:argl],e) | x is [[ =domain,:.],:.]]
@@ -609,12 +624,18 @@ getFormModemaps(form is [op,:argl],e) ==
     stackMessage ["no modemap for","%b",op,"%d","with ",nargs," arguments"]
   finalModemapList
 
+@
+\subsection{getConstructorFormOfMode}
+<<*>>=
 getConstructorFormOfMode(m,e) ==
   isConstructorForm m => m
   if m="$" then m:= "Rep"
   atom m and get(m,"value",e) is [v,:.] =>
     isConstructorForm v => v
 
+@
+\subsection{getConstructorMode}
+<<*>>=
 getConstructorMode(x,e) ==
   atom x => (u:= getmode(x,e) or return nil; getConstructorFormOfMode(u,e))
   x is ["elt",y,a] =>
@@ -624,8 +645,14 @@ getConstructorMode(x,e) ==
     u is ["Record",:l] =>
       (or/[p is [., =a,R] for p in l]) and isConstructorForm R => R
 
+@
+\subsection{isConstructorForm}
+<<*>>=
 isConstructorForm u == u is [name,:.] and MEMBER(name,'(Record Vector List))
 
+@
+\subsection{eltModemapFilter}
+<<*>>=
 eltModemapFilter(name,mmList,e) ==
   isConstantId(name,e) =>
     l:= [mm for mm in mmList | mm is [[.,.,.,sel,:.],:.] and sel=name] => l
@@ -634,6 +661,9 @@ eltModemapFilter(name,mmList,e) ==
     nil
   mmList
 
+@
+\subsection{seteltModemapFilter}
+<<*>>=
 seteltModemapFilter(name,mmList,e) ==
   isConstantId(name,e) =>
     l:= [mm for (mm:= [[.,.,.,sel,:.],:.]) in mmList | sel=name] => l
@@ -642,6 +672,9 @@ seteltModemapFilter(name,mmList,e) ==
     nil
   mmList
 
+@
+\subsection{substituteIntoFunctorModemap}
+<<*>>=
 substituteIntoFunctorModemap(argl,modemap is [[dc,:sig],:.],e) ==
   #dc^=#sig =>
     keyedSystemError("S2GE0016",['"substituteIntoFunctorModemap",
@@ -655,14 +688,22 @@ substituteIntoFunctorModemap(argl,modemap is 
[[dc,:sig],:.],e) ==
     [SUBLIS(substitutionList,modemap),e]
   nil
 
---% SPECIAL EVALUATION FUNCTIONS
+@
 
+\section{Special evaluation functions}
+\subsection{compConstructorCategory}
+<<*>>=
 compConstructorCategory(x,m,e) == [x,resolve($Category,m),e]
 
+@
+\subsection{compString}
+<<*>>=
 compString(x,m,e) == [x,resolve($StringCategory,m),e]
 
---% SUBSET CATEGORY
-
+@
+\subsection{compSubsetCategory}
+Compile SubsetCategory
+<<*>>=
 compSubsetCategory(["SubsetCategory",cat,R],m,e) ==
   --1. put "Subsets" property on R to allow directly coercion to subset;
   --   allow automatic coercion from subset to R but not vice versa
@@ -675,10 +716,15 @@ compSubsetCategory(["SubsetCategory",cat,R],m,e) ==
           ["CATEGORY","domain",["SIGNATURE","coerce",[R,"$"]],["SIGNATURE",
             "lift",[R,"$"]],["SIGNATURE","reduce",["$",R]]]
 
---% CONS
-
+@
+\subsection{compCons}
+Compile cons
+<<*>>=
 compCons(form,m,e) == compCons1(form,m,e) or compForm(form,m,e)
 
+@
+\subsection{compCons1}
+<<*>>=
 compCons1(["CONS",x,y],m,e) ==
   [x,mx,e]:= comp(x,$EmptyMode,e) or return nil
   null y => convert([["LIST",x],["List",mx],e],m)
@@ -693,10 +739,15 @@ compCons1(["CONS",x,y],m,e) ==
     [["CONS",x,y],["Pair",mx,my],e]
   convert(T,m)
 
---% SETQ
-
+@
+\subsection{compSetq}
+Compile setq
+<<*>>=
 compSetq(["LET",form,val],m,E) == compSetq1(form,val,m,E)
 
+@
+\subsection{compSetq1}
+<<*>>=
 compSetq1(form,val,m,E) ==
   IDENTP form => setqSingle(form,val,m,E)
   form is [":",x,y] =>
@@ -707,13 +758,23 @@ compSetq1(form,val,m,E) ==
     op="Tuple" => setqMultiple(l,val,m,E)
     setqSetelt(form,val,m,E)
 
+@
+\subsection{compMakeDeclaration}
+<<*>>=
 compMakeDeclaration(x,m,e) ==
   $insideExpressionIfTrue: local
   compColon(x,m,e)
 
+@
+\subsection{setqSetelt}
+Compile setelt
+<<*>>=
 setqSetelt([v,:s],val,m,E) ==
   comp(["setelt",v,:s,val],m,E)
 
+@
+\subsection{setqSingle}
+<<*>>=
 setqSingle(id,val,m,E) ==
   $insideSetqSingleIfTrue: local:= true
     --used for comping domain forms within functions
@@ -756,6 +817,9 @@ setqSingle(id,val,m,E) ==
             (isDomainForm(x,e') => ['ELT,id,0];CAR outputComp(id,e'))]
   [form,m',e']
 
+@
+\subsection{assignError}
+<<*>>=
 assignError(val,m',form,m) ==
   message:=
     val =>
@@ -764,6 +828,9 @@ assignError(val,m',form,m) ==
     ["CANNOT ASSIGN: ",val,"%l","   TO: ",form,"%l","   OF MODE: ",m]
   stackMessage message
 
+@
+\subsection{setqMultiple}
+<<*>>=
 setqMultiple(nameList,val,m,e) ==
   val is ["CONS",:.] and m=$NoValueMode =>
     setqMultipleExplicit(nameList,uncons val,m,e)
@@ -796,6 +863,9 @@ setqMultiple(nameList,val,m,e) ==
   if assignList="failed" then NIL
   else [MKPROGN [x,:assignList,g],m',e]
 
+@
+\subsection{setqMultipleExplicit}
+<<*>>=
 setqMultipleExplicit(nameList,valList,m,e) ==
   #nameList^=#valList =>
     stackMessage ["Multiple assignment error; # of items in: ",nameList,
@@ -813,7 +883,10 @@ setqMultipleExplicit(nameList,valList,m,e) ==
   [["PROGN",:[T.expr for T in assignList],:[T.expr for T in reAssignList]],
     $NoValueMode, (LAST reAssignList).env]
 
---% WHERE
+@
+\subsection{compWhere}
+Compile where
+<<*>>=
 compWhere([.,form,:exprList],m,eInit) ==
   $insideExpressionIfTrue: local:= false
   $insideWhereIfTrue: local:= true
@@ -829,6 +902,10 @@ compWhere([.,form,:exprList],m,eInit) ==
     eInit
   [x,m,eFinal]
 
+@
+\subsection{compConstruct}
+Compile construct
+<<*>>=
 compConstruct(form is ["construct",:l],m,e) ==
   y:= modeIsAggregateOf("List",m,e) =>
     T:= compList(l,["List",CADR y],e) => convert(T,m)
@@ -845,26 +922,90 @@ compConstruct(form is ["construct",:l],m,e) ==
       (T:= compVector(l,["Vector",CADR y],e)) and (T':= convert(T,m)) =>
          return T'
 
+@
+\subsection{compQuote}
+Compile quote
+<<*>>=
 compQuote(expr,m,e) == [expr,m,e]
 
+@
+\subsection{compList}
+Compile list
+<<*>>=
 compList(l,m is ["List",mUnder],e) ==
   null l => [NIL,m,e]
   Tl:= [[.,mUnder,e]:= comp(x,mUnder,e) or return "failed" for x in l]
   Tl="failed" => nil
   T:= [["LIST",:[T.expr for T in Tl]],["List",mUnder],e]
 
+@
+\subsection{compVector}
+Compile vector
+<<*>>=
 compVector(l,m is ["Vector",mUnder],e) ==
   null l => [$EmptyVector,m,e]
   Tl:= [[.,mUnder,e]:= comp(x,mUnder,e) or return "failed" for x in l]
   Tl="failed" => nil
   [["VECTOR",:[T.expr for T in Tl]],m,e]
 
---% MACROS
-<<compMacro>>
---% SEQ
+@
+\subsection{compMacro}
+The compMacro function does macro expansion during spad file compiles.
+If a macro occurs twice in the same file the macro expands infinitely
+causing a stack overflow. The reason for the infinite recursion is that
+the left hand side of the macro definition is expanded. Thus defining
+a macro:
+\begin{verbatim}
+name ==> 1
+\end{verbatim}
+will expand properly the first time. The second time it turns into:
+\begin{verbatim}
+1 ==> 1
+\end{verbatim}
+The original code read:
+\begin{verbatim}
+compMacro(form,m,e) ==
+  $macroIfTrue: local:= true
+  ["MDEF",lhs,signature,specialCases,rhs]:= form
+  rhs :=
+    rhs is ['CATEGORY,:.] => ['"-- the constructor category"]
+    rhs is ['Join,:.]     => ['"-- the constructor category"]
+    rhs is ['CAPSULE,:.]  => ['"-- the constructor capsule"]
+    rhs is ['add,:.]      => ['"-- the constructor capsule"]
+    formatUnabbreviated rhs
+  sayBrightly ['"   processing macro definition",'%b,
+    :formatUnabbreviated lhs,'" ==> ",:rhs,'%d]
+  ["MDEF",lhs,signature,specialCases,rhs]:= form:= macroExpand(form,e)
+  m=$EmptyMode or m=$NoValueMode =>
+    ["/throwAway",$NoValueMode,put(first lhs,"macro",rhs,e)]
 
+\end{verbatim}
+Juergen Weiss proposed the following fixed code. This does not expand
+the left hand side of the macro.
+<<*>>=
+compMacro(form,m,e) ==
+  $macroIfTrue: local:= true
+  ["MDEF",lhs,signature,specialCases,rhs]:= form
+  prhs :=
+    rhs is ['CATEGORY,:.] => ['"-- the constructor category"]
+    rhs is ['Join,:.]     => ['"-- the constructor category"]
+    rhs is ['CAPSULE,:.]  => ['"-- the constructor capsule"]
+    rhs is ['add,:.]      => ['"-- the constructor capsule"]
+    formatUnabbreviated rhs
+  sayBrightly ['"   processing macro definition",'%b,
+    :formatUnabbreviated lhs,'" ==> ",:prhs,'%d]
+  m=$EmptyMode or m=$NoValueMode =>
+    ["/throwAway",$NoValueMode,put(first lhs,"macro",macroExpand(rhs,e),e)]
+
+@
+\subsection{compSeq}
+Compile seq
+<<*>>=
 compSeq(["SEQ",:l],m,e) == compSeq1(l,[m,:$exitModeStack],e)
 
+@
+\subsection{compSeq1}
+<<*>>=
 compSeq1(l,$exitModeStack,e) ==
   $insideExpressionIfTrue: local
   $finalEnv: local
@@ -882,8 +1023,14 @@ compSeq1(l,$exitModeStack,e) ==
   form:= ["SEQ",:replaceExitEtc(c,catchTag,"TAGGEDexit",$exitModeStack.(0))]
   [["CATCH",catchTag,form],$exitModeStack.(0),$finalEnv]
 
+@
+\subsection{compSeqItem}
+<<*>>=
 compSeqItem(x,m,e) == comp(macroExpand(x,e),m,e)
 
+@
+\subsection{replaceExitEtc}
+<<*>>=
 replaceExitEtc(x,tag,opFlag,opMode) ==
   (fn(x,tag,opFlag,opMode); x) where
     fn(x,tag,opFlag,opMode) ==
@@ -905,15 +1052,20 @@ replaceExitEtc(x,tag,opFlag,opMode) ==
       replaceExitEtc(first x,tag,opFlag,opMode)
       replaceExitEtc(rest x,tag,opFlag,opMode)
 
---% SUCHTHAT
+@
+\subsection{compSuchthat}
+Compile suchthat
+<<*>>=
 compSuchthat([.,x,p],m,e) ==
   [x',m',e]:= comp(x,m,e) or return nil
   [p',.,e]:= comp(p,$Boolean,e) or return nil
   e:= put(x',"condition",p',e)
   [x',m',e]
 
---% exit
-
+@
+\subsection{compExit}
+Compile exit
+<<*>>=
 compExit(["exit",level,x],m,e) ==
   index:= level-1
   $exitModeStack = [] => comp(x,m,e)
@@ -925,20 +1077,29 @@ compExit(["exit",level,x],m,e) ==
   modifyModeStack(m',index)
   [["TAGGEDexit",index,u],m,e]
 
+@
+\subsection{modifyModeStack}
+<<*>>=
 modifyModeStack(m,index) ==
   $reportExitModeStack =>
     SAY("exitModeStack: ",COPY $exitModeStack," ====> ",
       ($exitModeStack.index:= resolve(m,$exitModeStack.index); $exitModeStack))
   $exitModeStack.index:= resolve(m,$exitModeStack.index)
 
+@
+\subsection{compLeave}
+Compile leave
+<<*>>=
 compLeave(["leave",level,x],m,e) ==
   index:= #$exitModeStack-1-$leaveLevelStack.(level-1)
   [x',m',e']:= u:= comp(x,$exitModeStack.index,e) or return nil
   modifyModeStack(m',index)
   [["TAGGEDexit",index,u],m,e]
 
---% return
-
+@
+\subsection{compReturn}
+Compile return
+<<*>>=
 compReturn(["return",level,x],m,e) ==
   null $exitModeStack =>
     stackSemanticError(["the return before","%b",x,"%d","is unneccessary"],nil)
@@ -952,8 +1113,10 @@ compReturn(["return",level,x],m,e) ==
     modifyModeStack(m',index)
   [["TAGGEDreturn",0,u],m,e']
 
---% ELT
-
+@
+\subsection{compElt}
+Compile Elt
+<<*>>=
 compElt(form,m,E) ==
   form isnt ["elt",aDomain,anOp] => compForm(form,m,E)
   aDomain="Lisp" =>
@@ -979,8 +1142,10 @@ compElt(form,m,E) ==
     convert([["call",val],first rest sig,E], m) --implies fn calls used to 
access constants
   compForm(form,m,E)
 
---% HAS
-
+@
+\subsection{compHas}
+Compile has
+<<*>>=
 compHas(pred is ["has",a,b],m,$e) ==
   --b is (":",:.) => (.,.,E):= comp(b,$EmptyMode,E)
   $e:= chaseInferences(pred,$e)
@@ -990,6 +1155,9 @@ compHas(pred is ["has",a,b],m,$e) ==
 
       --used in various other places to make the discrimination
 
+@
+\subsection{compHasFormat}
+<<*>>=
 compHasFormat (pred is ["has",olda,b]) ==
   argl := rest $form
   formals := TAKE(#argl,$FormalMapVariableList)
@@ -1003,8 +1171,10 @@ compHasFormat (pred is ["has",olda,b]) ==
   isDomainForm(b,$EmptyEnvironment) => ["EQUAL",a,b]
   ["HasCategory",a,mkDomainConstructor b]
 
---% IF
-
+@
+\subsection{compIf}
+Compile if
+<<*>>=
 compIf(["IF",a,b,c],m,E) ==
   [xa,ma,Ea,Einv]:= compBoolean(a,$Boolean,E) or return nil
   [xb,mb,Eb]:= Tb:= compFromIf(b,m,Ea) or return nil
@@ -1019,6 +1189,9 @@ compIf(["IF",a,b,c],m,E) ==
       E
   [x,mc,returnEnv]
 
+@
+\subsection{canReturn}
+<<*>>=
 canReturn(expr,level,exitCount,ValueFlag) ==  --SPAD: exit and friends
   atom expr => ValueFlag and level=exitCount
   (op:= first expr)="QUOTE" => ValueFlag and level=exitCount
@@ -1056,10 +1229,16 @@ canReturn(expr,level,exitCount,ValueFlag) ==  --SPAD: 
exit and friends
     and/[canReturn(u,level,exitCount,ValueFlag) for u in expr]
   systemErrorHere '"canReturn" --for the time being
 
+@
+\subsection{compBoolean}
+<<*>>=
 compBoolean(p,m,E) ==
   [p',m,E]:= comp(p,m,E) or return nil
   [p',m,getSuccessEnvironment(p,E),getInverseEnvironment(p,E)]
 
+@
+\subsection{getSuccessEnvironment}
+<<*>>=
 getSuccessEnvironment(a,e) ==
 
   -- the next four lines try to ensure that explicit special-case tests
@@ -1079,6 +1258,9 @@ getSuccessEnvironment(a,e) ==
     put(x,"condition",[a,:get(x,"condition",e)],e)
   e
 
+@
+\subsection{getInverseEnvironment}
+<<*>>=
 getInverseEnvironment(a,E) ==
   atom a => E
   [op,:argl]:= a
@@ -1101,12 +1283,18 @@ getInverseEnvironment(a,E) ==
     put(x,"condition",[newpred,:get(x,"condition",E)],E)
   E
 
+@
+\subsection{getUnionMode}
+<<*>>=
 getUnionMode(x,e) ==
   m:=
     atom x => getmode(x,e)
     return nil
   isUnionMode(m,e)
 
+@
+\subsection{isUnionMode}
+<<*>>=
 isUnionMode(m,e) ==
   m is ["Union",:.] => m
   (m':= getmode(m,e)) is ["Mapping",["UnionCategory",:.]] => CADR m'
@@ -1114,30 +1302,45 @@ isUnionMode(m,e) ==
     (v.expr is ["Union",:.] => v.expr; nil)
   nil
 
+@
+\subsection{compFromIf}
+<<*>>=
 compFromIf(a,m,E) ==
   a="noBranch" => ["noBranch",m,E]
   true => comp(a,m,E)
 
+@
+\subsection{quotify}
+<<*>>=
 quotify x == x
 
+@
+\subsection{compImport}
+<<*>>=
 compImport(["import",:doms],m,e) ==
   for dom in doms repeat e:=addDomain(dom,e)
   ["/throwAway",$NoValueMode,e]
 
---Will the jerk who commented out these two functions please NOT do so
---again.  These functions ARE needed, and case can NOT be done by
---modemap alone.  The reason is that A case B requires to take A
---evaluated, but B unevaluated.  Therefore a special function is
---required.  You may have thought that you had tested this on "failed"
---etc., but "failed" evaluates to it's own mode.  Try it on x case $
---next time.
---                An angry JHD - August 15th., 1984
-
+@
+\subsection{compCase}
+Will the jerk who commented out these two functions please NOT do so
+again.  These functions ARE needed, and case can NOT be done by
+modemap alone.  The reason is that A case B requires to take A
+evaluated, but B unevaluated.  Therefore a special function is
+required.  You may have thought that you had tested this on ``failed''
+etc., but ``failed'' evaluates to it's own mode.  Try it on x case \$
+next time.
+
+An angry JHD - August 15th., 1984
+<<*>>=
 compCase(["case",x,m'],m,e) ==
   e:= addDomain(m',e)
   T:= compCase1(x,m',e) => coerce(T,m)
   nil
 
+@
+\subsection{compCase1}
+<<*>>=
 compCase1(x,m,e) ==
   [x',m',e']:= comp(x,$EmptyMode,e) or return nil
   u:=
@@ -1147,6 +1350,9 @@ compCase1(x,m,e) ==
   fn:= (or/[selfn for [cond,selfn] in u | cond=true]) or return nil
   [["call",fn,x'],$Boolean,e']
 
+@
+\subsection{compColon}
+<<*>>=
 compColon([":",f,t],m,e) ==
   $insideExpressionIfTrue=true => compColonInside(f,m,e,t)
     --if inside an expression, ":" means to convert to m "on faith"
@@ -1177,12 +1383,18 @@ compColon([":",f,t],m,e) ==
         e:= put(f,"value",[genSomeVariable(),t,$noEnv],e)
   ["/throwAway",getmode(f,e),e]
 
+@
+\subsection{unknownTypeError}
+<<*>>=
 unknownTypeError name ==
   name:=
     name is [op,:.] => op
     name
   stackSemanticError(["%b",name,"%d","is not a known type"],nil)
 
+@
+\subsection{compPretend}
+<<*>>=
 compPretend(["pretend",x,t],m,e) ==
   e:= addDomain(t,e)
   T:= comp(x,t,e) or comp(x,$EmptyMode,e) or return nil
@@ -1192,6 +1404,9 @@ compPretend(["pretend",x,t],m,e) ==
   T:= [T.expr,t,T.env]
   T':= coerce(T,m) => (if warningMessage then stackWarning warningMessage; T')
 
+@
+\subsection{compColonInside}
+<<*>>=
 compColonInside(x,m,e,m') ==
   e:= addDomain(m',e)
   T:= comp(x,$EmptyMode,e) or return nil
@@ -1208,19 +1423,23 @@ compColonInside(x,m,e,m') ==
          stackWarning [":",m'," -- should replace by pretend"]
     T'
 
+@
+\subsection{compIs}
+<<*>>=
 compIs(["is",a,b],m,e) ==
   [aval,am,e] := comp(a,$EmptyMode,e) or return nil
   [bval,bm,e] := comp(b,$EmptyMode,e) or return nil
   T:= [["domainEqual",aval,bval],$Boolean,e]
   coerce(T,m)
 
---%  Functions for coercion by the compiler
-
---  The function coerce is used by the old compiler for coercions.
---  The function coerceInteractive is used by the interpreter.
---  One should always call the correct function, since the represent-
---  ation of basic objects may not be the same.
-
+@
+\section{Functions for coercion by the compiler}
+\subsection{coerce}
+The function coerce is used by the old compiler for coercions.
+The function coerceInteractive is used by the interpreter.
+One should always call the correct function, since the representation 
+of basic objects may not be the same.
+<<*>>=
 coerce(T,m) ==
   $InteractiveMode =>
     keyedSystemError("S2GE0016",['"coerce",
@@ -1237,6 +1456,9 @@ coerce(T,m) ==
       ["Cannot coerce","%b",x,"%d","%l","      of mode","%b",m1,"%d","%l",
         "      to mode","%b",m2,"%d"]
 
+@
+\subsection{coerceEasy}
+<<*>>=
 coerceEasy(T,m) ==
   m=$EmptyMode => T
   m=$NoValueMode or m=$Void => [T.expr,m,T.env]
@@ -1248,6 +1470,9 @@ coerceEasy(T,m) ==
   T.mode=$EmptyMode or modeEqualSubst(T.mode,m,T.env) =>
     [T.expr,m,T.env]
 
+@
+\subsection{coerceSubset}
+<<*>>=
 coerceSubset([x,m,e],m') ==
   isSubset(m,m',e) or m="Rep" and m'="$" => [x,m',e]
   m is ['SubDomain,=m',:.] => [x,m',e]
@@ -1259,6 +1484,9 @@ coerceSubset([x,m,e],m') ==
       [x,m',e]
   nil
 
+@
+\subsection{coerceHard}
+<<*>>=
 coerceHard(T,m) ==
   $e: local:= T.env
   m':= T.mode
@@ -1275,6 +1503,9 @@ coerceHard(T,m) ==
       coerceExtraHard(T,m)
   coerceExtraHard(T,m)
 
+@
+\subsection{coerceExtraHard}
+<<*>>=
 coerceExtraHard(T is [x,m',e],m) ==
   T':= autoCoerceByModemap(T,m) => T'
   isUnionMode(m',e) is ["Union",:l] and (t:= hasType(x,e)) and
@@ -1284,6 +1515,9 @@ coerceExtraHard(T is [x,m',e],m) ==
       [['coerceRe2E,x,['ELT,COPY m',0]],m,e]
   nil
 
+@
+\subsection{coerceable}
+<<*>>=
 coerceable(m,m',e) ==
   m=m' => m
   -- must find any free parameters in m
@@ -1291,16 +1525,25 @@ coerceable(m,m',e) ==
   coerce(["$fromCoerceable$",m,e],m') => m'
   nil
 
+@
+\subsection{coerceExit}
+<<*>>=
 coerceExit([x,m,e],m') ==
   m':= resolve(m,m')
   x':= replaceExitEtc(x,catchTag:= MKQ GENSYM(),"TAGGEDexit",$exitMode)
   coerce([["CATCH",catchTag,x'],m,e],m')
 
+@
+\subsection{compAtSign}
+<<*>>=
 compAtSign(["@",x,m'],m,e) ==
   e:= addDomain(m',e)
   T:= comp(x,m',e) or return nil
   coerce(T,m)
 
+@
+\subsection{compCoerce}
+<<*>>=
 compCoerce(["::",x,m'],m,e) ==
   e:= addDomain(m',e)
   T:= compCoerce1(x,m',e) => coerce(T,m)
@@ -1308,6 +1551,9 @@ compCoerce(["::",x,m'],m,e) ==
     T:= (or/[compCoerce1(x,m1,e) for m1 in l]) or return nil
     coerce([T.expr,m',T.env],m)
 
+@
+\subsection{compCoerce1}
+<<*>>=
 compCoerce1(x,m',e) ==
   T:= comp(x,m',e) or comp(x,$EmptyMode,e) or return nil
   m1:=
@@ -1323,6 +1569,9 @@ compCoerce1(x,m',e) ==
     code:= ['PROG1,['LET,gg,T.expr], ['check_-subtype,pred,MKQ m',gg]]
     [code,m',T.env]
 
+@
+\subsection{coerceByModemap}
+<<*>>=
 coerceByModemap([x,m,e],m') ==
 --+ modified 6/27 for new runtime system
   u:=
@@ -1337,6 +1586,9 @@ coerceByModemap([x,m,e],m') ==
     genDeltaEntry ['coerce,:mm]
   [["call",fn,x],m',e]
 
+@
+\subsection{autoCoerceByModemap}
+<<*>>=
 autoCoerceByModemap([x,source,e],target) ==
   u:=
     [cexpr
@@ -1351,9 +1603,12 @@ autoCoerceByModemap([x,source,e],target) ==
       "      to: ",target," without a case statement"]
   [["call",fn,x],target,e]
 
---% Very old resolve
--- should only be used in the old (preWATT) compiler
 
+@
+\subsection{resolve}
+Very old resolve
+should only be used in the old (preWATT) compiler
+<<*>>=
 resolve(din,dout) ==
   din=$NoValueMode or dout=$NoValueMode => $NoValueMode
   dout=$EmptyMode => din
@@ -1363,6 +1618,9 @@ resolve(din,dout) ==
     mkUnion(din,dout)
   dout
 
+@
+\subsection{modeEqual}
+<<*>>=
 modeEqual(x,y) ==
   -- this is the late modeEqual
   -- orders Unions
@@ -1379,6 +1637,9 @@ modeEqual(x,y) ==
     true
   (and/[modeEqual(u,v) for u in x for v in y])
 
+@
+\subsection{modeEqualSubst}
+<<*>>=
 modeEqualSubst(m1,m,e) ==
   modeEqual(m1, m) => true
   atom m1 => get(m1,"value",e) is [m',:.] and modeEqual(m',m)
@@ -1389,10 +1650,9 @@ modeEqualSubst(m1,m,e) ==
         and/[modeEqualSubst(xm1,xm2,e) for xm1 in l1 for xm2 in l2]
   nil
 
---% Things to support )compile
-
 @
 \section{)compile}
+This is the implementation of the )compile command.
 
 You use this command to invoke the new Axiom library compiler or the
 old Axiom system compiler.  The {\tt )compile} system command is
@@ -1701,8 +1961,8 @@ with a {\tt .lsp} file, the Lisp file is compiled and 
{\tt )library}
 is called. For Aldor, You must also have present a {\tt .asy}
 generated from the same source file.
 
+\subsection{compileSpad2Cmd}
 <<*>>=
-
 compileSpad2Cmd args ==
     -- This is the old compiler
     -- Assume we entered from the "compiler" function, so args ^= nil
@@ -1801,6 +2061,9 @@ compileSpad2Cmd args ==
     terminateSystemCommand()
     spadPrompt()
 
+@
+\subsection{convertSpadToAsFile}
+<<*>>=
 convertSpadToAsFile path ==
     -- can assume path has type = .spad
     $globalMacroStack : local := nil       -- for spad -> as translator
@@ -1833,6 +2096,9 @@ convertSpadToAsFile path ==
     mkCheck()
     'done
 
+@
+\subsection{compilerDoit}
+<<*>>=
 compilerDoit(constructor, fun) ==
     $byConstructors : local := []
     $constructorsSeen : local := []
@@ -1847,6 +2113,9 @@ compilerDoit(constructor, fun) ==
         null MEMBER(ii,$constructorsSeen) =>
           sayBrightly ['">>> Warning ",'%b,ii,'%d,'" was not found"]
 
+@
+\subsection{compilerDoitWithScreenedLisplib}
+<<*>>=
 compilerDoitWithScreenedLisplib(constructor, fun) ==
     EMBED('RWRITE,
           '(LAMBDA (KEY VALUE STREAM)
@@ -1860,6 +2129,40 @@ compilerDoitWithScreenedLisplib(constructor, fun) ==
 
 
 @
+\section{License}
+<<license>>=
+-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+--     - Redistributions of source code must retain the above copyright
+--       notice, this list of conditions and the following disclaimer.
+--
+--     - Redistributions in binary form must reproduce the above copyright
+--       notice, this list of conditions and the following disclaimer in
+--       the documentation and/or other materials provided with the
+--       distribution.
+--
+--     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+--       names of its contributors may be used to endorse or promote products
+--       derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@
 \eject
 \begin{thebibliography}{99}
 \bibitem{1} nothing
diff --git a/src/interp/g-util.boot.pamphlet b/src/interp/g-util.boot.pamphlet
index 878e547..dd1e8c4 100644
--- a/src/interp/g-util.boot.pamphlet
+++ b/src/interp/g-util.boot.pamphlet
@@ -20,68 +20,52 @@ THIS CODE TO LISP AND STORE THE RESULTING LISP CODE BACK 
INTO
 THIS FILE.}
 
 See the {\bf g-util.clisp} section below.
-\section{License}
-<<license>>=
--- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
--- All rights reserved.
---
--- Redistribution and use in source and binary forms, with or without
--- modification, are permitted provided that the following conditions are
--- met:
---
---     - Redistributions of source code must retain the above copyright
---       notice, this list of conditions and the following disclaimer.
---
---     - Redistributions in binary form must reproduce the above copyright
---       notice, this list of conditions and the following disclaimer in
---       the documentation and/or other materials provided with the
---       distribution.
---
---     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
---       names of its contributors may be used to endorse or promote products
---       derived from this software without specific prior written permission.
---
--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-@
+\section{Utility Functions of General Use}
+\subsection{PPtoFile}
 <<*>>=
-<<license>>
-
---% Utility Functions of General Use
-
 PPtoFile(x, fname) ==
     stream := DEFIOSTREAM([['MODE, :'OUTPUT], ['FILE, :fname]], 80, 0)
     PRETTYPRINT(x, stream)
     SHUT stream
     x
 
--- Convert an arbitrary lisp object to canonical boolean.
+@
+\subsection{bool}
+Convert an arbitrary lisp object to canonical boolean.
+<<*>>=
 bool x ==
     NULL NULL x
 
---% Various lispy things
-
+@
+\subsection{Identity}
+<<*>>=
 Identity x == x
 
+@
+\section{Property Lists}
+\subsection{length1?}
+<<*>>=
 length1? l == PAIRP l and not PAIRP QCDR l
 
+@
+\subsection{length2?}
+<<*>>=
 length2? l == PAIRP l and PAIRP (l := QCDR l) and not PAIRP QCDR l
 
+@
+\subsection{pairList}
+<<*>>=
 pairList(u,v) == [[x,:y] for x in u for y in v]
 
--- GETALIST(alist,prop) == IFCDR assoc(prop,alist)
+@
+\subsection{GETALIST}
+<<*>>=
 GETALIST(alist,prop) == CDR assoc(prop,alist)
 
+@
+\subsection{PUTALIST}
+<<*>>=
 PUTALIST(alist,prop,val) ==
   null alist => [[prop,:val]]
   pair := assoc(prop,alist) =>
@@ -92,6 +76,9 @@ PUTALIST(alist,prop,val) ==
   QRPLACD(LASTPAIR alist,[[prop,:val]])
   alist
 
+@
+\subsection{REMALIST}
+<<*>>=
 REMALIST(alist,prop) ==
   null alist => alist
   alist is [[ =prop,:.],:r] =>
@@ -110,20 +97,28 @@ REMALIST(alist,prop) ==
     if null (l := QCDR l) or null rest l then ok := NIL
   alist
 
+@
+\section{Association Lists}
+\subsection{deleteLassoc}
+<<*>>=
 deleteLassoc(x,y) ==
   y is [[a,:.],:y'] =>
     EQ(x,a) => y'
     [first y,:deleteLassoc(x,y')]
   y
 
---% association list functions
-
+@
+\subsection{deleteAssoc}
+<<*>>=
 deleteAssoc(x,y) ==
   y is [[a,:.],:y'] =>
    a=x => deleteAssoc(x,y')
    [first y,:deleteAssoc(x,y')]
   y
 
+@
+\subsection{deleteAssocWOC}
+<<*>>=
 deleteAssocWOC(x,y) ==
   null y => y
   [[a,:.],:t]:= y
@@ -134,6 +129,9 @@ deleteAssocWOC(x,y) ==
       fn(x,t)
     nil
 
+@
+\subsection{insertWOC}
+<<*>>=
 insertWOC(x,y) ==
   null y => [x]
   (fn(x,y); y) where fn(x,y is [h,:t]) ==
@@ -143,14 +141,17 @@ insertWOC(x,y) ==
       RPLACA(y,x)
     fn(x,t)
 
-
-
---% Miscellaneous Functions for Working with Strings
-
+@
+\section{String Handling}
+\subsection{fillerSpaces}
+<<*>>=
 fillerSpaces(n,:charPart) ==
   n <= 0 => '""
   MAKE_-FULL_-CVEC(n,IFCAR charPart or '" ")
 
+@
+\subsection{centerString}
+<<*>>=
 centerString(text,width,fillchar) ==
   wid := entryWidth text
   wid >= width => text
@@ -162,6 +163,9 @@ centerString(text,width,fillchar) ==
   if f.1 ^= 0 then fill1 := STRCONC(fillchar,fill1)
   [fill1,text,fill2]
 
+@
+\subsection{stringPrefix?}
+<<*>>=
 stringPrefix?(pref,str) ==
   -- sees if the first #pref letters of str are pref
   -- replaces STRINGPREFIXP
@@ -175,6 +179,9 @@ stringPrefix?(pref,str) ==
     i := i + 1
   ok
 
+@
+\subsection{stringChar2Integer}
+<<*>>=
 stringChar2Integer(str,pos) ==
   -- replaces GETSTRINGDIGIT in UT LISP
   -- returns small integer represented by character in position pos
@@ -185,6 +192,9 @@ stringChar2Integer(str,pos) ==
   not DIGITP(d := SCHAR(str,pos)) => NIL
   DIG2FIX d
 
+@
+\subsection{dropLeadingBlanks}
+<<*>>=
 dropLeadingBlanks str ==
   str := object2String str
   l := QCSIZE str
@@ -197,13 +207,22 @@ dropLeadingBlanks str ==
   nb => SUBSTRING(str,nb,NIL)
   '""
 
+@
+\subsection{concat}
+<<*>>=
 concat(:l) == concatList l
 
+@
+\subsection{concatList}
+<<*>>=
 concatList [x,:y] ==
   null y => x
   null x => concatList y
   concat1(x,concatList y)
 
+@
+\subsection{concat1}
+<<*>>=
 concat1(x,y) ==
   null x => y
   atom x => (null y => x; atom y => [x,y]; [x,:y])
@@ -211,37 +230,58 @@ concat1(x,y) ==
   atom y => [:x,y]
   [:x,:y]
 
---% BOOT ravel and reshape
-
+@
+\section{BOOT ravel and reshape}
+\subsection{ravel}
+<<*>>=
 ravel a == a
 
+@
+\subsection{reshape}
+<<*>>=
 reshape(a,b) == a
 
---% Some functions for algebra code
-
+@
+\section{Some functions for algebra code}
+\subsection{boolODDP}
+<<*>>=
 boolODDP x == ODDP x
 
---% Miscellaneous
-
+@
+\section{Miscellaneous}
+\subsection{freeOfSharpVars}
+<<*>>=
 freeOfSharpVars x ==
   atom x => not isSharpVarWithNum x
   freeOfSharpVars first x and freeOfSharpVars rest x
 
+@
+\subsection{listOfSharpVars}
+<<*>>=
 listOfSharpVars x ==
   atom x => (isSharpVarWithNum x => LIST x; nil)
   setUnion(listOfSharpVars first x,listOfSharpVars rest x)
 
+@
+\subsection{listOfPatternIds}
+<<*>>=
 listOfPatternIds x ==
   isPatternVar x => [x]
   atom x => nil
   x is ['QUOTE,:.] => nil
   UNIONQ(listOfPatternIds first x,listOfPatternIds rest x)
 
+@
+\subsection{isPatternVar}
+<<*>>=
 isPatternVar v ==
   -- a pattern variable consists of a star followed by a star or digit(s)
   IDENTP(v) and MEMQ(v,'(_*_* _*1 _*2 _*3 _*4 _*5 _*6 _*7 _*8 _*9 _*10
     _*11 _*12 _*13 _*14 _*15 _*16 _*17 _*18 _*19 _*20)) and true
 
+@
+\subsection{removeZeroOne}
+<<*>>=
 removeZeroOne x ==
   -- replace all occurrences of (Zero) and (One) with
   -- 0 and 1
@@ -250,6 +290,9 @@ removeZeroOne x ==
   atom x => x
   [removeZeroOne first x,:removeZeroOne rest x]
 
+@
+\subsection{removeZeroOneDestructively}
+<<*>>=
 removeZeroOneDestructively t ==
   -- replace all occurrences of (Zero) and (One) with
   -- 0 and 1 destructively
@@ -259,6 +302,9 @@ removeZeroOneDestructively t ==
   RPLNODE(t,removeZeroOneDestructively first t,
     removeZeroOneDestructively rest t)
 
+@
+\subsection{flattenSexpr}
+<<*>>=
 flattenSexpr s ==
   null s => s
   ATOM s => s
@@ -266,14 +312,26 @@ flattenSexpr s ==
   ATOM f => [f,:flattenSexpr r]
   [:flattenSexpr f,:flattenSexpr r]
 
+@
+\subsection{isLowerCaseLetter}
+<<*>>=
 isLowerCaseLetter c == charRangeTest CHAR2NUM c
 
+@
+\subsection{isUpperCaseLetter}
+<<*>>=
 isUpperCaseLetter c == charRangeTest QSDIFFERENCE(CHAR2NUM c,64)
 
+@
+\subsection{isLetter}
+<<*>>=
 isLetter c ==
   n:= CHAR2NUM c
   charRangeTest n or charRangeTest QSDIFFERENCE(CHAR2NUM c,64)
 
+@
+\subsection{charRangeTest}
+<<*>>=
 charRangeTest n ==
   QSLESSP(153,n) =>
     QSLESSP(169,n) => false
@@ -285,18 +343,24 @@ charRangeTest n ==
     true
   false
 
+@
+\subsection{update}
+<<*>>=
 update() ==
   OBEY
     STRCONC('"SPADEDIT ",STRINGIMAGE _/VERSION,'" ",STRINGIMAGE _/WSNAME,'" A")
   _/UPDATE()
 
---% Inplace Merge Sort for Lists
--- MBM April/88
+@
+\section{Inplace Merge Sort for Lists}
+MBM April/88
 
--- listSort(pred,list) or listSort(pred,list,key)
--- the pred function is a boolean valued function defining the ordering
--- the key function extracts the key from an item for comparison by pred
+\verb|listSort(pred,list)| or \verb|listSort(pred,list,key)|
+The pred function is a boolean valued function defining the ordering
+the key function extracts the key from an item for comparison by pred
 
+\subsection{listSort}
+<<*>>=
 listSort(pred,list,:optional) ==
    NOT functionp pred => error "listSort: first arg must be a function"
    NOT LISTP list => error "listSort: second argument must be a list"
@@ -305,20 +369,29 @@ listSort(pred,list,:optional) ==
    NOT functionp key => error "listSort: last arg must be a function"
    mergeSort(pred,key,list,LENGTH list)
 
--- non-destructive merge sort using NOT GGREATERP as predicate
+@
+\subsection{MSORT}
+Non-destructive merge sort using NOT GGREATERP as predicate
+<<*>>=
 MSORT list == listSort(function GLESSEQP, COPY_-LIST list)
 
--- destructive merge sort using NOT GGREATERP as predicate
+@
+\subsection{NMSORT}
+Destructive merge sort using NOT GGREATERP as predicate
+<<*>>=
 NMSORT list == listSort(function GLESSEQP, list)
 
--- non-destructive merge sort using ?ORDER as predicate
+@
+\subsection{orderList}
+Non-destructive merge sort using ?ORDER as predicate
+<<*>>=
 orderList l == listSort(function _?ORDER, COPY_-LIST l)
 
--- dummy defn until clean-up
--- order     l == orderList l
-
+@
+\subsection{mergeInPlace}
+Merge the two sorted lists p and q
+<<*>>=
 mergeInPlace(f,g,p,q) ==
-   -- merge the two sorted lists p and q
    if NULL p then return p
    if NULL q then return q
    if FUNCALL(f,FUNCALL(g, QCAR p),FUNCALL(g, QCAR q))
@@ -331,6 +404,9 @@ mergeInPlace(f,g,p,q) ==
    if NULL p then QRPLACD(t,q) else QRPLACD(t,p)
    r
 
+@
+\subsection{mergeSort}
+<<*>>=
 mergeSort(f,g,p,n) ==
    if EQ(n,2) and FUNCALL(f,FUNCALL(g,QCADR p),FUNCALL(g,QCAR p)) then
       t := p
@@ -348,19 +424,26 @@ mergeSort(f,g,p,n) ==
    q := mergeSort(f,g,q,QSDIFFERENCE(n,l))
    mergeInPlace(f,g,p,q)
 
---% Throwing with glorious highlighting (maybe)
-
+@
+\subsection{spadThrow}
+Throwing with glorious highlighting (maybe)
+<<*>>=
 spadThrow() ==
   if $interpOnly and $mapName then
     putHist($mapName,'localModemap, nil, $e)
   THROW("SPAD__READER",nil)
 
+@
+\subsection{spadThrowBrightly}
+<<*>>=
 spadThrowBrightly x ==
   sayBrightly x
   spadThrow()
 
---% Type Formatting Without Abbreviation
-
+@
+\subsection{formatUnabbreviatedSig}
+Type Formatting Without Abbreviation
+<<*>>=
 formatUnabbreviatedSig sig ==
   null sig => ["() -> ()"]
   [target,:args] := sig
@@ -370,6 +453,9 @@ formatUnabbreviatedSig sig ==
   args := formatUnabbreviatedTuple args
   ['"(",:args,'") -> ",:target]
 
+@
+\subsection{formatUnabbreviatedTuple}
+<<*>>=
 formatUnabbreviatedTuple t ==
   -- t is a list of types
   null t => t
@@ -378,6 +464,9 @@ formatUnabbreviatedTuple t ==
   null rest t => t0
   [:t0,'",",:formatUnabbreviatedTuple QCDR t]
 
+@
+\subsection{formatUnabbreviated}
+<<*>>=
 formatUnabbreviated t ==
   atom t =>
     [t]
@@ -399,6 +488,9 @@ formatUnabbreviated t ==
     [arg,'"(",:formatUnabbreviatedTuple args,'")"]
   t
 
+@
+\subsection{sublisNQ}
+<<*>>=
 sublisNQ(al,e) ==
   atom al => e
   fn(al,e) where fn(al,e) ==
@@ -412,12 +504,17 @@ sublisNQ(al,e) ==
     EQ(a,u) and EQ(rest e,v) => e
     [u,:v]
 
--- function for turning strings in tex format
-
+@
+\subsection{str2Outform}
+Function for turning strings in tex format
+<<*>>=
 str2Outform s ==
   parse := ncParseFromString s or systemError '"String for TeX will not parse"
   parse2Outform parse
 
+@
+\subsection{parse2Outform}
+<<*>>=
 parse2Outform x ==
   x is [op,:argl] =>
     nargl := [parse2Outform y for y in argl]
@@ -426,16 +523,25 @@ parse2Outform x ==
     [op,:nargl]
   x
 
+@
+\subsection{str2Tex}
+<<*>>=
 str2Tex s ==
   outf := str2Outform s
   val := coerceInt(mkObj(wrap outf, '(OutputForm)), '(TexFormat))
   val := objValUnwrap val
   CAR val.1
 
+@
+\subsection{opOf}
+<<*>>=
 opOf x ==
   atom x => x
   first x
 
+@
+\subsection{getProplist}
+<<*>>=
 getProplist(x,E) ==
   not atom x => getProplist(first x,E)
   u:= search(x,E) => u
@@ -446,14 +552,23 @@ getProplist(x,E) ==
 --  (pl:=PROPLIST x) => pl
 -- Above line commented out JHD/BMT 2.Aug.90
 
+@
+\subsection{search}
+<<*>>=
 search(x,e is [curEnv,:tailEnv]) ==
   searchCurrentEnv(x,curEnv) or searchTailEnv(x,tailEnv)
 
+@
+\subsection{searchCurrentEnv}
+<<*>>=
 searchCurrentEnv(x,currentEnv) ==
   for contour in currentEnv repeat
     if u:= ASSQ(x,contour) then return (signal:= u)
   KDR signal
 
+@
+\subsection{searchTailEnv}
+<<*>>=
 searchTailEnv(x,e) ==
   for env in e repeat
     signal:=
@@ -462,6 +577,9 @@ searchTailEnv(x,e) ==
       if signal then return signal
   KDR signal
 
+@
+\subsection{augProplist}
+<<*>>=
 augProplist(proplist,prop,val) ==
   $InteractiveMode => augProplistInteractive(proplist,prop,val)
   while (proplist is [[ =prop,:.],:proplist']) repeat proplist:= proplist'
@@ -471,24 +589,42 @@ augProplist(proplist,prop,val) ==
     DELLASOS(prop,proplist)
   [[prop,:val],:proplist]
 
+@
+\subsection{augProplistOf}
+<<*>>=
 augProplistOf(var,prop,val,e) ==
   proplist:= getProplist(var,e)
   semchkProplist(var,proplist,prop,val)
   augProplist(proplist,prop,val)
 
+@
+\subsection{semchkProplist}
+<<*>>=
 semchkProplist(x,proplist,prop,val) ==
   prop="isLiteral" =>
     LASSOC("value",proplist) or LASSOC("mode",proplist) => warnLiteral x
   MEMQ(prop,'(mode value)) =>
     LASSOC("isLiteral",proplist) => warnLiteral x
 
+@
+\subsection{addBinding}
+The \verb|$envHashTable| is a performance improvement by Waldek Hebisch.
+<<*>>=
+DEFPARAMETER($envHashTable,nil)
+
 addBinding(var,proplist,e is [[curContour,:tailContour],:tailEnv]) ==
   EQ(proplist,getProplist(var,e)) => e
+  if $envHashTable then
+   for u in proplist repeat
+    HPUT($envHashTable,[var, CAR u],true)
   $InteractiveMode => addBindingInteractive(var,proplist,e)
   if curContour is [[ =var,:.],:.] then curContour:= rest curContour
                  --Previous line should save some space
   [[[lx,:curContour],:tailContour],:tailEnv] where lx:= [var,:proplist]
 
+@
+\subsection{position}
+<<*>>=
 position(x,l) ==
   posn(x,l,0) where
     posn(x,l,n) ==
@@ -496,21 +632,35 @@ position(x,l) ==
       x=first l => n
       posn(x,rest l,n+1)
 
+@
+\subsection{insert}
+<<*>>=
 insert(x,y) ==
   MEMBER(x,y) => y
   [x,:y]
 
+@
+\subsection{after}
+<<*>>=
 after(u,v) ==
   r:= u
   for x in u for y in v repeat r:= rest r
   r
 
-
+@
+\section{String trimming}
+<<*>>=
 $blank := char ('_ )
 
+@
+\subsection{trimString}
+<<*>>=
 trimString s ==
   leftTrim rightTrim s
 
+@
+\subsection{leftTrim}
+<<*>>=
 leftTrim s ==
   k := MAXINDEX s
   k < 0 => s
@@ -519,6 +669,9 @@ leftTrim s ==
     SUBSTRING(s,j + 1,nil)
   s
 
+@
+\subsection{rightTrim}
+<<*>>=
 rightTrim s ==  -- assumed a non-empty string
   k := MAXINDEX s
   k < 0 => s
@@ -527,38 +680,57 @@ rightTrim s ==  -- assumed a non-empty string
     SUBSTRING(s,0,j)
   s
 
+@
+\subsection{pp}
+<<*>>=
 pp x ==
   PRETTYPRINT x
   x
 
+@
+\subsection{pr}
+<<*>>=
 pr x ==
   F_,PRINT_-ONE x
   nil
 
+@
+\subsection{quickAnd}
+<<*>>=
 quickAnd(a,b) ==
   a = true => b
   b = true => a
   a = false or b = false => false
   simpBool ['AND,a,b]
 
+@
+\subsection{quickOr}
+<<*>>=
 quickOr(a,b) ==
   a = true or b = true => true
   b = false => a
   a = false => b
   simpCatPredicate simpBool ['OR,a,b]
 
+@
+\subsection{intern}
+<<*>>=
 intern x ==
   STRINGP x =>
     DIGITP x.0 => string2Integer x
     INTERN x
   x
 
+@
+\subsection{isDomain}
+<<*>>=
 isDomain a ==
   PAIRP a and VECP(CAR a) and
     MEMBER(CAR(a).0, $domainTypeTokens)
 
--- variables used by browser
-
+@
+\section{Variables used by browser}
+<<*>>=
 $htHash      := MAKE_-HASH_-TABLE()
 $glossHash   := MAKE_-HASH_-TABLE()
 $lispHash    := MAKE_-HASH_-TABLE()
@@ -629,14 +801,18 @@ $beginEndList := '(
   "verbatim"
   "detail")
 
+@
+\subsection{isDefaultPackageName}
+<<*>>=
 isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = char '_&
 @
 \section{g-util.clisp}
 <<g-util.clisp>>=
+;;; -*- Mode:Lisp; Package:Boot  -*-
+
 
 (IN-PACKAGE "BOOT" )
 
-;--% Utility Functions of General Use
 ;PPtoFile(x, fname) ==
 ;    stream := DEFIOSTREAM([['MODE, :'OUTPUT], ['FILE, :fname]], 80, 0)
 ;    PRETTYPRINT(x, stream)
@@ -646,14 +822,12 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |PPtoFile| REDEFINED
 
 (DEFUN |PPtoFile| (|x| |fname|) (PROG (|stream|) (RETURN (PROGN (SPADLET 
|stream| (DEFIOSTREAM (CONS (CONS (QUOTE MODE) (QUOTE OUTPUT)) (CONS (CONS 
(QUOTE FILE) |fname|) NIL)) 80 0)) (PRETTYPRINT |x| |stream|) (SHUT |stream|) 
|x|)))) 
-;-- Convert an arbitrary lisp object to canonical boolean.
 ;bool x ==
 ;    NULL NULL x
 
 ;;;     ***       |bool| REDEFINED
 
 (DEFUN |bool| (|x|) (NULL (NULL |x|))) 
-;--% Various lispy things
 ;Identity x == x
 
 ;;;     ***       |Identity| REDEFINED
@@ -673,8 +847,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |pairList| REDEFINED
 
-(DEFUN |pairList| (|u| |v|) (PROG NIL (RETURN (SEQ (PROG (#0=#:G2415) (SPADLET 
#0# NIL) (RETURN (DO ((#1=#:G2421 |u| (CDR #1#)) (|x| NIL) (#2=#:G2422 |v| (CDR 
#2#)) (|y| NIL)) ((OR (ATOM #1#) (PROGN (SETQ |x| (CAR #1#)) NIL) (ATOM #2#) 
(PROGN (SETQ |y| (CAR #2#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS 
(CONS |x| |y|) #0#))))))))))) 
-;-- GETALIST(alist,prop) == IFCDR assoc(prop,alist)
+(DEFUN |pairList| (|u| |v|) (PROG NIL (RETURN (SEQ (PROG (#0=#:G1403) (SPADLET 
#0# NIL) (RETURN (DO ((#1=#:G1404 |u| (CDR #1#)) (|x| NIL) (#2=#:G1405 |v| (CDR 
#2#)) (|y| NIL)) ((OR (ATOM #1#) (PROGN (SETQ |x| (CAR #1#)) NIL) (ATOM #2#) 
(PROGN (SETQ |y| (CAR #2#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS 
(CONS |x| |y|) #0#))))))))))) 
 ;GETALIST(alist,prop) == CDR assoc(prop,alist)
 
 ;;;     ***       GETALIST REDEFINED
@@ -723,7 +896,6 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |deleteLassoc| REDEFINED
 
 (DEFUN |deleteLassoc| (|x| |y|) (PROG (|ISTMP#1| |a| |y'|) (RETURN (COND ((AND 
(PAIRP |y|) (PROGN (SPADLET |ISTMP#1| (QCAR |y|)) (AND (PAIRP |ISTMP#1|) (PROGN 
(SPADLET |a| (QCAR |ISTMP#1|)) (QUOTE T)))) (PROGN (SPADLET |y'| (QCDR |y|)) 
(QUOTE T))) (COND ((EQ |x| |a|) |y'|) ((QUOTE T) (CONS (CAR |y|) 
(|deleteLassoc| |x| |y'|))))) ((QUOTE T) |y|))))) 
-;--% association list functions
 ;deleteAssoc(x,y) ==
 ;  y is [[a,:.],:y'] =>
 ;   a=x => deleteAssoc(x,y')
@@ -766,14 +938,13 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |insertWOC| REDEFINED
 
 (DEFUN |insertWOC| (|x| |y|) (COND ((NULL |y|) (CONS |x| NIL)) ((QUOTE T) 
(|insertWOC,fn| |x| |y|) |y|))) 
-;--% Miscellaneous Functions for Working with Strings
 ;fillerSpaces(n,:charPart) ==
 ;  n <= 0 => '""
 ;  MAKE_-FULL_-CVEC(n,IFCAR charPart or '" ")
 
 ;;;     ***       |fillerSpaces| REDEFINED
 
-(DEFUN |fillerSpaces| (&REST #0=#:G2562 &AUX |charPart| |n|) (DSETQ (|n| . 
|charPart|) #0#) (COND ((<= |n| 0) (MAKESTRING "")) ((QUOTE T) (MAKE-FULL-CVEC 
|n| (OR (IFCAR |charPart|) (MAKESTRING " ")))))) 
+(DEFUN |fillerSpaces| (&REST #0=#:G1406 &AUX |charPart| |n|) (DSETQ (|n| . 
|charPart|) #0#) (COND ((<= |n| 0) (MAKESTRING "")) ((QUOTE T) (MAKE-FULL-CVEC 
|n| (OR (IFCAR |charPart|) (MAKESTRING " ")))))) 
 ;centerString(text,width,fillchar) ==
 ;  wid := entryWidth text
 ;  wid >= width => text
@@ -787,7 +958,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |centerString| REDEFINED
 
-(DEFUN |centerString| (|text| |width| |fillchar|) (PROG (|wid| |f| |fill2| 
|fill1|) (RETURN (SEQ (PROGN (SPADLET |wid| (|entryWidth| |text|)) (COND ((>= 
|wid| |width|) |text|) ((QUOTE T) (SPADLET |f| (DIVIDE (SPADDIFFERENCE |width| 
|wid|) 2)) (SPADLET |fill1| (QUOTE ||)) (DO ((#0=#:G2567 (ELT |f| 0)) (|i| 1 
(QSADD1 |i|))) ((QSGREATERP |i| #0#) NIL) (SEQ (EXIT (SPADLET |fill1| (STRCONC 
|fillchar| |fill1|))))) (SPADLET |fill2| |fill1|) (COND ((NEQUAL (ELT |f| 1) 0) 
(SPADLET |fill1| (STRCONC |fillchar| |fill1|)))) (CONS |fill1| (CONS |text| 
(CONS |fill2| NIL)))))))))) 
+(DEFUN |centerString| (|text| |width| |fillchar|) (PROG (|wid| |f| |fill2| 
|fill1|) (RETURN (SEQ (PROGN (SPADLET |wid| (|entryWidth| |text|)) (COND ((>= 
|wid| |width|) |text|) ((QUOTE T) (SPADLET |f| (DIVIDE (SPADDIFFERENCE |width| 
|wid|) 2)) (SPADLET |fill1| (QUOTE ||)) (DO ((#0=#:G1407 (ELT |f| 0)) (|i| 1 
(QSADD1 |i|))) ((QSGREATERP |i| #0#) NIL) (SEQ (EXIT (SPADLET |fill1| (STRCONC 
|fillchar| |fill1|))))) (SPADLET |fill2| |fill1|) (COND ((NEQUAL (ELT |f| 1) 0) 
(SPADLET |fill1| (STRCONC |fillchar| |fill1|)))) (CONS |fill1| (CONS |text| 
(CONS |fill2| NIL)))))))))) 
 ;stringPrefix?(pref,str) ==
 ;  -- sees if the first #pref letters of str are pref
 ;  -- replaces STRINGPREFIXP
@@ -836,7 +1007,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |concat| REDEFINED
 
-(DEFUN |concat| (&REST #0=#:G2621 &AUX |l|) (DSETQ |l| #0#) (|concatList| 
|l|)) 
+(DEFUN |concat| (&REST #0=#:G1408 &AUX |l|) (DSETQ |l| #0#) (|concatList| 
|l|)) 
 ;concatList [x,:y] ==
 ;  null y => x
 ;  null x => concatList y
@@ -844,7 +1015,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |concatList| REDEFINED
 
-(DEFUN |concatList| (#0=#:G2623) (PROG (|x| |y|) (RETURN (PROGN (SPADLET |x| 
(CAR #0#)) (SPADLET |y| (CDR #0#)) (COND ((NULL |y|) |x|) ((NULL |x|) 
(|concatList| |y|)) ((QUOTE T) (|concat1| |x| (|concatList| |y|)))))))) 
+(DEFUN |concatList| (#0=#:G1409) (PROG (|x| |y|) (RETURN (PROGN (SPADLET |x| 
(CAR #0#)) (SPADLET |y| (CDR #0#)) (COND ((NULL |y|) |x|) ((NULL |x|) 
(|concatList| |y|)) ((QUOTE T) (|concat1| |x| (|concatList| |y|)))))))) 
 ;concat1(x,y) ==
 ;  null x => y
 ;  atom x => (null y => x; atom y => [x,y]; [x,:y])
@@ -855,7 +1026,6 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |concat1| REDEFINED
 
 (DEFUN |concat1| (|x| |y|) (COND ((NULL |x|) |y|) ((ATOM |x|) (COND ((NULL 
|y|) |x|) ((ATOM |y|) (CONS |x| (CONS |y| NIL))) ((QUOTE T) (CONS |x| |y|)))) 
((NULL |y|) |x|) ((ATOM |y|) (APPEND |x| (CONS |y| NIL))) ((QUOTE T) (APPEND 
|x| |y|)))) 
-;--% BOOT ravel and reshape
 ;ravel a == a
 
 ;;;     ***       |ravel| REDEFINED
@@ -866,13 +1036,11 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |reshape| REDEFINED
 
 (DEFUN |reshape| (|a| |b|) |a|) 
-;--% Some functions for algebra code
 ;boolODDP x == ODDP x
 
 ;;;     ***       |boolODDP| REDEFINED
 
 (DEFUN |boolODDP| (|x|) (ODDP |x|)) 
-;--% Miscellaneous
 ;freeOfSharpVars x ==
 ;  atom x => not isSharpVarWithNum x
 ;  freeOfSharpVars first x and freeOfSharpVars rest x
@@ -976,11 +1144,6 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |update| REDEFINED
 
 (DEFUN |update| NIL (PROGN (OBEY (STRCONC (MAKESTRING "SPADEDIT ") 
(STRINGIMAGE /VERSION) (MAKESTRING " ") (STRINGIMAGE /WSNAME) (MAKESTRING " 
A"))) (/UPDATE))) 
-;--% Inplace Merge Sort for Lists
-;-- MBM April/88
-;-- listSort(pred,list) or listSort(pred,list,key)
-;-- the pred function is a boolean valued function defining the ordering
-;-- the key function extracts the key from an item for comparison by pred
 ;listSort(pred,list,:optional) ==
 ;   NOT functionp pred => error "listSort: first arg must be a function"
 ;   NOT LISTP list => error "listSort: second argument must be a list"
@@ -991,29 +1154,23 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |listSort| REDEFINED
 
-(DEFUN |listSort| (&REST #0=#:G2710 &AUX |optional| LIST |pred|) (DSETQ 
(|pred| LIST . |optional|) #0#) (PROG (|key|) (RETURN (COND ((NULL (|functionp| 
|pred|)) (|error| (QUOTE |listSort: first arg must be a function|))) ((NULL 
(LISTP LIST)) (|error| (QUOTE |listSort: second argument must be a list|))) 
((NULL |optional|) (|mergeSort| |pred| (|function| |Identity|) LIST (LENGTH 
LIST))) ((QUOTE T) (SPADLET |key| (CAR |optional|)) (COND ((NULL (|functionp| 
|key|)) (|error| (QUOTE |listSort: last arg must be a function|))) ((QUOTE T) 
(|mergeSort| |pred| |key| LIST (LENGTH LIST))))))))) 
-;-- non-destructive merge sort using NOT GGREATERP as predicate
+(DEFUN |listSort| (&REST #0=#:G1410 &AUX |optional| LIST |pred|) (DSETQ 
(|pred| LIST . |optional|) #0#) (PROG (|key|) (RETURN (COND ((NULL (|functionp| 
|pred|)) (|error| (QUOTE |listSort: first arg must be a function|))) ((NULL 
(LISTP LIST)) (|error| (QUOTE |listSort: second argument must be a list|))) 
((NULL |optional|) (|mergeSort| |pred| (|function| |Identity|) LIST (LENGTH 
LIST))) ((QUOTE T) (SPADLET |key| (CAR |optional|)) (COND ((NULL (|functionp| 
|key|)) (|error| (QUOTE |listSort: last arg must be a function|))) ((QUOTE T) 
(|mergeSort| |pred| |key| LIST (LENGTH LIST))))))))) 
 ;MSORT list == listSort(function GLESSEQP, COPY_-LIST list)
 
 ;;;     ***       MSORT REDEFINED
 
 (DEFUN MSORT (LIST) (|listSort| (|function| GLESSEQP) (COPY-LIST LIST))) 
-;-- destructive merge sort using NOT GGREATERP as predicate
 ;NMSORT list == listSort(function GLESSEQP, list)
 
 ;;;     ***       NMSORT REDEFINED
 
 (DEFUN NMSORT (LIST) (|listSort| (|function| GLESSEQP) LIST)) 
-;-- non-destructive merge sort using ?ORDER as predicate
 ;orderList l == listSort(function _?ORDER, COPY_-LIST l)
 
 ;;;     ***       |orderList| REDEFINED
 
 (DEFUN |orderList| (|l|) (|listSort| (|function| ?ORDER) (COPY-LIST |l|))) 
-;-- dummy defn until clean-up
-;-- order     l == orderList l
 ;mergeInPlace(f,g,p,q) ==
-;   -- merge the two sorted lists p and q
 ;   if NULL p then return p
 ;   if NULL q then return q
 ;   if FUNCALL(f,FUNCALL(g, QCAR p),FUNCALL(g, QCAR q))
@@ -1048,8 +1205,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |mergeSort| REDEFINED
 
-(DEFUN |mergeSort| (|f| |g| |p| |n|) (PROG (|l| |t| |q|) (RETURN (SEQ (PROGN 
(COND ((AND (EQ |n| 2) (FUNCALL |f| (FUNCALL |g| (QCADR |p|)) (FUNCALL |g| 
(QCAR |p|)))) (SPADLET |t| |p|) (SPADLET |p| (QCDR |p|)) (QRPLACD |p| |t|) 
(QRPLACD |t| NIL))) (COND ((QSLESSP |n| 3) (RETURN |p|))) (SPADLET |l| 
(QSQUOTIENT |n| 2)) (SPADLET |t| |p|) (DO ((#0=#:G2749 (SPADDIFFERENCE |l| 1)) 
(|i| 1 (QSADD1 |i|))) ((QSGREATERP |i| #0#) NIL) (SEQ (EXIT (SPADLET |t| (QCDR 
|t|))))) (SPADLET |q| (CDR |t|)) (QRPLACD |t| NIL) (SPADLET |p| (|mergeSort| 
|f| |g| |p| |l|)) (SPADLET |q| (|mergeSort| |f| |g| |q| (QSDIFFERENCE |n| 
|l|))) (|mergeInPlace| |f| |g| |p| |q|)))))) 
-;--% Throwing with glorious highlighting (maybe)
+(DEFUN |mergeSort| (|f| |g| |p| |n|) (PROG (|l| |t| |q|) (RETURN (SEQ (PROGN 
(COND ((AND (EQ |n| 2) (FUNCALL |f| (FUNCALL |g| (QCADR |p|)) (FUNCALL |g| 
(QCAR |p|)))) (SPADLET |t| |p|) (SPADLET |p| (QCDR |p|)) (QRPLACD |p| |t|) 
(QRPLACD |t| NIL))) (COND ((QSLESSP |n| 3) (RETURN |p|))) (SPADLET |l| 
(QSQUOTIENT |n| 2)) (SPADLET |t| |p|) (DO ((#0=#:G1411 (SPADDIFFERENCE |l| 1)) 
(|i| 1 (QSADD1 |i|))) ((QSGREATERP |i| #0#) NIL) (SEQ (EXIT (SPADLET |t| (QCDR 
|t|))))) (SPADLET |q| (CDR |t|)) (QRPLACD |t| NIL) (SPADLET |p| (|mergeSort| 
|f| |g| |p| |l|)) (SPADLET |q| (|mergeSort| |f| |g| |q| (QSDIFFERENCE |n| 
|l|))) (|mergeInPlace| |f| |g| |p| |q|)))))) 
 ;spadThrow() ==
 ;  if $interpOnly and $mapName then
 ;    putHist($mapName,'localModemap, nil, $e)
@@ -1065,7 +1221,6 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |spadThrowBrightly| REDEFINED
 
 (DEFUN |spadThrowBrightly| (|x|) (PROGN (|sayBrightly| |x|) (|spadThrow|))) 
-;--% Type Formatting Without Abbreviation
 ;formatUnabbreviatedSig sig ==
 ;  null sig => ["() -> ()"]
 ;  [target,:args] := sig
@@ -1128,12 +1283,11 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |sublisNQ,fn| REDEFINED
 
-(DEFUN |sublisNQ,fn| (|al| |e|) (PROG (|a| |u| |v|) (RETURN (SEQ (IF (ATOM 
|e|) (EXIT (SEQ (DO ((#0=#:G2847 |al| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) 
(PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (IF (EQ (CAR |x|) |e|) (EXIT 
(RETURN (SPADLET |e| (CDR |x|)))))))) (EXIT |e|)))) (IF (EQ (SPADLET |a| (CAR 
|e|)) (QUOTE QUOTE)) (EXIT |e|)) (SPADLET |u| (|sublisNQ,fn| |al| |a|)) 
(SPADLET |v| (|sublisNQ,fn| |al| (CDR |e|))) (IF (AND (EQ |a| |u|) (EQ (CDR 
|e|) |v|)) (EXIT |e|)) (EXIT (CONS |u| |v|)))))) 
+(DEFUN |sublisNQ,fn| (|al| |e|) (PROG (|a| |u| |v|) (RETURN (SEQ (IF (ATOM 
|e|) (EXIT (SEQ (DO ((#0=#:G1412 |al| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) 
(PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (IF (EQ (CAR |x|) |e|) (EXIT 
(RETURN (SPADLET |e| (CDR |x|)))))))) (EXIT |e|)))) (IF (EQ (SPADLET |a| (CAR 
|e|)) (QUOTE QUOTE)) (EXIT |e|)) (SPADLET |u| (|sublisNQ,fn| |al| |a|)) 
(SPADLET |v| (|sublisNQ,fn| |al| (CDR |e|))) (IF (AND (EQ |a| |u|) (EQ (CDR 
|e|) |v|)) (EXIT |e|)) (EXIT (CONS |u| |v|)))))) 
 
 ;;;     ***       |sublisNQ| REDEFINED
 
 (DEFUN |sublisNQ| (|al| |e|) (COND ((ATOM |al|) |e|) ((QUOTE T) (|sublisNQ,fn| 
|al| |e|)))) 
-;-- function for turning strings in tex format
 ;str2Outform s ==
 ;  parse := ncParseFromString s or systemError '"String for TeX will not parse"
 ;  parse2Outform parse
@@ -1151,7 +1305,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |parse2Outform| REDEFINED
 
-(DEFUN |parse2Outform| (|x|) (PROG (|op| |argl| |nargl| |ISTMP#1| BRACKET |r|) 
(RETURN (SEQ (COND ((AND (PAIRP |x|) (PROGN (SPADLET |op| (QCAR |x|)) (SPADLET 
|argl| (QCDR |x|)) (QUOTE T))) (SPADLET |nargl| (PROG (#0=#:G2887) (SPADLET #0# 
NIL) (RETURN (DO ((#1=#:G2892 |argl| (CDR #1#)) (|y| NIL)) ((OR (ATOM #1#) 
(PROGN (SETQ |y| (CAR #1#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS 
(|parse2Outform| |y|) #0#)))))))) (COND ((BOOT-EQUAL |op| (QUOTE |construct|)) 
(CONS (QUOTE BRACKET) (CONS (CONS (QUOTE ARGLST) (PROG (#2=#:G2902) (SPADLET 
#2# NIL) (RETURN (DO ((#3=#:G2907 |argl| (CDR #3#)) (|y| NIL)) ((OR (ATOM #3#) 
(PROGN (SETQ |y| (CAR #3#)) NIL)) (NREVERSE0 #2#)) (SEQ (EXIT (SETQ #2# (CONS 
(|parse2Outform| |y|) #2#)))))))) NIL))) ((AND (BOOT-EQUAL |op| (QUOTE 
|brace|)) (PAIRP |nargl|) (EQ (QCDR |nargl|) NIL) (PROGN (SPADLET |ISTMP#1| 
(QCAR |nargl|)) (AND (PAIRP |ISTMP#1|) (PROGN (SPADLET BRACKET (QCAR 
|ISTMP#1|)) (SPADLET |r| (QCDR |ISTMP#1|)) (QUOTE T))))) (CONS (QUOT!
E BRACE) |r|)) ((QUOTE T) (CONS |op| |nargl|)))) ((QUOTE T) |x|)))))) 
+(DEFUN |parse2Outform| (|x|) (PROG (|op| |argl| |nargl| |ISTMP#1| BRACKET |r|) 
(RETURN (SEQ (COND ((AND (PAIRP |x|) (PROGN (SPADLET |op| (QCAR |x|)) (SPADLET 
|argl| (QCDR |x|)) (QUOTE T))) (SPADLET |nargl| (PROG (#0=#:G1413) (SPADLET #0# 
NIL) (RETURN (DO ((#1=#:G1414 |argl| (CDR #1#)) (|y| NIL)) ((OR (ATOM #1#) 
(PROGN (SETQ |y| (CAR #1#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS 
(|parse2Outform| |y|) #0#)))))))) (COND ((BOOT-EQUAL |op| (QUOTE |construct|)) 
(CONS (QUOTE BRACKET) (CONS (CONS (QUOTE ARGLST) (PROG (#2=#:G1415) (SPADLET 
#2# NIL) (RETURN (DO ((#3=#:G1416 |argl| (CDR #3#)) (|y| NIL)) ((OR (ATOM #3#) 
(PROGN (SETQ |y| (CAR #3#)) NIL)) (NREVERSE0 #2#)) (SEQ (EXIT (SETQ #2# (CONS 
(|parse2Outform| |y|) #2#)))))))) NIL))) ((AND (BOOT-EQUAL |op| (QUOTE 
|brace|)) (PAIRP |nargl|) (EQ (QCDR |nargl|) NIL) (PROGN (SPADLET |ISTMP#1| 
(QCAR |nargl|)) (AND (PAIRP |ISTMP#1|) (PROGN (SPADLET BRACKET (QCAR 
|ISTMP#1|)) (SPADLET |r| (QCDR |ISTMP#1|)) (QUOTE T))))) (CONS (QUOT!
E BRACE) |r|)) ((QUOTE T) (CONS |op| |nargl|)))) ((QUOTE T) |x|)))))) 
 ;str2Tex s ==
 ;  outf := str2Outform s
 ;  val := coerceInt(mkObj(wrap outf, '(OutputForm)), '(TexFormat))
@@ -1194,7 +1348,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |searchCurrentEnv| REDEFINED
 
-(DEFUN |searchCurrentEnv| (|x| |currentEnv|) (PROG (|u| |signal|) (RETURN (SEQ 
(PROGN (DO ((#0=#:G2958 |currentEnv| (CDR #0#)) (|contour| NIL)) ((OR (ATOM 
#0#) (PROGN (SETQ |contour| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (COND ((SPADLET 
|u| (ASSQ |x| |contour|)) (RETURN (SPADLET |signal| |u|))) ((QUOTE T) NIL))))) 
(KDR |signal|)))))) 
+(DEFUN |searchCurrentEnv| (|x| |currentEnv|) (PROG (|u| |signal|) (RETURN (SEQ 
(PROGN (DO ((#0=#:G1417 |currentEnv| (CDR #0#)) (|contour| NIL)) ((OR (ATOM 
#0#) (PROGN (SETQ |contour| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (COND ((SPADLET 
|u| (ASSQ |x| |contour|)) (RETURN (SPADLET |signal| |u|))) ((QUOTE T) NIL))))) 
(KDR |signal|)))))) 
 ;searchTailEnv(x,e) ==
 ;  for env in e repeat
 ;    signal:=
@@ -1205,7 +1359,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |searchTailEnv| REDEFINED
 
-(DEFUN |searchTailEnv| (|x| |e|) (PROG (|u| |signal|) (RETURN (SEQ (PROGN (DO 
((#0=#:G2976 |e| (CDR #0#)) (|env| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |env| 
(CAR #0#)) NIL)) NIL) (SEQ (EXIT (SPADLET |signal| (PROGN (DO ((#1=#:G2985 
|env| (CDR #1#)) (|contour| NIL)) ((OR (ATOM #1#) (PROGN (SETQ |contour| (CAR 
#1#)) NIL)) NIL) (SEQ (EXIT (COND ((AND (SPADLET |u| (ASSQ |x| |contour|)) 
(ASSQ (QUOTE FLUID) |u|)) (RETURN (SPADLET |signal| |u|))) ((QUOTE T) NIL))))) 
(COND (|signal| (RETURN |signal|)) ((QUOTE T) NIL))))))) (KDR |signal|)))))) 
+(DEFUN |searchTailEnv| (|x| |e|) (PROG (|u| |signal|) (RETURN (SEQ (PROGN (DO 
((#0=#:G1418 |e| (CDR #0#)) (|env| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |env| 
(CAR #0#)) NIL)) NIL) (SEQ (EXIT (SPADLET |signal| (PROGN (DO ((#1=#:G1419 
|env| (CDR #1#)) (|contour| NIL)) ((OR (ATOM #1#) (PROGN (SETQ |contour| (CAR 
#1#)) NIL)) NIL) (SEQ (EXIT (COND ((AND (SPADLET |u| (ASSQ |x| |contour|)) 
(ASSQ (QUOTE FLUID) |u|)) (RETURN (SPADLET |signal| |u|))) ((QUOTE T) NIL))))) 
(COND (|signal| (RETURN |signal|)) ((QUOTE T) NIL))))))) (KDR |signal|)))))) 
 ;augProplist(proplist,prop,val) ==
 ;  $InteractiveMode => augProplistInteractive(proplist,prop,val)
 ;  while (proplist is [[ =prop,:.],:proplist']) repeat proplist:= proplist'
@@ -1235,8 +1389,14 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;     ***       |semchkProplist| REDEFINED
 
 (DEFUN |semchkProplist| (|x| |proplist| |prop| |val|) (SEQ (COND ((BOOT-EQUAL 
|prop| (QUOTE |isLiteral|)) (COND ((OR (LASSOC (QUOTE |value|) |proplist|) 
(LASSOC (QUOTE |mode|) |proplist|)) (EXIT (|warnLiteral| |x|))))) ((MEMQ |prop| 
(QUOTE (|mode| |value|))) (COND ((LASSOC (QUOTE |isLiteral|) |proplist|) (EXIT 
(|warnLiteral| |x|)))))))) 
+;DEFPARAMETER($envHashTable,nil)
+
+(DEFPARAMETER |$envHashTable| NIL) 
 ;addBinding(var,proplist,e is [[curContour,:tailContour],:tailEnv]) ==
 ;  EQ(proplist,getProplist(var,e)) => e
+;  if $envHashTable then
+;   for u in proplist repeat
+;    HPUT($envHashTable,[var, CAR u],true)
 ;  $InteractiveMode => addBindingInteractive(var,proplist,e)
 ;  if curContour is [[ =var,:.],:.] then curContour:= rest curContour
 ;                 --Previous line should save some space
@@ -1244,7 +1404,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |addBinding| REDEFINED
 
-(DEFUN |addBinding| (|var| |proplist| |e|) (PROG (|tailContour| |tailEnv| 
|ISTMP#1| |curContour| |lx|) (RETURN (PROGN (SPADLET |curContour| (CAAR |e|)) 
(SPADLET |tailContour| (CDAR |e|)) (SPADLET |tailEnv| (CDR |e|)) (COND ((EQ 
|proplist| (|getProplist| |var| |e|)) |e|) (|$InteractiveMode| 
(|addBindingInteractive| |var| |proplist| |e|)) ((QUOTE T) (COND ((AND (PAIRP 
|curContour|) (PROGN (SPADLET |ISTMP#1| (QCAR |curContour|)) (AND (PAIRP 
|ISTMP#1|) (EQUAL (QCAR |ISTMP#1|) |var|)))) (SPADLET |curContour| (CDR 
|curContour|)))) (SPADLET |lx| (CONS |var| |proplist|)) (CONS (CONS (CONS |lx| 
|curContour|) |tailContour|) |tailEnv|))))))) 
+(DEFUN |addBinding| (|var| |proplist| |e|) (PROG (|tailContour| |tailEnv| 
|ISTMP#1| |curContour| |lx|) (RETURN (SEQ (PROGN (SPADLET |curContour| (CAAR 
|e|)) (SPADLET |tailContour| (CDAR |e|)) (SPADLET |tailEnv| (CDR |e|)) (COND 
((EQ |proplist| (|getProplist| |var| |e|)) |e|) ((QUOTE T) (COND 
(|$envHashTable| (DO ((#0=#:G1420 |proplist| (CDR #0#)) (|u| NIL)) ((OR (ATOM 
#0#) (PROGN (SETQ |u| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (HPUT |$envHashTable| 
(CONS |var| (CONS (CAR |u|) NIL)) (QUOTE T))))))) (COND (|$InteractiveMode| 
(|addBindingInteractive| |var| |proplist| |e|)) ((QUOTE T) (COND ((AND (PAIRP 
|curContour|) (PROGN (SPADLET |ISTMP#1| (QCAR |curContour|)) (AND (PAIRP 
|ISTMP#1|) (EQUAL (QCAR |ISTMP#1|) |var|)))) (SPADLET |curContour| (CDR 
|curContour|)))) (SPADLET |lx| (CONS |var| |proplist|)) (CONS (CONS (CONS |lx| 
|curContour|) |tailContour|) |tailEnv|)))))))))) 
 ;position(x,l) ==
 ;  posn(x,l,0) where
 ;    posn(x,l,n) ==
@@ -1273,7 +1433,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |after| REDEFINED
 
-(DEFUN |after| (|u| |v|) (PROG (|r|) (RETURN (SEQ (PROGN (SPADLET |r| |u|) (DO 
((#0=#:G3068 |u| (CDR #0#)) (|x| NIL) (#1=#:G3069 |v| (CDR #1#)) (|y| NIL)) 
((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL) (ATOM #1#) (PROGN (SETQ |y| 
(CAR #1#)) NIL)) NIL) (SEQ (EXIT (SPADLET |r| (CDR |r|))))) |r|))))) 
+(DEFUN |after| (|u| |v|) (PROG (|r|) (RETURN (SEQ (PROGN (SPADLET |r| |u|) (DO 
((#0=#:G1421 |u| (CDR #0#)) (|x| NIL) (#1=#:G1422 |v| (CDR #1#)) (|y| NIL)) 
((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL) (ATOM #1#) (PROGN (SETQ |y| 
(CAR #1#)) NIL)) NIL) (SEQ (EXIT (SPADLET |r| (CDR |r|))))) |r|))))) 
 ;$blank := char ('_ )
 
 (SPADLET |$blank| (|char| (QUOTE | |))) 
@@ -1304,7 +1464,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 ;;;     ***       |rightTrim| REDEFINED
 
-(DEFUN |rightTrim| (|s|) (PROG (|k| |j|) (RETURN (SEQ (PROGN (SPADLET |k| 
(MAXINDEX |s|)) (COND ((MINUSP |k|) |s|) ((BOOT-EQUAL (ELT |s| |k|) |$blank|) 
(DO ((#0=#:G3107 (SPADDIFFERENCE 1)) (|i| |k| (+ |i| #0#))) ((OR (IF (MINUSP 
#0#) (< |i| 0) (> |i| 0)) (NULL (BOOT-EQUAL (ELT |s| |i|) |$blank|))) NIL) (SEQ 
(EXIT (SPADLET |j| |i|)))) (SUBSTRING |s| 0 |j|)) ((QUOTE T) |s|))))))) 
+(DEFUN |rightTrim| (|s|) (PROG (|k| |j|) (RETURN (SEQ (PROGN (SPADLET |k| 
(MAXINDEX |s|)) (COND ((MINUSP |k|) |s|) ((BOOT-EQUAL (ELT |s| |k|) |$blank|) 
(DO ((#0=#:G1423 (SPADDIFFERENCE 1)) (|i| |k| (+ |i| #0#))) ((OR (IF (MINUSP 
#0#) (< |i| 0) (> |i| 0)) (NULL (BOOT-EQUAL (ELT |s| |i|) |$blank|))) NIL) (SEQ 
(EXIT (SPADLET |j| |i|)))) (SUBSTRING |s| 0 |j|)) ((QUOTE T) |s|))))))) 
 ;pp x ==
 ;  PRETTYPRINT x
 ;  x
@@ -1347,12 +1507,12 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 
 (DEFUN |intern| (|x|) (COND ((STRINGP |x|) (COND ((DIGITP (ELT |x| 0)) 
(|string2Integer| |x|)) ((QUOTE T) (INTERN |x|)))) ((QUOTE T) |x|))) 
 ;isDomain a ==
-;  REFVECP a and #a>5 and GETDATABASE(a.0,'CONSTRUCTORKIND) = 'domain
+;  PAIRP a and VECP(CAR a) and
+;    MEMBER(CAR(a).0, $domainTypeTokens)
 
 ;;;     ***       |isDomain| REDEFINED
 
-(DEFUN |isDomain| (|a|) (AND (REFVECP |a|) (> (|#| |a|) 5) (BOOT-EQUAL 
(GETDATABASE (ELT |a| 0) (QUOTE CONSTRUCTORKIND)) (QUOTE |domain|)))) 
-;-- variables used by browser
+(DEFUN |isDomain| (|a|) (AND (PAIRP |a|) (VECP (CAR |a|)) (|member| (ELT (CAR 
|a|) 0) |$domainTypeTokens|))) 
 ;$htHash      := MAKE_-HASH_-TABLE()
 
 (SPADLET |$htHash| (MAKE-HASH-TABLE)) 
@@ -1501,6 +1661,40 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = 
char '_&
 ;;;Boot translation finished for g-util.boot
 
 @
+\section{License}
+<<license>>=
+-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+--     - Redistributions of source code must retain the above copyright
+--       notice, this list of conditions and the following disclaimer.
+--
+--     - Redistributions in binary form must reproduce the above copyright
+--       notice, this list of conditions and the following disclaimer in
+--       the documentation and/or other materials provided with the
+--       distribution.
+--
+--     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+--       names of its contributors may be used to endorse or promote products
+--       derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@
 \eject
 \begin{thebibliography}{99}
 \bibitem{1} nothing
diff --git a/src/interp/i-intern.boot.pamphlet 
b/src/interp/i-intern.boot.pamphlet
index 144aa0e..7520954 100644
--- a/src/interp/i-intern.boot.pamphlet
+++ b/src/interp/i-intern.boot.pamphlet
@@ -9,9 +9,7 @@
 \eject
 \tableofcontents
 \eject
-\begin{verbatim}
-Internal Interpreter Facilities
-
+\section{Internal Interpreter Facilities}
 Vectorized Attributed Trees
 
 The interpreter translates parse forms into vats for analysis.
@@ -19,82 +17,65 @@ These contain a number of slots in each node for 
information.
 The leaves are now all vectors, though the leaves for basic types
 such as integers and strings used to just be the objects themselves.
 The vectors for the leaves with such constants now have the value
-of $immediateDataSymbol as their name. Their are undoubtably still
+of \verb|$immediateDataSymbol| as their name. Their are undoubtably still
 some functions that still check whether a leaf is a constant. Note
 that if it is not a vector it is a subtree.
 
 attributed tree nodes have the following form:
-slot         description
-----         -----------------------------------------------------
- 0           operation name or literal
- 1           declared mode of variable
- 2           computed value of subtree from this node
- 3           modeset: list of single computed mode of subtree
- 4           prop list for extra things
-
-\end{verbatim}
-\section{License}
-<<license>>=
--- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
--- All rights reserved.
---
--- Redistribution and use in source and binary forms, with or without
--- modification, are permitted provided that the following conditions are
--- met:
---
---     - Redistributions of source code must retain the above copyright
---       notice, this list of conditions and the following disclaimer.
---
---     - Redistributions in binary form must reproduce the above copyright
---       notice, this list of conditions and the following disclaimer in
---       the documentation and/or other materials provided with the
---       distribution.
---
---     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
---       names of its contributors may be used to endorse or promote products
---       derived from this software without specific prior written permission.
---
--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-@
+\begin{tabular}{cl}
+slot & description\\
+---- & ------------------------- \\
+ 0   & operation name or literal\\
+ 1   & declared mode of variable\\
+ 2   & computed value of subtree from this node\\
+ 3   & modeset: list of single computed mode of subtree\\
+ 4   & prop list for extra things\\
+\end{tabular}
 <<*>>=
-<<license>>
 
 SETANDFILEQ($useParserSrcPos, NIL)
 SETANDFILEQ($transferParserSrcPos, NIL)
 
---  Making Trees
-
+@
+\section{Making trees}
+\subsection{mkAtreeNode}
+<<*>>=
 mkAtreeNode x ==
   -- maker of attrib tree node
   v := MAKE_-VEC 5
   v.0 := x
   v
 
+@
+\subsection{mkAtree}
+Maker of attrib tree from parser form
+<<*>>=
 mkAtree x ==
-  -- maker of attrib tree from parser form
   mkAtree1 mkAtreeExpandMacros x
 
+@
+\subsection{mkAtreeWithSrcPos}
+<<*>>=
 mkAtreeWithSrcPos(form, posnForm) ==
     posnForm and $useParserSrcPos => pf2Atree(posnForm)
     transferSrcPosInfo(posnForm, mkAtree form)
 
+@
+\subsection{mkAtree1WithSrcPos}
+<<*>>=
 mkAtree1WithSrcPos(form, posnForm) ==
   transferSrcPosInfo(posnForm, mkAtree1 form)
 
+@
+\subsection{mkAtreeNodeWithSrcPos}
+<<*>>=
 mkAtreeNodeWithSrcPos(form, posnForm) ==
   transferSrcPosInfo(posnForm, mkAtreeNode form)
 
+@
+\subsection{transferSrcPosInfo}
+<<*>>=
 transferSrcPosInfo(pf, atree) ==
     not (pf and $transferParserSrcPos) => atree
     pos := pfPosOrNopos(pf)
@@ -108,9 +89,12 @@ transferSrcPosInfo(pf, atree) ==
     putSrcPos(atree, fn, pfSourceText(pf), pfLinePosn(pos), pfCharPosn(pos))
     atree
 
+@
+\subsection{mkAtreeExpandMacros}
+Handle macro expansion. if the macros have args we require that
+we match the correct number of args
+<<*>>=
 mkAtreeExpandMacros x ==
-  -- handle macro expansion. if the macros have args we require that
-  -- we match the correct number of args
   if x isnt ['MDEF,:.] and x isnt ['DEF,['macro,:.],:.] then
     atom x and (m := isInterpMacro x) =>
       [args,:body] := m
@@ -134,6 +118,9 @@ mkAtreeExpandMacros x ==
       x := [mkAtreeExpandMacros op,:argl]
   x
 
+@
+\subsection{mkAtree1}
+<<*>>=
 mkAtree1 x ==
   -- first special handler for making attrib tree
   null x => throwKeyedMsg("S2IP0005",['"NIL"])
@@ -156,8 +143,10 @@ mkAtree1 x ==
   x is [op,:argl] => mkAtree2(x,op,argl)
   systemErrorHere '"mkAtree1"
 
--- mkAtree2 and mkAtree3 were created because mkAtree1 got so big
-
+@
+\subsection{mkAtree2}
+mkAtree2 and mkAtree3 were created because mkAtree1 got so big
+<<*>>=
 mkAtree2(x,op,argl) ==
   nargl := #argl
   (op= '_-) and (nargl = 1) and (INTEGERP CAR argl) =>
@@ -227,6 +216,10 @@ mkAtree2(x,op,argl) ==
       '"not qualifying an operator"])
   mkAtree3(x,op,argl)
 
+@
+\subsection{mkAtree3}
+mkAtree2 and mkAtree3 were created because mkAtree1 got so big
+<<*>>=
 mkAtree3(x,op,argl) ==
   op='REDUCE and argl is [op1,axis,body] =>
     [mkAtreeNode op,axis,mkAtree1 op1,mkAtree1 body]
@@ -314,12 +307,17 @@ mkAtree3(x,op,argl) ==
     mkAtree1 op
   [z,:[mkAtree1 y for y in argl]]
 
+@
+\subsection{collectDefTypesAndPreds}
+Given an arglist to a DEF-like form, this function returns
+a vector of three things:
+\begin{itemize}
+\item slot 0: just the variables
+\item slot 1: the type declarations on the variables
+\item slot 2: a predicate for all arguments
+\end{itemize}
+<<*>>=
 collectDefTypesAndPreds args ==
-  -- given an arglist to a DEF-like form, this function returns
-  -- a vector of three things:
-  --   slot 0: just the variables
-  --   slot 1: the type declarations on the variables
-  --   slot 2: a predicate for all arguments
   pred := types := vars := NIL
   junk :=
     IDENTP args =>
@@ -357,11 +355,17 @@ collectDefTypesAndPreds args ==
     vars  := [args]
   VECTOR(vars,types,pred)
 
+@
+\subsection{mkAtreeValueOf}
+<<*>>=
 mkAtreeValueOf l ==
   -- scans for ['valueOf,atom]
   not CONTAINED('valueOf,l) => l
   mkAtreeValueOf1 l
 
+@
+\subsection{mkAtreeValueOf1}
+<<*>>=
 mkAtreeValueOf1 l ==
   null l or atom l or null rest l => l
   l is ['valueOf,u] and IDENTP u =>
@@ -371,10 +375,16 @@ mkAtreeValueOf1 l ==
     v
   [mkAtreeValueOf1 x for x in l]
 
+@
+\subsection{mkLessOrEqual}
+<<*>>=
 mkLessOrEqual(lhs,rhs) == ['not,['_<,rhs,lhs]]
 
+@
+\subsection{emptyAtree}
+Remove mode, value, and misc. info from attrib tree
+<<*>>=
 emptyAtree expr ==
-  -- remove mode, value, and misc. info from attrib tree
   VECP expr =>
     $immediateDataSymbol = expr.0 => nil
     expr.1:= NIL
@@ -384,8 +394,11 @@ emptyAtree expr ==
   atom expr => nil
   for e in expr repeat emptyAtree e
 
+@
+\subsection{unVectorize}
+Transforms from an atree back into a tree
+<<*>>=
 unVectorize body ==
-  -- transforms from an atree back into a tree
   VECP body =>
     name := getUnname body
     name ^= $immediateDataSymbol => name
@@ -399,9 +412,10 @@ unVectorize body ==
     [newOp,:unVectorize argl]
   systemErrorHere '"unVectorize"
 
-
---  Stuffing and Getting Info
-
+@
+\section{Stuffing and Getting Info}
+\subsection{putAtree}
+<<*>>=
 putAtree(x,prop,val) ==
   x is [op,:.] =>
     -- only willing to add property if op is a vector
@@ -414,6 +428,9 @@ putAtree(x,prop,val) ==
   x.4 := insertShortAlist(prop,val,x.4)
   x
 
+@
+\subsection{getAtree}
+<<*>>=
 getAtree(x,prop) ==
   x is [op,:.] =>
     -- only willing to get property if op is a vector
@@ -425,19 +442,31 @@ getAtree(x,prop) ==
     => x.n
   QLASSQ(prop,x.4)
 
+@
+\subsection{putTarget}
+<<*>>=
 putTarget(x, targ) ==
   -- want to put nil modes perhaps to clear old target
   if targ = $EmptyMode then targ := nil
   putAtree(x,'target,targ)
 
+@
+\subsection{getTarget}
+<<*>>=
 getTarget(x) == getAtree(x,'target)
 
+@
+\subsection{insertShortAlist}
+<<*>>=
 insertShortAlist(prop,val,al) ==
   pair := QASSQ(prop,al) =>
     RPLACD(pair,val)
     al
   [[prop,:val],:al]
 
+@
+\subsection{transferPropsToNode}
+<<*>>=
 transferPropsToNode(x,t) ==
   propList := getProplist(x,$env)
   QLASSQ('Led,propList) or QLASSQ('Nud,propList) => nil
@@ -456,19 +485,32 @@ transferPropsToNode(x,t) ==
     putMode(t,am)
   t
 
-isLeaf x == atom x     --may be a number or a vector
+@
+\subsection{isLeaf}
+May be a number or a vector
+<<*>>=
+isLeaf x == atom x
 
+@
+\subsection{getMode}
+<<*>>=
 getMode x ==
   x is [op,:.] => getMode op
   VECP x => x.1
   m := getBasicMode x => m
   keyedSystemError("S2II0001",[x])
 
+@
+\subsection{putMode}
+<<*>>=
 putMode(x,y) ==
   x is [op,:.] => putMode(op,y)
   null VECP x => keyedSystemError("S2II0001",[x])
   x.1 := y
 
+@
+\subsection{getValue}
+<<*>>=
 getValue x ==
   VECP x => x.2
   atom x =>
@@ -476,40 +518,64 @@ getValue x ==
     keyedSystemError("S2II0001",[x])
   getValue first x
 
+@
+\subsection{putValue}
+<<*>>=
 putValue(x,y) ==
   x is [op,:.] => putValue(op,y)
   null VECP x => keyedSystemError("S2II0001",[x])
   x.2 := y
 
+@
+\subsection{putValueValue}
+<<*>>=
 putValueValue(vec,val) ==
   putValue(vec,val)
   vec
 
+@
+\subsection{getUnnameIfCan}
+<<*>>=
 getUnnameIfCan x ==
   VECP x => x.0
   x is [op,:.] => getUnnameIfCan op
   atom x => x
   nil
 
+@
+\subsection{getUnname}
+<<*>>=
 getUnname x ==
   x is [op,:.] => getUnname op
   getUnname1 x
 
+@
+\subsection{getUnname1}
+<<*>>=
 getUnname1 x ==
   VECP x => x.0
   null atom x => keyedSystemError("S2II0001",[x])
   x
 
+@
+\subsection{computedMode}
+<<*>>=
 computedMode t ==
   getModeSet t is [m] => m
   keyedSystemError("S2GE0016",['"computedMode",'"non-singleton modeset"])
 
+@
+\subsection{putModeSet}
+<<*>>=
 putModeSet(x,y) ==
   x is [op,:.] => putModeSet(op,y)
   not VECP x => keyedSystemError("S2II0001",[x])
   x.3 := y
   y
 
+@
+\subsection{getModeOrFirstModeSetIfThere}
+<<*>>=
 getModeOrFirstModeSetIfThere x ==
   x is [op,:.] => getModeOrFirstModeSetIfThere op
   VECP x =>
@@ -522,6 +588,9 @@ getModeOrFirstModeSetIfThere x ==
   m := getBasicMode x => m
   NIL
 
+@
+\subsection{getModeSet}
+<<*>>=
 getModeSet x ==
   x and PAIRP x => getModeSet first x
   VECP x =>
@@ -535,6 +604,9 @@ getModeSet x ==
   keyedSystemError("S2GE0016",['"getModeSet",
     '"not an attributed tree"])
 
+@
+\subsection{getModeSetUseSubdomain}
+<<*>>=
 getModeSetUseSubdomain x ==
   x and PAIRP x => getModeSetUseSubdomain first x
   VECP(x) =>
@@ -562,8 +634,14 @@ getModeSetUseSubdomain x ==
   keyedSystemError("S2GE0016",
     ['"getModeSetUseSubomain",'"not an attributed tree"])
 
+@
+\subsection{atree2EvaluatedTree}
+<<*>>=
 atree2EvaluatedTree x == atree2Tree1(x,true)
 
+@
+\subsection{atree2Tree1}
+<<*>>=
 atree2Tree1(x,evalIfTrue) ==
   (triple := getValue x) and objMode(triple) ^= $EmptyMode =>
     coerceOrCroak(triple,$OutputForm,$mapName)
@@ -572,12 +650,10 @@ atree2Tree1(x,evalIfTrue) ==
     x
   [atree2Tree1(y,evalIfTrue) for y in x]
 
---% Environment Utilities
-
--- getValueFromEnvironment(x,mode) ==
---   $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$env)) => v
---   $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$e))   => v
---   throwKeyedMsg("S2IE0001",[x])
+@
+\section{Environment Utilities}
+\subsection{getValueFromEnvironment}
+<<*>>=
 getValueFromEnvironment(x,mode) ==
   $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$env)) => v
   $failure ^= (v := getValueFromSpecificEnvironment(x,mode,$e))   => v
@@ -585,6 +661,9 @@ getValueFromEnvironment(x,mode) ==
      throwKeyedMsg("S2IE0001",[x])
   objValUnwrap v
 
+@
+\subsection{getValueFromSpecificEnvironment}
+<<*>>=
 getValueFromSpecificEnvironment(id,mode,e) ==
   PAIRP e =>
     u := get(id,'value,e) =>
@@ -610,6 +689,9 @@ getValueFromSpecificEnvironment(id,mode,e) ==
     $failure
   $failure
 
+@
+\subsection{addBindingInteractive}
+<<*>>=
 addBindingInteractive(var,proplist,e is [[curContour,:.],:.]) ==
   -- change proplist of var in e destructively
   u := ASSQ(var,curContour) =>
@@ -618,21 +700,36 @@ addBindingInteractive(var,proplist,e is 
[[curContour,:.],:.]) ==
   RPLAC(CAAR e,[[var,:proplist],:curContour])
   e
 
+@
+\subsection{augProplistInteractive}
+<<*>>=
 augProplistInteractive(proplist,prop,val) ==
   u := ASSQ(prop,proplist) =>
     RPLACD(u,val)
     proplist
   [[prop,:val],:proplist]
 
+@
+\subsection{getFlag}
+<<*>>=
 getFlag x == get("--flags--",x,$e)
 
+@
+\subsection{putFlag}
+<<*>>=
 putFlag(flag,value) ==
   $e := put ("--flags--", flag, value, $e)
 
+@
+\subsection{get}
+<<*>>=
 get(x,prop,e) ==
   $InteractiveMode => get0(x,prop,e)
   get1(x,prop,e)
 
+@
+\subsection{get0}
+<<*>>=
 get0(x,prop,e) ==
   null atom x => get(QCAR x,prop,e)
   u:= QLASSQ(x,CAR QCAR e) => QLASSQ(prop,u)
@@ -640,6 +737,9 @@ get0(x,prop,e) ==
     QLASSQ(prop,u)
   nil
 
+@
+\subsection{get1}
+<<*>>=
 get1(x,prop,e) ==
     --this is the old get
   null atom x => get(QCAR x,prop,e)
@@ -648,21 +748,39 @@ get1(x,prop,e) ==
       or get2(x,prop,e)
   LASSOC(prop,getProplist(x,e)) or get2(x,prop,e)
 
+@
+\subsection{get2}
+<<*>>=
 get2(x,prop,e) ==
   prop="modemap" and constructor? x =>
     (u := getConstructorModemap(x)) => [u]
     nil
   nil
 
+@
+\subsection{getI}
+<<*>>=
 getI(x,prop) == get(x,prop,$InteractiveFrame)
 
+@
+\subsection{putI}
+<<*>>=
 putI(x,prop,val) == ($InteractiveFrame := put(x,prop,val,$InteractiveFrame))
 
+@
+\subsection{getIProplist}
+<<*>>=
 getIProplist x == getProplist(x,$InteractiveFrame)
 
+@
+\subsection{removeBindingI}
+<<*>>=
 removeBindingI x ==
   RPLAC(CAAR $InteractiveFrame,deleteAssocWOC(x,CAAR $InteractiveFrame))
 
+@
+\subsection{rempropI}
+<<*>>=
 rempropI(x,prop) ==
   id:=
     atom x => x
@@ -672,17 +790,26 @@ rempropI(x,prop) ==
     recordOldValue(id,prop,getI(id,prop))
     $InteractiveFrame:= remprop(id,prop,$InteractiveFrame)
 
+@
+\subsection{remprop}
+<<*>>=
 remprop(x,prop,e) ==
   u:= ASSOC(prop,pl:= getProplist(x,e)) =>
     e:= addBinding(x,DELASC(first u,pl),e)
     e
   e
 
+@
+\subsection{fastSearchCurrentEnv}
+<<*>>=
 fastSearchCurrentEnv(x,currentEnv) ==
   u:= QLASSQ(x,CAR currentEnv) => u
   while (currentEnv:= QCDR currentEnv) repeat
     u:= QLASSQ(x,CAR currentEnv) => u
 
+@
+\subsection{put}
+<<*>>=
 put(x,prop,val,e) ==
   $InteractiveMode and not EQ(e,$CategoryFrame) =>
     putIntSymTab(x,prop,val,e)
@@ -697,6 +824,9 @@ put(x,prop,val,e) ==
     e
   addBinding(x,newProplist,e)
 
+@
+\subsection{putIntSymTab}
+<<*>>=
 putIntSymTab(x,prop,val,e) ==
   null atom x => putIntSymTab(first x,prop,val,e)
   pl0 := pl := search(x,e)
@@ -712,6 +842,9 @@ putIntSymTab(x,prop,val,e) ==
   EQ(pl0,pl) => e
   addIntSymTabBinding(x,pl,e)
 
+@
+\subsection{addIntSymTabBinding}
+<<*>>=
 addIntSymTabBinding(var,proplist,e is [[curContour,:.],:.]) ==
   -- change proplist of var in e destructively
   u := ASSQ(var,curContour) =>
@@ -720,33 +853,55 @@ addIntSymTabBinding(var,proplist,e is 
[[curContour,:.],:.]) ==
   RPLAC(CAAR e,[[var,:proplist],:curContour])
   e
 
+@
+\section{Source and position information}
+In the following, src is a string containing an original input line,
+line is the line number of the string within the source file,
+and col is the index within src of the start of the form represented
+by x. x is a VAT.
 
---% Source and position information
-
--- In the following, src is a string containing an original input line,
--- line is the line number of the string within the source file,
--- and col is the index within src of the start of the form represented
--- by x. x is a VAT.
-
+\subsection{putSrcPos}
+<<*>>=
 putSrcPos(x, file, src, line, col) ==
     putAtree(x, 'srcAndPos, srcPos_New(file, src, line, col))
 
+@
+\subsection{getSrcPos}
+<<*>>=
 getSrcPos(x) == getAtree(x, 'srcAndPos)
 
+@
+\subsection{srcPosNew}
+<<*>>=
 srcPosNew(file, src, line, col) == LIST2VEC [file, src, line, col]
 
+@
+\subsection{srcPosFile}
+<<*>>=
 srcPosFile(sp) ==
     if sp then sp.0 else nil
 
+@
+\subsection{srcPosSource}
+<<*>>=
 srcPosSource(sp) ==
     if sp then sp.1 else nil
 
+@
+\subsection{srcPosLine}
+<<*>>=
 srcPosLine(sp) ==
     if sp then sp.2 else nil
 
+@
+\subsection{srcPosColumn}
+<<*>>=
 srcPosColumn(sp) ==
     if sp then sp.3 else nil
 
+@
+\subsection{srcPosDisplay}
+<<*>>=
 srcPosDisplay(sp) ==
     null sp => nil
     s := STRCONC('"_"", srcPosFile sp, '"_", line ",
@@ -759,58 +914,163 @@ srcPosDisplay(sp) ==
     sayBrightly [fillerSpaces(#s, '" "), dots, '"^"]
     true
 
---% Functions on interpreter objects
-
--- Interpreter objects used to be called triples because they had the
--- structure [value, type, environment].  For many years, the environment
--- was not used, so finally in January, 1990, the structure of objects
--- was changed to be (type . value).  This was chosen because it was the
--- structure of objects of type Any.  Sometimes the values are wrapped
--- (see the function isWrapped to see what this means physically).
--- Wrapped values are not actual values belonging to their types.  An
--- unwrapped value must be evaluated to get an actual value.  A wrapped
--- value must be unwrapped before being passed to a library function.
--- Typically, an unwrapped value in the interpreter consists of LISP
--- code, e.g., parts of a function that is being constructed.
---                 RSS 1/14/90
-
--- These are the new structure functions.
-
+@
+\section{Functions on interpreter objects}
+Interpreter objects used to be called triples because they had the
+structure [value, type, environment].  For many years, the environment
+was not used, so finally in January, 1990, the structure of objects
+was changed to be (type . value).  This was chosen because it was the
+structure of objects of type Any.  Sometimes the values are wrapped
+(see the function isWrapped to see what this means physically).
+Wrapped values are not actual values belonging to their types.  An
+unwrapped value must be evaluated to get an actual value.  A wrapped
+value must be unwrapped before being passed to a library function.
+Typically, an unwrapped value in the interpreter consists of LISP
+code, e.g., parts of a function that is being constructed.
+--  RSS 1/14/90
+
+These are the new structure functions.
+
+\subsection{mkObj}
+<<*>>=
 mkObj(val, mode) == CONS(mode,val)              -- old names
+
+@
+\subsection{mkObjWrap}
+<<*>>=
 mkObjWrap(val, mode) == CONS(mode,wrap val)
+
+@
+\subsection{mkObjCode}
+<<*>>=
 mkObjCode(val, mode) == ['CONS, MKQ mode,val ]
 
+@
+\subsection{objNew}
+<<*>>=
 objNew(val, mode) == CONS(mode,val)             -- new names as of 10/14/93
+
+@
+\subsection{objNewWrap}
+<<*>>=
 objNewWrap(val, mode) == CONS(mode,wrap val)
+
+@
+\subsection{objNewCode}
+<<*>>=
 objNewCode(val, mode) == ['CONS, MKQ mode,val ]
+
+@
+\subsection{objSetVal}
+<<*>>=
 objSetVal(obj,val) == RPLACD(obj,val)
+
+@
+\subsection{objSetMode}
+<<*>>=
 objSetMode(obj,mode) == RPLACA(obj,mode)
 
+@
+\subsection{objVal}
+<<*>>=
 objVal obj == CDR obj
+
+@
+\subsection{objValUnwrap}
+<<*>>=
 objValUnwrap obj == unwrap CDR obj
+
+@
+\subsection{objMode}
+<<*>>=
 objMode obj == CAR obj
+
+@
+\subsection{objEnv}
+<<*>>=
 objEnv obj == $NE
 
+@
+\subsection{objCodeVal}
+<<*>>=
 objCodeVal obj == CADDR obj
-objCodeMode obj == CADR obj
-
 
+@
+\subsection{objCodeMode}
+<<*>>=
+objCodeMode obj == CADR obj
 
-
---% Library compiler structures needed by the interpreter
-
--- Tuples and Crosses
-
+@
+\section{Library compiler structures needed by the interpreter}
+Tuples and Crosses
+\subsection{asTupleNew}
+<<*>>=
 asTupleNew(size, listOfElts) == CONS(size, LIST2VEC listOfElts)
+
+@
+\subsection{asTupleNew0}
+<<*>>=
 asTupleNew0(listOfElts) == CONS(#listOfElts, LIST2VEC listOfElts)
 
+@
+\subsection{asTupleNewCode}
+<<*>>=
 asTupleNewCode(size, listOfElts) == ["asTupleNew", size, ['LIST, :listOfElts]]
+
+@
+\subsection{asTupleNewCode0}
+<<*>>=
 asTupleNewCode0(listForm) == ["asTupleNew0", listForm]
 
+@
+\subsection{asTupleSize}
+<<*>>=
 asTupleSize(at) == CAR at
+
+@
+\subsection{asTupleAsVector}
+<<*>>=
 asTupleAsVector(at) == CDR at
+
+@
+\subsection{asTupleAsList}
+<<*>>=
 asTupleAsList(at) == VEC2LIST asTupleAsVector at
 @
+\section{License}
+<<license>>=
+-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+--     - Redistributions of source code must retain the above copyright
+--       notice, this list of conditions and the following disclaimer.
+--
+--     - Redistributions in binary form must reproduce the above copyright
+--       notice, this list of conditions and the following disclaimer in
+--       the documentation and/or other materials provided with the
+--       distribution.
+--
+--     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+--       names of its contributors may be used to endorse or promote products
+--       derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@
 \eject
 \begin{thebibliography}{99}
 \bibitem{1} nothing




reply via email to

[Prev in Thread] Current Thread [Next in Thread]