diff --git a/books/bookvol5.pamphlet b/books/bookvol5.pamphlet
index 966799a..0052071 100644
--- a/books/bookvol5.pamphlet
+++ b/books/bookvol5.pamphlet
@@ -34526,6 +34526,15 @@ searchCurrentEnv(x,currentEnv) ==
@
+The {\bf initialize-preparse} expects to be called before the {\bf preparse}
+function. It initializes the state, in particular, it reads a single line
+from the input stream and stores it in {\tt \verb|$preparse-last-line|}.
+The caller gives a stream and the {\tt \verb|$preparse-last-line|} variable
+is initialized as:
+\begin{verbatim}
+ 2> (INITIALIZE-PREPARSE #)
+ <2 (INITIALIZE-PREPARSE ")abbrev domain EQ Equation")
+\end{verbatim}
\defun{initialize-preparse}{initialize-preparse}
\calls{initialize-preparse}{get-a-line}
\usesdollar{initialize-preparse}{index}
@@ -34541,6 +34550,167 @@ searchCurrentEnv(x,currentEnv) ==
@
+The {\bf preparse} function returns a list of pairs of the form:
+( (linenumber . linestring) .... (linenumber . linestring))
+For instance, for the file {\tt EQ.spad}, we get:
+\begin{verbatim}
+<2 (PREPARSE (
+ (19 . "Equation(S: Type): public == private where")
+ (20 . " (Ex ==> OutputForm;")
+ (21 . " public ==> Type with")
+ (22 . " (\"=\": (S, S) -> $;")
+ (24 . " equation: (S, S) -> $;")
+ (26 . " swap: $ -> $;")
+ (28 . " lhs: $ -> S;")
+ (30 . " rhs: $ -> S;")
+ (32 . " map: (S -> S, $) -> $;")
+ (35 . " if S has InnerEvalable(Symbol,S) then")
+ (36 . " InnerEvalable(Symbol,S);")
+ (37 . " if S has SetCategory then")
+ (38 . " (SetCategory;")
+ (39 . " CoercibleTo Boolean;")
+ (40 . " if S has Evalable(S) then")
+ (41 . " (eval: ($, $) -> $;")
+ (43 . " eval: ($, List $) -> $));")
+ (45 . " if S has AbelianSemiGroup then")
+ (46 . " (AbelianSemiGroup;")
+ (47 . " \"+\": (S, $) -> $;")
+ (50 . " \"+\": ($, S) -> $);")
+ (53 . " if S has AbelianGroup then")
+ (54 . " (AbelianGroup;")
+ (55 . " leftZero : $ -> $;")
+ (57 . " rightZero : $ -> $;")
+ (59 . " \"-\": (S, $) -> $;")
+ (62 . " \"-\": ($, S) -> $);")
+ (65 . " if S has SemiGroup then")
+ (66 . " (SemiGroup;")
+ (67 . " \"*\": (S, $) -> $;")
+ (70 . " \"*\": ($, S) -> $);")
+ (73 . " if S has Monoid then")
+ (74 . " (Monoid;")
+ (75 . " leftOne : $ -> Union($,\"failed\");")
+ (77 . " rightOne : $ -> Union($,\"failed\"));")
+ (79 . " if S has Group then")
+ (80 . " (Group;")
+ (81 . " leftOne : $ -> Union($,\"failed\");")
+ (83 . " rightOne : $ -> Union($,\"failed\"));")
+ (85 . " if S has Ring then")
+ (86 . " (Ring;")
+ (87 . " BiModule(S,S));")
+ (88 . " if S has CommutativeRing then")
+ (89 . " Module(S);")
+ (91 . " if S has IntegralDomain then")
+ (92 . " factorAndSplit : $ -> List $;")
+ (96 . " if S has PartialDifferentialRing(Symbol) then")
+ (97 . " PartialDifferentialRing(Symbol);")
+ (98 . " if S has Field then")
+ (99 . " (VectorSpace(S);")
+ (100 . " \"/\": ($, $) -> $;")
+ (103 . " inv: $ -> $);")
+ (105 . " if S has ExpressionSpace then")
+ (106 . " subst: ($, $) -> $);")
+ (109 . " private ==> add")
+ (110 . " (Rep := Record(lhs: S, rhs: S);")
+ (111 . " eq1,eq2: $;")
+ (112 . " s : S;")
+ (113 . " if S has IntegralDomain then")
+ (114 . " factorAndSplit eq ==")
+ (115 . " ((S has factor : S -> Factored S) =>")
+ (116 . " (eq0 := rightZero eq;")
+ (117 . " [equation(rcf.factor,0)
+ for rcf in factors factor lhs eq0]);")
+ (118 . " [eq]);")
+ (119 . " l:S = r:S == [l, r];")
+ (120 . " equation(l, r) == [l, r];")
+ (121 . " lhs eqn == eqn.lhs;")
+ (122 . " rhs eqn == eqn.rhs;")
+ (123 . " swap eqn == [rhs eqn, lhs eqn];")
+ (124 . " map(fn, eqn) == equation(fn(eqn.lhs), fn(eqn.rhs));")
+ (125 . " if S has InnerEvalable(Symbol,S) then")
+ (126 . " (s:Symbol;")
+ (127 . " ls:List Symbol;")
+ (128 . " x:S;")
+ (129 . " lx:List S;")
+ (130 . " eval(eqn,s,x) == eval(eqn.lhs,s,x) = eval(eqn.rhs,s,x);")
+ (131 . " eval(eqn,ls,lx) == eval(eqn.lhs,ls,lx) =
+ eval(eqn.rhs,ls,lx));")
+ (132 . " if S has Evalable(S) then")
+ (133 . " (eval(eqn1:$, eqn2:$):$ ==")
+ (134 . " eval(eqn1.lhs, eqn2 pretend Equation S) =")
+ (135 . " eval(eqn1.rhs, eqn2 pretend Equation S);")
+ (136 . " eval(eqn1:$, leqn2:List $):$ ==")
+ (137 . " eval(eqn1.lhs, leqn2 pretend List Equation S) =")
+ (138 . " eval(eqn1.rhs, leqn2 pretend List Equation S));")
+ (139 . " if S has SetCategory then")
+ (140 . " (eq1 = eq2 == (eq1.lhs = eq2.lhs)@Boolean and")
+ (141 . " (eq1.rhs = eq2.rhs)@Boolean;")
+ (142 . " coerce(eqn:$):Ex == eqn.lhs::Ex = eqn.rhs::Ex;")
+ (143 . " coerce(eqn:$):Boolean == eqn.lhs = eqn.rhs);")
+ (144 . " if S has AbelianSemiGroup then")
+ (145 . " (eq1 + eq2 == eq1.lhs + eq2.lhs = eq1.rhs + eq2.rhs;")
+ (146 . " s + eq2 == [s,s] + eq2;")
+ (147 . " eq1 + s == eq1 + [s,s]);")
+ (148 . " if S has AbelianGroup then")
+ (149 . " (- eq == (- lhs eq) = (-rhs eq);")
+ (150 . " s - eq2 == [s,s] - eq2;")
+ (151 . " eq1 - s == eq1 - [s,s];")
+ (152 . " leftZero eq == 0 = rhs eq - lhs eq;")
+ (153 . " rightZero eq == lhs eq - rhs eq = 0;")
+ (154 . " 0 == equation(0$S,0$S);")
+ (155 . " eq1 - eq2 == eq1.lhs - eq2.lhs = eq1.rhs - eq2.rhs);")
+ (156 . " if S has SemiGroup then")
+ (157 . " (eq1:$ * eq2:$ == eq1.lhs * eq2.lhs = eq1.rhs * eq2.rhs;")
+ (158 . " l:S * eqn:$ == l * eqn.lhs = l * eqn.rhs;")
+ (159 . " l:S * eqn:$ == l * eqn.lhs = l * eqn.rhs;")
+ (160 . " eqn:$ * l:S == eqn.lhs * l = eqn.rhs * l);")
+ (165 . " if S has Monoid then")
+ (166 . " (1 == equation(1$S,1$S);")
+ (167 . " recip eq ==")
+ (168 . " ((lh := recip lhs eq) case \"failed\" => \"failed\";")
+ (169 . " (rh := recip rhs eq) case \"failed\" => \"failed\";")
+ (170 . " [lh :: S, rh :: S]);")
+ (171 . " leftOne eq ==")
+ (172 . " ((re := recip lhs eq) case \"failed\" => \"failed\";")
+ (173 . " 1 = rhs eq * re);")
+ (174 . " rightOne eq ==")
+ (175 . " ((re := recip rhs eq) case \"failed\" => \"failed\";")
+ (176 . " lhs eq * re = 1));")
+ (177 . " if S has Group then")
+ (178 . " (inv eq == [inv lhs eq, inv rhs eq];")
+ (179 . " leftOne eq == 1 = rhs eq * inv rhs eq;")
+ (180 . " rightOne eq == lhs eq * inv rhs eq = 1);")
+ (181 . " if S has Ring then")
+ (182 . " (characteristic() == characteristic()$S;")
+ (183 . " i:Integer * eq:$ == (i::S) * eq);")
+ (184 . " if S has IntegralDomain then")
+ (185 . " factorAndSplit eq ==")
+ (186 . " ((S has factor : S -> Factored S) =>")
+ (187 . " (eq0 := rightZero eq;")
+ (188 . " [equation(rcf.factor,0)
+ for rcf in factors factor lhs eq0]);")
+ (189 . " (S has Polynomial Integer) =>")
+ (190 . " (eq0 := rightZero eq;")
+ (191 . " MF ==> MultivariateFactorize(Symbol,
+ IndexedExponents Symbol,
+ Integer, Polynomial Integer);")
+ (193 . " p : Polynomial Integer :=
+ (lhs eq0) pretend Polynomial Integer;")
+ (194 . " [equation((rcf.factor) pretend S,0)
+ for rcf in factors factor(p)$MF]);")
+ (195 . " [eq]);")
+ (196 . " if S has PartialDifferentialRing(Symbol) then")
+ (197 . " differentiate(eq:$, sym:Symbol):$ ==")
+ (198 . " [differentiate(lhs eq, sym), differentiate(rhs eq, sym)];")
+ (199 . " if S has Field then")
+ (200 . " (dimension() == 2 :: CardinalNumber;")
+ (201 . " eq1:$ / eq2:$ == eq1.lhs / eq2.lhs = eq1.rhs / eq2.rhs;")
+ (202 . " inv eq == [inv lhs eq, inv rhs eq]);")
+ (203 . " if S has ExpressionSpace then")
+ (204 . " subst(eq1,eq2) ==")
+ (205 . " (eq3 := eq2 pretend Equation S;")
+ (206 . " [subst(lhs eq1,eq3),subst(rhs eq1,eq3)])))")))
+\end{verbatim}
+
\defun{preparse}{preparse}
\calls{preparse}{preparse}
\calls{preparse}{preparse1}
diff --git a/books/bookvol9.pamphlet b/books/bookvol9.pamphlet
index 9274680..2b7800a 100644
--- a/books/bookvol9.pamphlet
+++ b/books/bookvol9.pamphlet
@@ -427,9 +427,229 @@ the spad compiler does when it encounters an error.
should stop at the first error.
The value of the {\tt )set break} variable then controls what happens.
+\section{EQ.spad}
+We will explain the compilation function using the file {\tt EQ.spad}.
+We trace the execution of the various functions to understand the actual
+call parameters and results returned. The {\tt EQ.spad} file is:
+\begin{verbatim}
+)abbrev domain EQ Equation
+--FOR THE BENEFIT OF LIBAX0 GENERATION
+++ Author: Stephen M. Watt, enhancements by Johannes Grabmeier
+++ Date Created: April 1985
+++ Date Last Updated: June 3, 1991; September 2, 1992
+++ Basic Operations: =
+++ Related Domains:
+++ Also See:
+++ AMS Classifications:
+++ Keywords: equation
+++ Examples:
+++ References:
+++ Description:
+++ Equations as mathematical objects. All properties of the basis domain,
+++ e.g. being an abelian group are carried over the equation domain, by
+++ performing the structural operations on the left and on the
+++ right hand side.
+-- The interpreter translates "=" to "equation". Otherwise, it will
+-- find a modemap for "=" in the domain of the arguments.
+
+Equation(S: Type): public == private where
+ Ex ==> OutputForm
+ public ==> Type with
+ "=": (S, S) -> $
+ ++ a=b creates an equation.
+ equation: (S, S) -> $
+ ++ equation(a,b) creates an equation.
+ swap: $ -> $
+ ++ swap(eq) interchanges left and right hand side of equation eq.
+ lhs: $ -> S
+ ++ lhs(eqn) returns the left hand side of equation eqn.
+ rhs: $ -> S
+ ++ rhs(eqn) returns the right hand side of equation eqn.
+ map: (S -> S, $) -> $
+ ++ map(f,eqn) constructs a new equation by applying f to both
+ ++ sides of eqn.
+ if S has InnerEvalable(Symbol,S) then
+ InnerEvalable(Symbol,S)
+ if S has SetCategory then
+ SetCategory
+ CoercibleTo Boolean
+ if S has Evalable(S) then
+ eval: ($, $) -> $
+ ++ eval(eqn, x=f) replaces x by f in equation eqn.
+ eval: ($, List $) -> $
+ ++ eval(eqn, [x1=v1, ... xn=vn]) replaces xi by vi in equation eqn.
+ if S has AbelianSemiGroup then
+ AbelianSemiGroup
+ "+": (S, $) -> $
+ ++ x+eqn produces a new equation by adding x to both sides of
+ ++ equation eqn.
+ "+": ($, S) -> $
+ ++ eqn+x produces a new equation by adding x to both sides of
+ ++ equation eqn.
+ if S has AbelianGroup then
+ AbelianGroup
+ leftZero : $ -> $
+ ++ leftZero(eq) subtracts the left hand side.
+ rightZero : $ -> $
+ ++ rightZero(eq) subtracts the right hand side.
+ "-": (S, $) -> $
+ ++ x-eqn produces a new equation by subtracting both sides of
+ ++ equation eqn from x.
+ "-": ($, S) -> $
+ ++ eqn-x produces a new equation by subtracting x from both sides of
+ ++ equation eqn.
+ if S has SemiGroup then
+ SemiGroup
+ "*": (S, $) -> $
+ ++ x*eqn produces a new equation by multiplying both sides of
+ ++ equation eqn by x.
+ "*": ($, S) -> $
+ ++ eqn*x produces a new equation by multiplying both sides of
+ ++ equation eqn by x.
+ if S has Monoid then
+ Monoid
+ leftOne : $ -> Union($,"failed")
+ ++ leftOne(eq) divides by the left hand side, if possible.
+ rightOne : $ -> Union($,"failed")
+ ++ rightOne(eq) divides by the right hand side, if possible.
+ if S has Group then
+ Group
+ leftOne : $ -> Union($,"failed")
+ ++ leftOne(eq) divides by the left hand side.
+ rightOne : $ -> Union($,"failed")
+ ++ rightOne(eq) divides by the right hand side.
+ if S has Ring then
+ Ring
+ BiModule(S,S)
+ if S has CommutativeRing then
+ Module(S)
+ --Algebra(S)
+ if S has IntegralDomain then
+ factorAndSplit : $ -> List $
+ ++ factorAndSplit(eq) make the right hand side 0 and
+ ++ factors the new left hand side. Each factor is equated
+ ++ to 0 and put into the resulting list without repetitions.
+ if S has PartialDifferentialRing(Symbol) then
+ PartialDifferentialRing(Symbol)
+ if S has Field then
+ VectorSpace(S)
+ "/": ($, $) -> $
+ ++ e1/e2 produces a new equation by dividing the left and right
+ ++ hand sides of equations e1 and e2.
+ inv: $ -> $
+ ++ inv(x) returns the multiplicative inverse of x.
+ if S has ExpressionSpace then
+ subst: ($, $) -> $
+ ++ subst(eq1,eq2) substitutes eq2 into both sides of eq1
+ ++ the lhs of eq2 should be a kernel
+
+ private ==> add
+ Rep := Record(lhs: S, rhs: S)
+ eq1,eq2: $
+ s : S
+ if S has IntegralDomain then
+ factorAndSplit eq ==
+ (S has factor : S -> Factored S) =>
+ eq0 := rightZero eq
+ [equation(rcf.factor,0) for rcf in factors factor lhs eq0]
+ [eq]
+ l:S = r:S == [l, r]
+ equation(l, r) == [l, r] -- hack! See comment above.
+ lhs eqn == eqn.lhs
+ rhs eqn == eqn.rhs
+ swap eqn == [rhs eqn, lhs eqn]
+ map(fn, eqn) == equation(fn(eqn.lhs), fn(eqn.rhs))
+
+ if S has InnerEvalable(Symbol,S) then
+ s:Symbol
+ ls:List Symbol
+ x:S
+ lx:List S
+ eval(eqn,s,x) == eval(eqn.lhs,s,x) = eval(eqn.rhs,s,x)
+ eval(eqn,ls,lx) == eval(eqn.lhs,ls,lx) = eval(eqn.rhs,ls,lx)
+ if S has Evalable(S) then
+ eval(eqn1:$, eqn2:$):$ ==
+ eval(eqn1.lhs, eqn2 pretend Equation S) =
+ eval(eqn1.rhs, eqn2 pretend Equation S)
+ eval(eqn1:$, leqn2:List $):$ ==
+ eval(eqn1.lhs, leqn2 pretend List Equation S) =
+ eval(eqn1.rhs, leqn2 pretend List Equation S)
+ if S has SetCategory then
+ eq1 = eq2 == (eq1.lhs = eq2.lhs)@Boolean and
+ (eq1.rhs = eq2.rhs)@Boolean
+ coerce(eqn:$):Ex == eqn.lhs::Ex = eqn.rhs::Ex
+ coerce(eqn:$):Boolean == eqn.lhs = eqn.rhs
+ if S has AbelianSemiGroup then
+ eq1 + eq2 == eq1.lhs + eq2.lhs = eq1.rhs + eq2.rhs
+ s + eq2 == [s,s] + eq2
+ eq1 + s == eq1 + [s,s]
+ if S has AbelianGroup then
+ - eq == (- lhs eq) = (-rhs eq)
+ s - eq2 == [s,s] - eq2
+ eq1 - s == eq1 - [s,s]
+ leftZero eq == 0 = rhs eq - lhs eq
+ rightZero eq == lhs eq - rhs eq = 0
+ 0 == equation(0$S,0$S)
+ eq1 - eq2 == eq1.lhs - eq2.lhs = eq1.rhs - eq2.rhs
+ if S has SemiGroup then
+ eq1:$ * eq2:$ == eq1.lhs * eq2.lhs = eq1.rhs * eq2.rhs
+ l:S * eqn:$ == l * eqn.lhs = l * eqn.rhs
+ l:S * eqn:$ == l * eqn.lhs = l * eqn.rhs
+ eqn:$ * l:S == eqn.lhs * l = eqn.rhs * l
+ -- We have to be a bit careful here: raising to a +ve integer is OK
+ -- (since it's the equivalent of repeated multiplication)
+ -- but other powers may cause contradictions
+ -- Watch what else you add here! JHD 2/Aug 1990
+ if S has Monoid then
+ 1 == equation(1$S,1$S)
+ recip eq ==
+ (lh := recip lhs eq) case "failed" => "failed"
+ (rh := recip rhs eq) case "failed" => "failed"
+ [lh :: S, rh :: S]
+ leftOne eq ==
+ (re := recip lhs eq) case "failed" => "failed"
+ 1 = rhs eq * re
+ rightOne eq ==
+ (re := recip rhs eq) case "failed" => "failed"
+ lhs eq * re = 1
+ if S has Group then
+ inv eq == [inv lhs eq, inv rhs eq]
+ leftOne eq == 1 = rhs eq * inv rhs eq
+ rightOne eq == lhs eq * inv rhs eq = 1
+ if S has Ring then
+ characteristic() == characteristic()$S
+ i:Integer * eq:$ == (i::S) * eq
+ if S has IntegralDomain then
+ factorAndSplit eq ==
+ (S has factor : S -> Factored S) =>
+ eq0 := rightZero eq
+ [equation(rcf.factor,0) for rcf in factors factor lhs eq0]
+ (S has Polynomial Integer) =>
+ eq0 := rightZero eq
+ MF ==> MultivariateFactorize(Symbol, IndexedExponents Symbol, _
+ Integer, Polynomial Integer)
+ p : Polynomial Integer := (lhs eq0) pretend Polynomial Integer
+ [equation((rcf.factor) pretend S,0) for rcf in factors factor(p)$MF]
+ [eq]
+ if S has PartialDifferentialRing(Symbol) then
+ differentiate(eq:$, sym:Symbol):$ ==
+ [differentiate(lhs eq, sym), differentiate(rhs eq, sym)]
+ if S has Field then
+ dimension() == 2 :: CardinalNumber
+ eq1:$ / eq2:$ == eq1.lhs / eq2.lhs = eq1.rhs / eq2.rhs
+ inv eq == [inv lhs eq, inv rhs eq]
+ if S has ExpressionSpace then
+ subst(eq1,eq2) ==
+ eq3 := eq2 pretend Equation S
+ [subst(lhs eq1,eq3),subst(rhs eq1,eq3)]
+
+\end{verbatim}
+
+
+\section{Compiling EQ.spad}
Given the top level command:
\begin{verbatim}
-)co PR
+)co EQ
\end{verbatim}
The default call chain looks like:
\begin{verbatim}
@@ -565,84 +785,61 @@ The default call chain looks like:
<22 (|comp| ...)
\end{verbatim}
-\subsection{Aldor compiler}
-\begin{verbatim}
--O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom
-\end{verbatim}
-These options mean:
-\begin{itemize}
-\item {\tt -O}: perform all optimizations,
-\item {\tt -Fasy}: generate a {\tt .asy} file,
-\item {\tt -Fao}: generate a {\tt .ao} file,
-\item {\tt -Flsp}: generate a {\tt .lsp} (Lisp) file,
-\item {\tt -laxiom}: use the {\tt axiom} library {\tt libaxiom.al},
-\item {\tt -Mno-AXL\_W\_WillObsolete}: do not display messages
-about older generated files becoming obsolete, and
-\item {\tt -DAxiom}: define the global assertion {\tt Axiom} so that the
-Aldor libraries for generating stand-alone code
-are not accidentally used with Axiom.
-\end{itemize}
-
-To supplement these default arguments, use the {\tt )moreargs} option on
-{\tt )compile.}
-For example,
+In order to explain the compiler we will walk through the compilation of
+EQ.spad, which handles equations as mathematical objects. We start the
+system. Most of the structure in Axiom are circular so we have to the
+\verb|*print-cycle*| to true.
\begin{verbatim}
-)compile mycode.as )moreargs "-v"
+root@spiff:/tmp# axiom -nox
+
+(1) -> )lisp (setq *print-circle* t)
+
+Value = T
\end{verbatim}
-uses the default arguments and appends the {\tt -v} (verbose)
-argument flag.
-The additional argument specification {\bf must be enclosed in
-double quotes.}
-To completely replace these default arguments for a particular
-use of {\tt )compile}, use the {\tt )onlyargs} option.
-For example,
+We trace the function we find interesting:
\begin{verbatim}
-)compile mycode.as )onlyargs "-v -O"
+(1) -> )lisp (trace |compiler|)
+
+Value = (|compiler|)
\end{verbatim}
-only uses the {\tt -v} (verbose) and {\tt -O} (optimize)
-arguments.
-The argument specification {\bf must be enclosed in double quotes.}
-In this example, Lisp code is not produced and so the compilation
-output will not be available to Axiom.
-
-To completely replace the default arguments for all calls to {\tt
-)compile} within your Axiom session, use {\tt )set compiler args.}
-For example, to use the above arguments for all compilations, issue
+
+\defunsec{compiler}{The top level compiler command}
+We compile the spad file. We can see that the {\bf compiler} function gets
+a list
\begin{verbatim}
-)set compiler args "-v -O"
+(1) -> )co EQ
+
+ 1> (|compiler| (EQ))
\end{verbatim}
-Make sure you include the necessary {\tt -l} and {\tt -Y}
-arguments along with those needed for Lisp file creation.
-As above, {\bf the argument specification must be enclosed in double
-quotes.}
-
-The {\tt )compile} command works with several file extensions. We saw
-above what happens when it is invoked on a file with extension {\tt
-.as.} A {\tt .ao} file is a portable binary compiled version of a
-{\tt .as} file, and {\tt )compile} simply passes the {\tt .ao} file
-onto Aldor. The generated Lisp file is compiled and {\tt )library}
-is automatically called, just as if you had specified a {\tt .as} file.
-
-A {\tt .al} file is an archive file containing {\tt .ao} files. The
-archive is created (on Unix systems) with the {\tt ar} program. When
-{\tt )compile} is given a {\tt .al} file, it creates a directory whose
-name is based on that of the archive. For example, if you issue
+In order to find this file, the {\bf pathname} and {\bf pathnameType}
+functions are used to find the location and pathname to the file. They
+{\bf pathnameType} function eventually returns the fact that this is
+a spad source file. Once that is known we call the {\bf compileSpad2Cmd}
+function with a list containing the full pathname as a string.
\begin{verbatim}
-)compile mylib.al
+ 1> (|compiler| (EQ))
+ 2> (|pathname| (EQ))
+ <2 (|pathname| #p"EQ")
+ 2> (|pathnameType| #p"EQ")
+ 3> (|pathname| #p"EQ")
+ <3 (|pathname| #p"EQ")
+ <2 (|pathnameType| NIL)
+ 2> (|pathnameType| "/tmp/EQ.spad")
+ 3> (|pathname| "/tmp/EQ.spad")
+ <3 (|pathname| #p"/tmp/EQ.spad")
+ <2 (|pathnameType| "spad")
+ 2> (|pathnameType| "/tmp/EQ.spad")
+ 3> (|pathname| "/tmp/EQ.spad")
+ <3 (|pathname| #p"/tmp/EQ.spad")
+ <2 (|pathnameType| "spad")
+ 2> (|pathnameType| "/tmp/EQ.spad")
+ 3> (|pathname| "/tmp/EQ.spad")
+ <3 (|pathname| #p"/tmp/EQ.spad")
+ <2 (|pathnameType| "spad")
+ 2> (|compileSpad2Cmd| ("/tmp/EQ.spad"))
\end{verbatim}
-the directory {\tt mylib.axldir} is created. All members of the
-archive are unarchived into the directory and {\tt )compile} is called
-on each {\tt .ao} file found. It is your responsibility to remove the
-directory and its contents, if you choose to do so.
-A {\tt .lsp} file is a Lisp source file, generated by Aldor
-when called with the {\tt -Flsp} option. When {\tt )compile} is used
-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.
-
-\defunsec{compiler}{The top level compiler command}
\calls{compiler}{helpSpad2Cmd(5)}
\calls{compiler}{selectOptionLC(5)}
\calls{compiler}{pathname(5)}
@@ -652,10 +849,7 @@ generated from the same source file.
\calls{compiler}{throwKeyedMsg}
\calls{compiler}{findfile}
\calls{compiler}{compileSpad2Cmd}
-\calls{compiler}{compileAsharpLispCmd}
\calls{compiler}{compileSpadLispCmd}
-\calls{compiler}{compileAsharpCmd}
-\calls{compiler}{compileAsharpArchiveCmd}
\usesdollar{compiler}{newConlist}
\usesdollar{compiler}{options}
\uses{compiler}{/editfile}
@@ -691,41 +885,19 @@ generated from the same source file.
(setq af (|pathname| args))
(setq aft (|pathnameType| af))
(cond
- ((or havenew (string= aft "as"))
- (if (null (setq af1 ($findfile af '(|as|))))
- (|throwKeyedMsg| 's2il0003 (cons (namestring af) nil))
- (|compileAsharpCmd| (cons af1 nil))))
((or haveold (string= aft "spad"))
(if (null (setq af1 ($findfile af '(|spad|))))
(|throwKeyedMsg| 's2il0003 (cons (namestring af) nil))
(|compileSpad2Cmd| (cons af1 nil))))
- ((string= aft "lsp")
- (if (null (setq af1 ($findfile af '(|lsp|))))
- (|throwKeyedMsg| 's2il0003 (cons (namestring af) nil))
- (|compileAsharpLispCmd| (cons af1 nil))))
((string= aft "nrlib")
(if (null (setq af1 ($findfile af '(|nrlib|))))
(|throwKeyedMsg| 'S2IL0003 (cons (namestring af) nil))
(|compileSpadLispCmd| (cons af1 nil))))
- ((string= aft "ao")
- (if (null (setq af1 ($findfile af '(|ao|))))
- (|throwKeyedMsg| 's2il0003 (cons (namestring af) nil))
- (|compileAsharpCmd| (cons af1 nil))))
- ((string= aft "al")
- (if (null (setq af1 ($findfile af '(|al|))))
- (|throwKeyedMsg| 's2il0003 (cons (namestring af) nil))
- (|compileAsharpArchiveCmd| (cons af1 nil))))
(t
- (setq af1 ($findfile af '(|as| |spad| |ao| |asy|)))
+ (setq af1 ($findfile af '(|spad|)))
(cond
- ((and af1 (string= (|pathnameType| af1) "as"))
- (|compileAsharpCmd| (cons af1 nil)))
- ((and af1 (string= (|pathnameType| af1) "ao"))
- (|compileAsharpCmd| (cons af1 nil)))
((and af1 (string= (|pathnameType| af1) "spad"))
(|compileSpad2Cmd| (cons af1 nil)))
- ((and af1 (string= (|pathnameType| af1) "asy"))
- (|compileAsharpArchiveCmd| (cons af1 nil)))
(t
(setq ef (|pathname| /editfile))
(setq ef (|mergePathnames| af ef))
@@ -734,33 +906,88 @@ generated from the same source file.
(t
(setq af ef)
(cond
- ((string= (|pathnameType| af) "as")
- (|compileAsharpCmd| args))
- ((string= (|pathnameType| af) "ao")
- (|compileAsharpCmd| args))
((string= (|pathnameType| af) "spad")
(|compileSpad2Cmd| args))
(t
- (setq af1 ($findfile af '(|as| |spad| |ao| |asy|)))
+ (setq af1 ($findfile af '(|spad|)))
(cond
- ((and af1 (string= (|pathnameType| af1) "as"))
- (|compileAsharpCmd| (cons af1 nil)))
- ((and af1 (string= (|pathnameType| af1) "ao"))
- (|compileAsharpCmd| (cons af1 nil)))
((and af1 (string= (|pathnameType| af1) "spad"))
(|compileSpad2Cmd| (cons af1 nil)))
- ((and af1 (string= (|pathnameType| af1) "asy"))
- (|compileAsharpArchiveCmd| (cons af1 nil)))
(t (|throwKeyedMsg| 's2iz0039 nil)))))))))))))))))
@
+
\defunsec{compileSpad2Cmd}{The Spad compiler top level function}
-This is the old compiler.
-Assume we entered from the "compiler" function, so args is
-a file with file extension .spad.
+The argument to this function, as noted above, is a list containing
+the string pathname to the file.
+\begin{verbatim}
+ 2> (|compileSpad2Cmd| ("/tmp/EQ.spad"))
+\end{verbatim}
+There is a fair bit of redundant work to find the full filename and pathname
+of the file. This needs to be eliminated.
+
+The trace of the functions in this routines is:
+\begin{verbatim}
+ 1> (|selectOptionLC| "compiler" (|abbreviations| |boot| |browse| |cd| |clear| |close| |compiler| |copyright| |credits| |describe| |display| |edit| |fin| |frame| |help| |history| |lisp| |library| |load| |ltrace| |pquit| |quit| |read| |savesystem| |set| |show| |spool| |summary| |synonym| |system| |trace| |trademark| |undo| |what| |with| |workfiles| |zsystemdevelopment|) |commandErrorIfAmbiguous|)
+ <1 (|selectOptionLC| |compiler|)
+ 1> (|selectOptionLC| |compiler| (|abbreviations| |boot| |browse| |cd| |clear| |close| |compiler| |copyright| |credits| |describe| |display| |edit| |fin| |frame| |help| |history| |lisp| |library| |load| |ltrace| |pquit| |quit| |read| |savesystem| |set| |show| |spool| |summary| |synonym| |system| |trace| |trademark| |undo| |what| |with| |workfiles| |zsystemdevelopment|) |commandError|)
+ <1 (|selectOptionLC| |compiler|)
+ 1> (|pathname| (EQ))
+ <1 (|pathname| #p"EQ")
+ 1> (|pathnameType| #p"EQ")
+ 2> (|pathname| #p"EQ")
+ <2 (|pathname| #p"EQ")
+ <1 (|pathnameType| NIL)
+ 1> (|pathnameType| "/tmp/EQ.spad")
+ 2> (|pathname| "/tmp/EQ.spad")
+ <2 (|pathname| #p"/tmp/EQ.spad")
+ <1 (|pathnameType| "spad")
+ 1> (|pathnameType| "/tmp/EQ.spad")
+ 2> (|pathname| "/tmp/EQ.spad")
+ <2 (|pathname| #p"/tmp/EQ.spad")
+ <1 (|pathnameType| "spad")
+ 1> (|pathnameType| "/tmp/EQ.spad")
+ 2> (|pathname| "/tmp/EQ.spad")
+ <2 (|pathname| #p"/tmp/EQ.spad")
+ <1 (|pathnameType| "spad")
+ 1> (|compileSpad2Cmd| ("/tmp/EQ.spad"))
+ 2> (|pathname| ("/tmp/EQ.spad"))
+ <2 (|pathname| #p"/tmp/EQ.spad")
+ 2> (|pathnameType| #p"/tmp/EQ.spad")
+ 3> (|pathname| #p"/tmp/EQ.spad")
+ <3 (|pathname| #p"/tmp/EQ.spad")
+ <2 (|pathnameType| "spad")
+ 2> (|updateSourceFiles| #p"/tmp/EQ.spad")
+ 3> (|pathname| #p"/tmp/EQ.spad")
+ <3 (|pathname| #p"/tmp/EQ.spad")
+ 3> (|pathname| #p"/tmp/EQ.spad")
+ <3 (|pathname| #p"/tmp/EQ.spad")
+ 3> (|pathnameType| #p"/tmp/EQ.spad")
+ 4> (|pathname| #p"/tmp/EQ.spad")
+ <4 (|pathname| #p"/tmp/EQ.spad")
+ <3 (|pathnameType| "spad")
+ 3> (|pathname| ("EQ" "spad" "*"))
+ <3 (|pathname| #p"EQ.spad")
+ 3> (|pathnameType| #p"EQ.spad")
+ 4> (|pathname| #p"EQ.spad")
+ <4 (|pathname| #p"EQ.spad")
+ <3 (|pathnameType| "spad")
+ <2 (|updateSourceFiles| #p"EQ.spad")
+ 2> (|namestring| ("/tmp/EQ.spad"))
+ 3> (|pathname| ("/tmp/EQ.spad"))
+ <3 (|pathname| #p"/tmp/EQ.spad")
+ <2 (|namestring| "/tmp/EQ.spad")
+ Compiling AXIOM source code from file /tmp/EQ.spad using old system
+ compiler.
+\end{verbatim}
+
+Again we find a lot of redundant work. We finally end up calling
+{\bf compilerDoit} with a constructed argument list:
+\begin{verbatim}
+ 2> (|compilerDoit| NIL (|rq| |lib|))
+\end{verbatim}
+
-The \verb|$f| and \verb|$m| are compiler variables, probably function
-and mode.
\calls{compileSpad2Cmd}{pathname(5)}
\calls{compileSpad2Cmd}{pathnameType(5)}
\calls{compileSpad2Cmd}{namestring(5)}
@@ -824,9 +1051,7 @@ and mode.
(setq optargs (cdr opt))
(setq fullopt (|selectOptionLC| optname optlist nil))
(case fullopt
- (|new| (|error| '|Internal error: compileSpad2Cmd got )new|))
(|old| nil)
- (|translate| (setq translateoldtonew t))
(|library| (setelt fun 1 '|lib|))
(|nolibrary| (setelt fun 1 '|nolib|))
(|quiet| (when (nequal (elt fun 0) '|c|) (setelt fun 0 '|rq|)))
@@ -850,12 +1075,6 @@ and mode.
(list (strconc ")" (|object2String| optname)))))))
(setq |$InteractiveMode| nil)
(cond
- (translateoldtonew
- (|oldParserAutoloadOnceTrigger|)
- (|browserAutoloadOnceTrigger|)
- (|spad2AsTranslatorAutoloadOnceTrigger|)
- (|sayKeyedMsg| 's2iz0085 nil)
- (|convertSpadToAsFile| path))
(|$compileOnlyCertainItems|
(if (null constructor)
(|sayKeyedMsg| 's2iz0040 nil)
@@ -866,6 +1085,23 @@ and mode.
(|spadPrompt|)))))
@
+
+This trivial function cases on the second argument to decide which
+combination of operations was requested. For this case we see:
+\begin{verbatim}
+(1) -> )co EQ
+ Compiling AXIOM source code from file /tmp/EQ.spad using old system
+ compiler.
+ 1> (|compilerDoit| NIL (|rq| |lib|))
+ 2> (|/RQ,LIB|)
+
+... [snip]...
+
+ <2 (|/RQ,LIB| T)
+ <1 (|compilerDoit| T)
+(1) ->
+\end{verbatim}
+
\defun{compilerDoit}{compilerDoit}
\calls{compilerDoit}{/rq(5)}
\calls{compilerDoit}{/rf(5)}
@@ -891,6 +1127,48 @@ and mode.
@
+This function simply calls {\bf \verb|/rf-1|}.
+\begin{verbatim}
+(2) -> )co EQ
+ Compiling AXIOM source code from file /tmp/EQ.spad using old system
+ compiler.
+ 1> (|compilerDoit| NIL (|rq| |lib|))
+ 2> (|/RQ,LIB|)
+ 3> (/RF-1 NIL)
+...[snip]...
+ <3 (/RF-1 T)
+ <2 (|/RQ,LIB| T)
+ <1 (|compilerDoit| T)
+\end{verbatim}
+
+\defun{/RQ,LIB}{/RQ,LIB}
+\calls{/RQ,LIB}{/rf-1(5)}
+\uses{/RQ,LIB}{echo-meta(5)}
+\usesdollar{/RQ,LIB}{lisplib}
+<>=
+(defun |/RQ,LIB| (&rest foo &aux (echo-meta nil) ($lisplib t))
+ (declare (special echo-meta $lisplib))
+ (/rf-1 nil))
+
+@
+
+Since this function is called with nil we fall directly into the
+call to the function {\bf spad}:
+\begin{verbatim}
+(2) -> )co EQ
+ Compiling AXIOM source code from file /tmp/EQ.spad using old system
+ compiler.
+ 1> (|compilerDoit| NIL (|rq| |lib|))
+ 2> (|/RQ,LIB|)
+ 3> (/RF-1 NIL)
+ 4> (SPAD "/tmp/EQ.spad")
+...[snip]...
+ <4 (SPAD T)
+ <3 (/RF-1 T)
+ <2 (|/RQ,LIB| T)
+ <1 (|compilerDoit| T)
+\end{verbatim}
+
\defun{/rf-1}{/rf-1}
\calls{/rf-1}{makeInputFilename(5)}
\calls{/rf-1}{ncINTERPFILE}
@@ -910,6 +1188,427 @@ and mode.
@
+Here we begin the actual compilation process.
+\begin{verbatim}
+ 1> (SPAD "/tmp/EQ.spad")
+ 2> (|makeInitialModemapFrame|)
+ <2 (|makeInitialModemapFrame| ((NIL)))
+ 2> (INIT-BOOT/SPAD-READER)
+ <2 (INIT-BOOT/SPAD-READER NIL)
+ 2> (OPEN "/tmp/EQ.spad" :DIRECTION :INPUT)
+ <2 (OPEN #)
+ 2> (INITIALIZE-PREPARSE #)
+ <2 (INITIALIZE-PREPARSE ")abbrev domain EQ Equation")
+ 2> (PREPARSE #)
+ EQ abbreviates domain Equation
+ <2 (PREPARSE (# # # # # # # # ...))
+ 2> (|PARSE-NewExpr|)
+ <2 (|PARSE-NewExpr| T)
+ 2> (S-PROCESS (|where| # #))
+...[snip]...
+ 3> (OPEN "/tmp/EQ.erlib/info" :DIRECTION :OUTPUT)
+ <3 (OPEN #