\start
Date: Wed, 1 Aug 2007 02:13:23 -0400
From: Bill Page
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC
Cc: Camm Maguire

On 31 Jul 2007 22:24:49 -0400, Stephen Wilson wrote:
> Camm Maguire writes:
> ...
> > 2) The only rationale for a non-commercial use clause that I can see
> >    is to keep open the possibility of a controlled separate licensing
> >    to particular entites for commercial use.

The intention of NAG as very clearly articulated by Steven Watt at the
Axiom meeting, is to reserve the right to derive some income from
Aldor through an alternate form of licensing (or some other proposal)
*if* any developer of Aldor finds some way to include Aldor in a
product or service for which they receive income. Mike Dewar of NAG
has also explained this same point of view both on and off this list.

So if you use Aldor to write a program to design a new airplane and
make a lot of money selling the airplane - no problem, go for it. The
airplane does not incorporate Aldor. But if you create a software
package e.g. a new computer algebra system that includes Aldor and
market it as a competitor to Maple then aldor.org will want a piece of
that action.

Understanding exactly what is meant by charging for "services related
to Aldor" seems harder but Stephen said that they would publish an
interpretation of the license that makes it clear that this does *not*
include services such as teaching a course in how to program in Aldor
or otherwise using it for most academic purposes and research.

> >    Thus, open Aldor ideally could make significant strides which would be
> >    available to the  commercial version, but the latter could "embrace and
> >    extend" the former, effectively co-opting this work and potentially draining
> >    open Aldor of its user and developer base.

Do you mean that volunteer developers should somehow be protected from
competition with commercially-oriented developers? We do not know
exactly what form a commercial license for Aldor would take but my
impression from talking with Stephen Watt is that he is open to
suggestions and proposals.

What prevents work contributed to Axiom right now from being abused in
this way now?

> >    The copyright holder  can argue that they earn the moral right to this
> >    option with the initial source release, but the point as I see it is that no
> >    volunteer should consider sinking in large quantities of time and
> >    labor in scaling a steep learning curve and improving the system
> >    for free if the system isn't effectively guaranteed a very long
> >    lifetime as a vibrant open source project.

Isn't that a problem with any open source project (even Axiom)?
Ensuring that Aldor has a long (or at least longer) life is one of the
motivations for making it publicly available in the first place. As
far as I can see distributing Aldor freely for non-commerical use is
the best possible guarantee of this.

> >   The calculus for a volunteer is that the benefit accrued from one's own
> >    learning and that of many others over a long payoff period more than
> >    compensates for the time lost upfront scaling the learning curve and possibly
> >    tailoring the system to any particular needs.
> >

I think there are many possible motivtions for volunteers and
certainly sharing and collaborating with others is one of them. I do
not really understand why you think
the APL2 non-commercial use clause would make that any less likely.

> > Just my $0.02.
>
> Thats worth a lot more than $0.02, IMHO.
>

I agree that it is worth a lot, but personally would not want to put a
monetary value on it. :)

\start
Date: Wed, 1 Aug 2007 02:51:37 -0400
From: Bill Page
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

On 7/31/07, C Y wrote:
> --- Bill Page wrote:
> ...
> >
> > I dont know anything about Intellectual property laws in the US but
> > isnt "Axiom" too common a word to qualify as a trademark?
>
> The fact that NAG DID have it registered as a trademark when it was a
> commercial product would seem to be conclusive proof that it is not too
> common to qualify.  Many other "common" words act as trademarks - have
> a look in the uspto's trademark search engine.
>

Actually isn't the Axiom "trademark" the logo with the character i
having both an upper and lower dot? (See
http://wiki.axiom-developer.org ) Maybe that is what makes it
sufficiently unique?

\start
Date: Wed, 1 Aug 2007 06:23:16 -0700 (PDT)
From: Cliff Yapp
To: Bill Page
Subject: Re: Axiom meeting at ISSAC

--- Bill Page wrote:

> > >  Thus, open Aldor ideally could make significant strides which
> > > would be available to the  commercial version, but the latter
> > > could "embrace and extend" the former, effectively co-opting this
> > > work and potentially draining open Aldor of its user and
> > > developer base.
> 
> Do you mean that volunteer developers should somehow be protected
> from competition with commercially-oriented developers?

I don't think he means that.  If I understand correctly the terms of
this license, any commercial activity around the code base can be
undertaken ONLY by those with the exclusive rights to do so.  With GPL,
it is possible to sell services related to the use of the software. 
Also, the provision "you grant Aldor.org a royalty-free license to use,
modify or redistribute your modifications without limitation" would
seem to be a blanket grant to Aldor.org exclusively to take everyone's
work and incorporate it into some future Aldor that shifts to a closed
source license again.

I understand why they have these terms in the license and that is their
right, but for me it is a non-starter.

> We do not know exactly what form a commercial license for Aldor would
> take but my impression from talking with Stephen Watt is that he is
> open to suggestions and proposals.
> 
> What prevents work contributed to Axiom right now from being abused
> in this way now?

The difference with Axiom in its current form is that ANYONE can make a
closed source product from the Axiom codebase.  That in turn makes it
less likely, because any commercial company who tries it may find
themselves up against a competitor tomorrow with almost the same
product to offer.  Aldor.org, in contrast, wouldn't face any such
competition because they have exclusive rights to take any work on
Aldor and incorporate it into their own commercial product.

The benefit to Axiom's current licensing setup, in my eyes, is that
ANYONE can use the code for anything they want to do.  With Aldor, only
Aldor.org may use the code for anything they want to do.

>From my standpoint, if the Axiom project starts to achieve results that
are new in the CAS/mathematical community it is to everyone's interest
that that work be used as far and wide as possible.  Anyone trying to
duplicate it would be an artificial waste of effort imposed by
licensing restrictions.  If MathCAD wanted to use Axiom as a foundation
for symbolic operations, that's great!  It would mean better quality
results for users of MathCAD.  It would be nice if they would
contribute back any fixes, and GPL/LGPL advocates would select that
license because it would guarantee those fixes would come back.  I'm
divided in my mind whether wide use of the mathematical abilities of
the code and trusting to a common sense of purpose is better than LGPL
- we want both wide usage and community involvement.

> > > The copyright holder  can argue that they earn the moral right
> > > to this option with the initial source release, but the point as
> > > I see it is that no volunteer should consider sinking in large
> > > quantities of time and labor in scaling a steep learning curve
> > > and improving the system for free if the system isn't effectively
> > > guaranteed a very long lifetime as a vibrant open source project.
> 
> Isn't that a problem with any open source project (even Axiom)?

Yes, but the licensing terms can kill that spirit from the outset. 
With Axiom, whatever happens, the original code base will be freely
available and can be worked on by anyone with the interest, ability,
and time.   Suppose the Aldor.org organization ends the community
version of Aldor, takes all modifications made to date, and beings
selling Visual Aldor or some such.  The community would be stuck,
because they would have to work only with the last open version of
Aldor and any work they did on it could go straight into the
proprietary version.  Aldor.org has no obligations to the community,
and the non-commercial clause means that no one can even try forming
their own commercial Aldor to help support the community version.  In
the case of Axiom, the latter is still possible.  And if a company
tries such a stunt, the open version of Axiom can shift to the GPL and
cut off the commercial company from any further community support if
they get too antisocial.  There's a balance of power.

> Ensuring that Aldor has a long (or at least longer) life is one of
> the motivations for making it publicly available in the first place.
> As far as I can see distributing Aldor freely for non-commerical use
> is the best possible guarantee of this.

Free for non-commercial use doesn't have too many examples of success
in the open source community.  Rather than worry about what constitutes
commercial use and how to get users when THEY need to worry about what
is commercial use, at least some people will just find a tool without
those complications.  For me this license is out of the question.  I
wish them well but I personally won't use Aldor with these terms.

> I think there are many possible motivations for volunteers and
> certainly sharing and collaborating with others is one of them. I do
> not really understand why you think the APL2 non-commercial use
> clause would make that any less likely.

A lot of open source work is funded by companies like Redhat that do
commercial things with open source software while giving all
modifications back to the community.  Aldor.org's license would prevent
any of this sort of activity, as I understand it.

It's about being part of the community, not just making use of the
community labor pool.

\start
Date: 01 Aug 2007 09:25:22 -0500
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

Cliff Yapp writes:

[...]

| That's probably a moot point, at least at the present time - why would
| anyone want to fork Aldor?

Why would anyone want to fork Axiom?

| My opinion is that the non-commercial restriction is a no-go - I would
| prefer to work with Steven on his new language.

You still have the opportunity to go to the Aldor workshop and disucss
that with Stephen.  Assuming you're interested in Aldor.  If you're
not, then...  

\start
Date: 01 Aug 2007 09:27:59 -0500
From: Gabriel Dos Reis
To: Ondrej Certik
Subject: Re: Axiom meeting at ISSAC

Ondrej Certik writes:

[...]

| So it cannot go to the Debian main distribution, and that of course is
| a major problem, at least for me.

The linux distribution I've been for a decade now has a button that
let me install "non-open source" software of highly practical value to me.

\start
Date: 01 Aug 2007 09:30:26 -0500
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

Cliff Yapp writes:

[...]

| If Axiom depended on Aldor, it could not be used for such an
| undertaking.

Nobody prevents you from building an Aldor compiler, written in Lisp
for example.  

\start
Date: 01 Aug 2007 09:38:11 -0500
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

Cliff Yapp writes:

[...]

|                               If I understand correctly the terms of
| this license, any commercial activity around the code base can be
| undertaken ONLY by those with the exclusive rights to do so.

We can spend lot of time speculating; I would have thought that asking
Stephen directly about the real intent and meaning of license would be
more productive than pure speculation.  So I asked him.  And he answered.
And the answer was reported here.  But, I suspect pure speculation has
higher value than the real thing.

\start
Date: 01 Aug 2007 10:55:34 -0400
From: Stephen Wilson
To: Camm Maguire
Subject: gclcvs-2.7.0 and Axiom

Hello Camm,

I am interested in your opinion about the following error, which is
occurring for me during the compilation of src/algebra/tree.spad:

-------
 Error: 
 Fast links are on: do (si::use-fast-links nil) for debugging
 Signalled by |NEWLOOKUPINADDCHAIN|.
 Condition in |newLookupInAddChain| [or a callee]: INTERNAL-SIMPLE-TYPE-ERROR: #<FREE OBJECT 01ce05c8> is not of type FUNCTION: 

 Broken at |NEWLOOKUPINADDCHAIN|.  Type :H for Help.
  1 (Continue) Return to top level.
 BOOT>>:bt

 #0   newLookupInAddChain {loc0=|empty?|,loc1=((|Boolean|) $),loc2=#<vector 01f8d9f0>,loc3=#<vector 01f8d9...} [ihs=14]
 #1   genDeltaEntry {loc0=(|empty?| (#1=(|List| s) (|Boolean|) (|List| s)) (t (elt #1# #))),loc1=(el...} [ihs=13]
 #2   compForm3 {loc0=(|empty?| |ls|),loc1=|$EmptyMode|,loc2=(((# # # ...))),loc3=(((#1=# # #) (...} [ihs=12]
 #3   compForm {loc0=(|empty?| |ls|),loc1=|$EmptyMode|,loc2=(((# # # ...))),loc3=nil,loc4=speci...} [ihs=11]
 #4   setqSingle {loc0=#:g2300,loc1=(|empty?| |ls|),loc2=|NoValueMode|,loc3=(((# # # ...))),loc4=...} [ihs=10]
 #5   compSeq1 {loc0=((let #1=#:g2300 (|empty?| |ls|)) (|exit| 1 (if #1# # ...))),loc1=($),loc2...} [ihs=9]
 #6   compDefineCapsuleFunction {loc0=(def (|tree| |ls|) (nil nil) ...),loc1=|$EmptyMode|,loc2=(((# # # ...))),l...} [ihs=8]
 #7   compCapsuleInner {loc0=((mdef (|cycleTreeMax|) (nil) ...) (qsetrefv $ 7 ...) (|:| |t| $) ...),loc...} [ihs=7]
 #8   comp {loc0=(|where| (def (|Tree| s) (# nil) ...) (|:| s (|SetCategory|))),loc1=|$Empt...} [ihs=6]
 #9   SpadInterpretStream {loc0=1,loc1=(tim daly ?),loc2=t,loc3=nil,loc4="doc",loc5="spadhelp",loc6="axiom...} [ihs=3]
 #10   spad {loc0=|.axiom|,loc1=nil,loc2=nil,loc3=#<synonym stream to *terminal-io*>,loc4=25...} [ihs=2]
-------

The function |newLookupInAddChain| is defined in
src/interp/nrunfast.boot.pamphlet, and everything appears to be in
order on the Axiom side, however:

This is proving to be very difficult to debug, since I cannot
reproduce except by starting Axiom and immediately compiling the file.
If I do (si::use-fast-links nil) the problem goes away. Attempting to
trace any of the above functions, or even typing "1+1" at the axiom
prompt before compiling, the problem goes away.

This behavior is new, so I suspect a change in gclcvs. If this is a
GCL issue, I am hoping that you might be able to understand what this
problem could be, or perhaps suggest a technique to debug it.  If
there is anything I can do to provide more information please let me
know.

\start
Date: Wed, 1 Aug 2007 08:09:34 -0700 (PDT)
From: Cliff Yapp
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

--- Gabriel Dos Reis wrote:

> Cliff Yapp writes:
> 
> [...]
> 
> | If I understand correctly the terms of
> | this license, any commercial activity around the code base can be
> | undertaken ONLY by those with the exclusive rights to do so.
> 
> We can spend lot of time speculating; I would have thought that
> asking Stephen directly about the real intent and meaning of license
> would be more productive than pure speculation.  So I asked him.
> And he answered. And the answer was reported here.  But, I suspect
> pure speculation has higher value than the real thing.

I beg your pardon - I did not intend to imply discourtesy by seeming to
ignore the previous information.  However, I view the details of the
license text itself as important independent of the intent of the
authors.

Whatever the intent may be, the legal text of the license itself is
what will ultimately govern what can and cannot be done, within the
limits of the law.  That is why I focus on the text of the license
itself - intent lasts only as long as the individuals doing the
intending.

I am sure the Aldor.org and NAG organizations in their current forms
would be very reasonable to work with on almost any application of the
Aldor code.  However, the point is that organizations and licensing
terms outlive individuals and management teams and policy setters. 
That is why such care has been given to the wording and text of the
GPLv3, for example - because whatever the intent of the authors the
license text itself ultimately governs.  Relying in the long term on
the good will of individuals or organizations is too dangerous.  It's
about future proofing - what will Aldor.org look like as an
organization in 50 years? 100?  Could their resources and copyrights be
bought by someone else?  How can this license be abused if the
copyrights fall under control of someone inclined to abuse it?

Anyway, it's a fairly moot point.  As you state, both the license text
and clear intent statements are available.  Each of us will make
his/her own decisions in light of that information.

\start
Date: Wed, 1 Aug 2007 08:17:30 -0700 (PDT)
From: Cliff Yapp
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

--- Gabriel Dos Reis wrote:

> Cliff Yapp writes:
> 
> [...]
> 
> | If Axiom depended on Aldor, it could not be used for such an
> | undertaking.
> 
> Nobody prevents you from building an Aldor compiler, written in Lisp
> for example.  

Indeed, Steve's new compiler may end up looking like that - we'll see. 
If Aldor and the new compiler are both able to compile the Axiom
Algebra that's the best case scenario.

\start
Date: Wed, 1 Aug 2007 10:51:11 -0500 (CDT)
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, C Y wrote:

| Whatever the intent may be, the legal text of the license itself is
| what will ultimately govern what can and cannot be done, within the
| limits of the law.  That is why I focus on the text of the license
| itself - intent lasts only as long as the individuals doing the
| intending.

I would encourage anyone to whom this issue really matters to attend the
Aldor workshop and voice their concerns in face-to-face meetings.

I know some people already booked; I would encourage others to consider
attending.

\start
Date: Wed, 1 Aug 2007 10:52:32 -0500 (CDT)
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, C Y wrote:

| 
| --- Gabriel Dos Reis wrote:
| 
| > Cliff Yapp writes:
| > 
| > [...]
| > 
| > | If Axiom depended on Aldor, it could not be used for such an
| > | undertaking.
| > 
| > Nobody prevents you from building an Aldor compiler, written in Lisp
| > for example.  
| 
| Indeed, Steve's new compiler may end up looking like that - we'll see. 
| If Aldor and the new compiler are both able to compile the Axiom
| Algebra that's the best case scenario.

I think Aldor.org would not mind a second implementation -- at least, when
the question was raised, the answer was "go for it!".

\start
Date: Wed, 1 Aug 2007 11:55:57 -0400
From: Didier Deshommes
To: list
Subject: Axiom meeting at ISSAC

(Sorry, meant to send this to the whole list)

---------- Forwarded message ----------

31 Jul 2007 21:18:26 -0400, Stephen Wilson:
> FYI, this is already being seriously pursued in an experimental branch
> of the Axiom system, and the Aldor question does not impact that
> effort.  If at all interested in the details, please do not hesitate
> to ask.

Hi Stephen,
That sounds very interesting. How developed is this? Does it have the
same goals as Aldor? Does it aim to be compatible with Aldor? Any
information providing some kind of comparison of this vs Aldor would
be appreciated.

\start
Date: 01 Aug 2007 14:13:56 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gabriel Dos Reis writes:
> | Indeed, Steve's new compiler may end up looking like that - we'll see. 
> | If Aldor and the new compiler are both able to compile the Axiom
> | Algebra that's the best case scenario.
> 
> I think Aldor.org would not mind a second implementation -- at least, when
> the question was raised, the answer was "go for it!".

I am not going to re-implement Aldor.  I am going to re-implement SPAD,
along with some features Aldor already has, and some features Aldor
does not.

\start
Date: Wed, 1 Aug 2007 13:44:20 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > CY wrote:
| > | Indeed, Steve's new compiler may end up looking like that - we'll see. 
| > | If Aldor and the new compiler are both able to compile the Axiom
| > | Algebra that's the best case scenario.
| > 
| > I think Aldor.org would not mind a second implementation -- at least, when
| > the question was raised, the answer was "go for it!".
| 
| I am not going to re-implement Aldor.

As ever, I prefer facts to speculations; thanks for setting the record
straight. 

\start
Date: 01 Aug 2007 14:07:07 -0500
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

Cliff Yapp writes:

[...]

| So you don't agree with Tim's analysis here? 
| http://lists.nongnu.org/archive/html/axiom-developer/2007-07/msg00147.html
| 
| I suppose there's no reason not to ask NAG, but clearly they aren't
| selling Axiom any longer and their commercial trademark HAS lapsed:

Legal issues are tricky.  I wouldn't claim anyone, other NAG (who
still owns Axiom copyright), owns Axiom.  At least original Axiom
designers/developers present at the Axiom meeting did not seem to
indicate that a particular individual owns Axiom at this moment.  In
any case, I would refrain from making such ownership claim
until/unless formally established, and NAG steps forward and makes a
public statement to the effect.

\start
Date: 01 Aug 2007 15:07:29 -0400
From: Stephen Wilson
To: Didier Deshommes
Subject: Re: Axiom meeting at ISSAC

Didier,

The idea of improving the current Axiom compiler is itself not new
(Aldor is an example), but this particular effort is only a few months
old.  Consequently, it is not well developed at this point.  In
concrete terms, we have a new parser which can handle a good subset
(say 90%) of the current SPAD language. Current activity is centered
around developing new resources which need to exist before further
work continues -- literate programming tools, a build environment
which integrates seamlessly with all components, and a port of Axiom
as a whole to run on an ANSI common lisp (gcl-2.7.0).  This
`foundational' setup is almost complete.

This effort does not have the same goals as Aldor, nor does it aim to
be compatible with Aldor.  However, a lot of the lessons and insights
which users of Aldor can bring to this implementation will certainly
guide the effort.  Many people want dependent types, for example.  We
will support them, but it will likely be in a non-compatible way.  

For example, a type which depends on a runtime expression like "1 + n"
might not be allowed, since deciding equality over syntax trees does
not fit well in an imperative language.  On the other hand, such types
could rely on runtime support to enforce correctness.  This is an
example of how the semantics of the new SPAD are not tied to Aldor's
rules, and how we are still in the initial stages of designing the
system.

Another example is Aldors generators.  It is planned that these will
be supported in the new SPAD as a special case of continuations.
Thus, generators in SPAD will become an algebra item, not a builtin.


There is also the question of being able to provide the compiler
components in the form of a library which can be used by other aspects
Axiom.  For example, one would be able to use the new parser and
(forthcoming) type checker to support an IDE.  One of the main goals
aside from providing a better compiler is to provide a set of tools
which can be used to enrich the Axiom system as a whole.  The main
point here is one of design.  The new system will be flexible and
easily `plugged into' at all levels.


There is a wiki page which attempts to give some basic links for those
who wish to develop the system:

     http://wiki.axiom-developer.org/AxispBranch

The current work is only suitable for developers but there will
certainly be `public' releases made incrementally to keep `on-track'
for an eventual merge with the canonical Axiom sources.

\start
Date: 01 Aug 2007 14:34:07 -0500
From: Gabriel Dos Reis
To: Didier Deshommes
Subject: Re: Axiom meeting at ISSAC

Stephen Wilson writes:

[...]

| There is also the question of being able to provide the compiler
| components in the form of a library which can be used by other aspects
| Axiom.  For example, one would be able to use the new parser and
| (forthcoming) type checker to support an IDE.

People may note that, in Axiom as of today, one can already get the
syntax tree from both the old and the new parsers, and in fact use the
parser as a library -- as has been done the algorithmic
differentiation project.  You don't need to wait for a
functional new compiler to do that.

\start
Date: Wed, 1 Aug 2007 12:46:43 -0700 (PDT)
From: Cliff Yapp
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

--- Gabriel Dos Reis wrote:

> On Wed, 1 Aug 2007, C Y wrote:
> 
> | Whatever the intent may be, the legal text of the license itself is
> | what will ultimately govern what can and cannot be done, within the
> | limits of the law.  That is why I focus on the text of the license
> | itself - intent lasts only as long as the individuals doing the
> | intending.
> 
> I would encourage anyone to whom this issue really matters to attend
> the Aldor workshop and voice their concerns in face-to-face meetings.

Gaby, as you pointed out with some force earlier we have seen posted to
the list already not just speculation but very clear and explicit
information that Aldor.org wants to have a hand in any commercial
development of the Aldor code.  It has already been noted that this
makes it GPL incompatible, and anything GPL compatible is not going to
be able to serve the goals as stated.  Modified BSD is even less
compatible with that goal.

> I know some people already booked; I would encourage others to
> consider attending.

Based on what you heard at the Axiom meeting, do you think there is a
realistic chance they would consider a change that is at least GPL
compatible?  It sounds as if they have already considered that course
of action decided specifically to be GPL incompatible.  Modified BSD
will not serve their goal of non-commercial only, and is also GPL
compatible.

To me the issue at hand looks to be this:

Given the licensing terms and stated intent of Aldor.org in the release
of the Aldor source code, will the Axiom project pursue the use of
Aldor as part of Axiom?

There is also the question that if a concensus resolution to this and
other questions cannot be had, and multiple projects result, how is the
dispostion of the Axiom name to be decided?  

I don't see quite how we are going to make those decisions.

\start
Date: 01 Aug 2007 15:57:14 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gabriel Dos Reis writes:

> Stephen Wilson writes:
> 
> [...]
> 
> | There is also the question of being able to provide the compiler
> | components in the form of a library which can be used by other aspects
> | Axiom.  For example, one would be able to use the new parser and
> | (forthcoming) type checker to support an IDE.
> 
> People may note that, in Axiom as of today, one can already get the
> syntax tree from both the old and the new parsers, and in fact use the
> parser as a library -- as has been done the algorithmic
> differentiation project.  You don't need to wait for a
> functional new compiler to do that.

Can it incrementally parse input as the user is typing, thus making it
a usable component in an IDE?  Is the AST itself specified?  Does it
the representation past the lexical analysis phase contain line and
column number information?  Is the current implementation easily
modifiable and extensible?

\start
Date: Wed, 1 Aug 2007 15:05:11 -0500 (CDT)
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, C Y wrote:

| --- Gabriel Dos Reis wrote:
| 
| > On Wed, 1 Aug 2007, C Y wrote:
| > 
| > | Whatever the intent may be, the legal text of the license itself is
| > | what will ultimately govern what can and cannot be done, within the
| > | limits of the law.  That is why I focus on the text of the license
| > | itself - intent lasts only as long as the individuals doing the
| > | intending.
| > 
| > I would encourage anyone to whom this issue really matters to attend
| > the Aldor workshop and voice their concerns in face-to-face meetings.
| 
| Gaby, as you pointed out with some force earlier we have seen posted to
| the list already not just speculation but very clear and explicit
| information that Aldor.org wants to have a hand in any commercial
| development of the Aldor code.  It has already been noted that this
| makes it GPL incompatible, and anything GPL compatible is not going to
| be able to serve the goals as stated.  Modified BSD is even less
| compatible with that goal.

All I'm saying is: if this license issue really matters to you AND you think
you can change people's mind or you have persuasive arguments to influence
the decisions, then you should consider attending the Aldor workshop where
you can meet for real people directly involved in the event.  

No amount of emails or speculations to this list will have any impact.

| > I know some people already booked; I would encourage others to
| > consider attending.
| 
| Based on what you heard at the Axiom meeting, do you think there is a
| realistic chance they would consider a change that is at least GPL
| compatible?

I believe this is an example of question best answered by people
involved in getting Aldor source code to the public; and a question,
I believe, best dealt with in face to face meeting.

| It sounds as if they have already considered that course
| of action decided specifically to be GPL incompatible.  Modified BSD
| will not serve their goal of non-commercial only, and is also GPL
| compatible.

I'm under the impression that APL2 is a modified BSD license with
non-commercial use clause added.  At least three people on different sides on
the issue concurred on that view.

\start
Date: 01 Aug 2007 16:05:11 -0400
From: Stephen Wilson
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC
Cc: Gabriel Dos Reis

Stephen Wilson writes:

> Gabriel Dos Reis writes:
> 
> > Stephen Wilson writes:
> > 
> > [...]
> > 
> > | There is also the question of being able to provide the compiler
> > | components in the form of a library which can be used by other aspects
> > | Axiom.  For example, one would be able to use the new parser and
> > | (forthcoming) type checker to support an IDE.
> > 
> > People may note that, in Axiom as of today, one can already get the
> > syntax tree from both the old and the new parsers, and in fact use the
> > parser as a library -- as has been done the algorithmic
> > differentiation project.  You don't need to wait for a
> > functional new compiler to do that.
> 
> Can it incrementally parse input as the user is typing, thus making it
> a usable component in an IDE?  Is the AST itself specified?  Does it
> the representation past the lexical analysis phase contain line and
> column number information?  Is the current implementation easily
> modifiable and extensible?


Moreover, you do not need to wait for a functional new compiler. The
parser, as I said, is around 90% complete.

\start
Date: Wed, 1 Aug 2007 15:07:46 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| 
| > Stephen Wilson writes:
| > 
| > [...]
| > 
| > | There is also the question of being able to provide the compiler
| > | components in the form of a library which can be used by other aspects
| > | Axiom.  For example, one would be able to use the new parser and
| > | (forthcoming) type checker to support an IDE.
| > 
| > People may note that, in Axiom as of today, one can already get the
| > syntax tree from both the old and the new parsers, and in fact use the
| > parser as a library -- as has been done the algorithmic
| > differentiation project.  You don't need to wait for a
| > functional new compiler to do that.
| 
| Can it incrementally parse input as the user is typing, thus making it
| a usable component in an IDE?  Is the AST itself specified?  Does it
| the representation past the lexical analysis phase contain line and
| column number information?  Is the current implementation easily
| modifiable and extensible?

You can answer all those questions by looking at the source code.

The Axiom interpreter uses the new compiler/parser.

The Axiom compiler uses the old compiler/parser.

The new compiler/parser can also compiler library codes -- through
the connection is not present in Silver, but requires only few lines
of code.

\start
Date: Wed, 1 Aug 2007 13:22:36 -0700 (PDT)
From: Cliff Yapp
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

--- Gabriel Dos Reis wrote:
>
> No amount of emails or speculations to this list will have any
> impact.

Not on Aldor, no.  My PRIMARY concern is what impact Aldor will have on
the Axiom project, and that CAN be delt with on this list - it must be.

>From my standpoint, the Aldor issue is now closed - they have chosen an
incompatible license (which is their right, no problem) and we can now
proceed to improve/redo the existing one without fear that the work is
unnecessary.  Resolution either way is better than being left hanging.

Apparently, that opinion is not shared by other members of the list. 
If I am alone in that opinion, it doesn't matter much.  If I am not, it
could be a real problem for Axiom.
 
> I'm under the impression that APL2 is a modified BSD license with
> non-commercial use clause added.  At least three people on different
> sides on the issue concurred on that view.

That's fine, but it is still incompatible and the intent is that it be
incompatible (at least with the GPL).  The issue at hand remains - what
course does the Axiom Project take?

\start
Date: Wed, 1 Aug 2007 15:28:59 -0500 (CDT)
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, C Y wrote:

| From my standpoint, the Aldor issue is now closed - they have chosen an
| incompatible license (which is their right, no problem) and we can now
| proceed to improve/redo the existing one without fear that the work is
| unnecessary.  Resolution either way is better than being left hanging.

I have not seen anyone advocating to leave issues hanging.  

Active people from both community will be attending the Aldor
workshop. That is an excellent  opportunity to further the handling 
of pressing issues, directions, etc.  I would have thought interested people
would be very willing to take on the opportunity to meet face to face and 
discuss what they believe in.  

\start
Date: 01 Aug 2007 16:28:36 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gabriel Dos Reis writes:
> You can answer all those questions by looking at the source code.

I have looked at the source code.  There is a difference in terms of
functionality and applicability which the new parser is designed to
accommodate and which the old parsers are not.  

\start
Date: Wed, 1 Aug 2007 15:32:01 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > You can answer all those questions by looking at the source code.
| 
| I have looked at the source code.

Excellent.  For some reasons, I was under the impression that you looked
at the code before starting your new compiler.

\start
Date: 01 Aug 2007 16:36:19 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gabriel Dos Reis writes:
> Excellent.  For some reasons, I was under the impression that you looked
> at the code before starting your new compiler.

Speculation?

\start
Date: Wed, 1 Aug 2007 15:42:30 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > Excellent.  For some reasons, I was under the impression that you looked
| > at the code before starting your new compiler.
| 
| Speculation?

I did not speculate.  That is why I said if you read the code, you can 
answer your questions.  If turned out than you didn't.

\start
Date: 01 Aug 2007 16:54:06 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gabriel Dos Reis writes:

> On Wed, 1 Aug 2007, Stephen Wilson wrote:
> 
> | Gabriel Dos Reis writes:
> | > Excellent.  For some reasons, I was under the impression that you looked
> | > at the code before starting your new compiler.
> | 
> | Speculation?
> 
> I did not speculate.  That is why I said if you read the code, you can 
> answer your questions.  If turned out than you didn't.

OK!  You caught me!  I actually haven't read any of the source code.

Imagine my surprise when loading the new parser into axiom and it just
happened to work, and the compiler could understand the ASTs it
generated.  Must be the new implant the aliens installed in my
cerebrum or something.  Sorry for trying to dupe you into believing I
might have actually read the code.  Many apologies.

But for the record, the answers to my original questions are no, no,
no, and no.  Dont ask me how I know this.

\start
Date: Wed, 1 Aug 2007 15:58:22 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| OK!  You caught me!

I did not mean too.  Oh well, ainsi va la vie.

[...]

| But for the record, the answers to my original questions are no, no,
| no, and no.

(1) Which, of course, are untrue.
(2) And, as expected, your questions were rhetorical.


\start
Date: Wed, 1 Aug 2007 14:00:32 -0700 (PDT)
From: Cliff Yapp
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

--- Gabriel Dos Reis wrote:
> 
> I have not seen anyone advocating to leave issues hanging.  

So long as we leave the question of using or not using Aldor in Axiom
undecided as a project, it is hanging.  
 
> Active people from both community will be attending the Aldor
> workshop. That is an excellent opportunity to further the handling 
> of pressing issues, directions, etc.  I would have thought interested
> people would be very willing to take on the opportunity to meet face
> to face and discuss what they believe in.  

Unfortunately personal and financial constraints make a long trip of
that sort impractical for me.

What about an IRC meeting?  That at least is real time, even if it
can't be face to face.

\start
Date: Wed, 1 Aug 2007 16:04:28 -0500 (CDT)
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, C Y wrote:

| > Active people from both community will be attending the Aldor
| > workshop. That is an excellent opportunity to further the handling 
| > of pressing issues, directions, etc.  I would have thought interested
| > people would be very willing to take on the opportunity to meet face
| > to face and discuss what they believe in.  
| 
| Unfortunately personal and financial constraints make a long trip of
| that sort impractical for me.

\start
Date: 01 Aug 2007 17:13:19 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gabriel Dos Reis writes:
> (1) Which, of course, are untrue.

The SPAD parser/lexer is line oriented, which means it does not
incrementally parse user input by design.

The SPAD parser drops column information after the lexical stage (see
PARSE-NewExpr).  

The AST is not documented.  Moreover, it is ambiguous.

The system is not extensible or flexible by any rational
measurement.  


> (2) And, as expected, your questions were rhetorical.

Of course they were.  I was trying to explain the work I am doing and
you effectively dismissed it by saying "you dont need to wait for a
new compiler", which is not true.  Moreover, I feel my work has
advantages which are visible not only to developers but users as well.

I will be more than happy to discount your autoconf patch when it is
ready based on the fact that we already have a build system which more
or less works,  if your interested in that kind of collaboration.

\start
Date: Wed, 1 Aug 2007 16:30:48 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > (1) Which, of course, are untrue.

You asked the following questions:

    (i) Can it incrementally parse input as the user is typing, thus 
       making it a usable component in an IDE?  

   (ii) Is the AST itself specified?  

  (iii) Does it the representation past the lexical analysis phase contain
       line and column number information? 

   (iv) Is the current implementation easily modifiable and extensible?


(i) is open to debate and interpretation.
(ii) does not need a new parser or compiler to be solved.  I claim
    that the AST is self-descriptive for the most part -- that does
    excuse the non-existence of public documentation though.
    For a data-point, Jacob did not need much to get his way through 
    the AST system.

(iii) of course, the answer is yes.  As I mentioned earlier, there are two
    parser in Axiom, an old and a new.  You're looking at the old compiler.

[...]

| The system is not extensible or flexible by any rational
| measurement.  

I suspect it is more accurate to say:

  The system is not extensible or flexible by any Stephen Wilson's
  measurement.

Care should be exercised before generalizing to "rational".

| > (2) And, as expected, your questions were rhetorical.
| 
| Of course they were.  I was trying to explain the work I am doing and
| you effectively dismissed it by saying "you dont need to wait for a
| new compiler", which is not true.

"dismiss" is the way you chose to see a *factual statement* that
the current compiler can be used as a library roday, and that has been
done for real.

I would not venture to say that if I speculated you would have interpreted 
it as "celebrated".  Anyway, I'm quite amazed.

[...]

| I will be more than happy to discount your autoconf patch when it is
| ready based on the fact that we already have a build system which more
| or less works,  if your interested in that kind of collaboration.

You must have a serious problem.

\start
Date: 01 Aug 2007 17:50:17 -0400
From: Camm Maguire
To: Stephen Wilson
Subject: Re: gclcvs-2.7.0 and Axiom

Greetings!  Will try to take a look this evening -- thanks so much for
the report!

\start
Date: 01 Aug 2007 18:03:08 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gabriel Dos Reis writes:

> (iii) of course, the answer is yes.  As I mentioned earlier, there are two
>     parser in Axiom, an old and a new.  You're looking at the old compiler.

Of course I am looking at the old compiler, it is the only compiler.
It accepts one AST, not two.  That AST does not contain line/column
information.  The AST which Axiom uses does not contain line/column
information.  That information is intentionally erased at one point of
parsing or another, old or new, it does not matter.

> | The system is not extensible or flexible by any rational
> | measurement.  
> 
> I suspect it is more accurate to say:
> 
>   The system is not extensible or flexible by any Stephen Wilson's
>   measurement.
> 
> Care should be exercised before generalizing to "rational".

Yep, absolutely.  That is my opinion.  Rational thinking was used to
formulate it.


As for the rest of your post, I am not even going to bother trying to
explain.  If you dont understand the issues, thats your problem.


> 
> | > (2) And, as expected, your questions were rhetorical.
> | 
> | Of course they were.  I was trying to explain the work I am doing and
> | you effectively dismissed it by saying "you dont need to wait for a
> | new compiler", which is not true.
> 
> "dismiss" is the way you chose to see a *factual statement* that
> the current compiler can be used as a library roday, and that has been
> done for real.
> 
> I would not venture to say that if I speculated you would have interpreted 
> it as "celebrated".  Anyway, I'm quite amazed.
> 
> [...]
> 
> | I will be more than happy to discount your autoconf patch when it is
> | ready based on the fact that we already have a build system which more
> | or less works,  if your interested in that kind of collaboration.
> 
> You must have a serious problem.

\start
Date: 01 Aug 2007 18:54:45 -0400
From: Stephen Wilson
To: Camm Maguire
Subject: Re: gclcvs-2.7.0 and Axiom

--=-=-=

Camm Maguire writes:

> Greetings!  Will try to take a look this evening -- thanks so much for
> the report!

If you will be working with the modified version of Silver to
investigate, then the following patch should be applied on top of the
previous patches I have provided. 

This patch appears to solve the problem w.r.t elt over dotted lists by
modifying the boot compiler to emit calls to a safe function.  The
cached lisp has been updated to recognize this change.

It temporarily disables Axioms hook into universal-error-handler to
permit easier debugging.

It removes the calls to compiler::fixed-args.

I hope this is sufficient for you to reproduce the error I am seeing.
Please let me know if you run into any difficulties.

Thanks for looking into this!

Steve



--=-=-=

diff --git a/Makefile b/Makefile
diff --git a/src/interp/Makefile.pamphlet b/src/interp/Makefile.pamphlet
diff --git a/src/interp/def.lisp.pamphlet b/src/interp/def.lisp.pamphlet
index 247268c..410313c 100644
--- a/src/interp/def.lisp.pamphlet
+++ b/src/interp/def.lisp.pamphlet
@@ -583,7 +583,7 @@ foo defined inside of fum gets renamed as fum,foo.")
       (COND ((and (symbolp sel) (setq Y (GET SEL 'SEL\,FUNCTION)))
              (COND ((INTEGERP Y) (LIST 'ELT EXPR Y))
                    ((LIST Y EXPR))))
-            ((LIST 'ELT EXPR SEL))))))
+            ((LIST 'SAFE-ELT EXPR SEL))))))
 
 (defun DEF-SETELT (args)
   (let ((VAR (first args)) (SEL (second args)) (EXPR (third args)))
diff --git a/src/interp/g-boot.boot.pamphlet b/src/interp/g-boot.boot.pamphlet
index 5a9c83a..45e5c6d 100644
--- a/src/interp/g-boot.boot.pamphlet
+++ b/src/interp/g-boot.boot.pamphlet
@@ -864,7 +864,7 @@ bootTransform e ==
 
 ;;;     ***       |addCARorCDR| REDEFINED
 
-(DEFUN |addCARorCDR| (|acc| |expr|) (PROG (|funs| |p| |funsA| |funsR|) (RETURN (COND ((NULL (PAIRP |expr|)) (CONS |acc| (CONS |expr| NIL))) ((AND (BOOT-EQUAL |acc| (QUOTE CAR)) (EQCAR |expr| (QUOTE REVERSE))) (CONS (QUOTE |last|) (QCDR |expr|))) ((QUOTE T) (SPADLET |funs| (QUOTE (CAR CDR CAAR CDAR CADR CDDR CAAAR CADAR CAADR CADDR CDAAR CDDAR CDADR CDDDR))) (SPADLET |p| (|position| (QCAR |expr|) |funs|)) (COND ((BOOT-EQUAL |p| (SPADDIFFERENCE 1)) (CONS |acc| (CONS |expr| NIL))) ((QUOTE T) (SPADLET |funsA| (QUOTE (CAAR CADR CAAAR CADAR CAADR CADDR CAAAAR CAADAR CAAADR CAADDR CADAAR CADDAR CADADR CADDDR))) (SPADLET |funsR| (QUOTE (CDAR CDDR CDAAR CDDAR CDADR CDDDR CDAAAR CDADAR CDAADR CDADDR CDDAAR CDDDAR CDDADR CDDDDR))) (COND ((BOOT-EQUAL |acc| (QUOTE CAR)) (CONS (ELT |funsA| |p|) (QCDR |expr|))) ((QUOTE T) (CONS (ELT |funsR| |p|) (QCDR |expr|))))))))))) 
+(DEFUN |addCARorCDR| (|acc| |expr|) (PROG (|funs| |p| |funsA| |funsR|) (RETURN (COND ((NULL (PAIRP |expr|)) (CONS |acc| (CONS |expr| NIL))) ((AND (BOOT-EQUAL |acc| (QUOTE CAR)) (EQCAR |expr| (QUOTE REVERSE))) (CONS (QUOTE |last|) (QCDR |expr|))) ((QUOTE T) (SPADLET |funs| (QUOTE (CAR CDR CAAR CDAR CADR CDDR CAAAR CADAR CAADR CADDR CDAAR CDDAR CDADR CDDDR))) (SPADLET |p| (|position| (QCAR |expr|) |funs|)) (COND ((BOOT-EQUAL |p| (SPADDIFFERENCE 1)) (CONS |acc| (CONS |expr| NIL))) ((QUOTE T) (SPADLET |funsA| (QUOTE (CAAR CADR CAAAR CADAR CAADR CADDR CAAAAR CAADAR CAAADR CAADDR CADAAR CADDAR CADADR CADDDR))) (SPADLET |funsR| (QUOTE (CDAR CDDR CDAAR CDDAR CDADR CDDDR CDAAAR CDADAR CDAADR CDADDR CDDAAR CDDDAR CDDADR CDDDDR))) (COND ((BOOT-EQUAL |acc| (QUOTE CAR)) (CONS (SAFE-ELT |funsA| |p|) (QCDR |expr|))) ((QUOTE T) (CONS (SAFE-ELT |funsR| |p|) (QCDR |expr|))))))))))) 
 ;
 ;
 ;--% IS
diff --git a/src/interp/g-util.boot.pamphlet b/src/interp/g-util.boot.pamphlet
index 878e547..c5ee28b 100644
--- a/src/interp/g-util.boot.pamphlet
+++ b/src/interp/g-util.boot.pamphlet
@@ -787,7 +787,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=#:G2567 (SAFE-ELT |f| 0)) (|i| 1 (QSADD1 |i|))) ((QSGREATERP |i| #0#) NIL) (SEQ (EXIT (SPADLET |fill1| (STRCONC |fillchar| |fill1|))))) (SPADLET |fill2| |fill1|) (COND ((NEQUAL (SAFE-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
@@ -1160,7 +1160,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = char '_&
 
 ;;;     ***       |str2Tex| REDEFINED
 
-(DEFUN |str2Tex| (|s|) (PROG (|outf| |val|) (RETURN (PROGN (SPADLET |outf| (|str2Outform| |s|)) (SPADLET |val| (|coerceInt| (|mkObj| (|wrap| |outf|) (QUOTE (|OutputForm|))) (QUOTE (|TexFormat|)))) (SPADLET |val| (|objValUnwrap| |val|)) (CAR (ELT |val| 1)))))) 
+(DEFUN |str2Tex| (|s|) (PROG (|outf| |val|) (RETURN (PROGN (SPADLET |outf| (|str2Outform| |s|)) (SPADLET |val| (|coerceInt| (|mkObj| (|wrap| |outf|) (QUOTE (|OutputForm|))) (QUOTE (|TexFormat|)))) (SPADLET |val| (|objValUnwrap| |val|)) (CAR (SAFE-ELT |val| 1)))))) 
 ;opOf x ==
 ;  atom x => x
 ;  first x
@@ -1293,7 +1293,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = char '_&
 
 ;;;     ***       |leftTrim| REDEFINED
 
-(DEFUN |leftTrim| (|s|) (PROG (|k| |j|) (RETURN (SEQ (PROGN (SPADLET |k| (MAXINDEX |s|)) (COND ((MINUSP |k|) |s|) ((BOOT-EQUAL (ELT |s| 0) |$blank|) (DO ((|i| 0 (QSADD1 |i|))) ((OR (QSGREATERP |i| |k|) (NULL (BOOT-EQUAL (ELT |s| |i|) |$blank|))) NIL) (SEQ (EXIT (SPADLET |j| |i|)))) (SUBSTRING |s| (PLUS |j| 1) NIL)) ((QUOTE T) |s|))))))) 
+(DEFUN |leftTrim| (|s|) (PROG (|k| |j|) (RETURN (SEQ (PROGN (SPADLET |k| (MAXINDEX |s|)) (COND ((MINUSP |k|) |s|) ((BOOT-EQUAL (SAFE-ELT |s| 0) |$blank|) (DO ((|i| 0 (QSADD1 |i|))) ((OR (QSGREATERP |i| |k|) (NULL (BOOT-EQUAL (SAFE-ELT |s| |i|) |$blank|))) NIL) (SEQ (EXIT (SPADLET |j| |i|)))) (SUBSTRING |s| (PLUS |j| 1) NIL)) ((QUOTE T) |s|))))))) 
 ;rightTrim s ==  -- assumed a non-empty string
 ;  k := MAXINDEX s
 ;  k < 0 => s
@@ -1304,7 +1304,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 (SAFE-ELT |s| |k|) |$blank|) (DO ((#0=#:G3107 (SPADDIFFERENCE 1)) (|i| |k| (+ |i| #0#))) ((OR (IF (MINUSP #0#) (< |i| 0) (> |i| 0)) (NULL (BOOT-EQUAL (SAFE-ELT |s| |i|) |$blank|))) NIL) (SEQ (EXIT (SPADLET |j| |i|)))) (SUBSTRING |s| 0 |j|)) ((QUOTE T) |s|))))))) 
 ;pp x ==
 ;  PRETTYPRINT x
 ;  x
@@ -1345,13 +1345,13 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = char '_&
 
 ;;;     ***       |intern| REDEFINED
 
-(DEFUN |intern| (|x|) (COND ((STRINGP |x|) (COND ((DIGITP (ELT |x| 0)) (|string2Integer| |x|)) ((QUOTE T) (INTERN |x|)))) ((QUOTE T) |x|))) 
+(DEFUN |intern| (|x|) (COND ((STRINGP |x|) (COND ((DIGITP (SAFE-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
 
 ;;;     ***       |isDomain| REDEFINED
 
-(DEFUN |isDomain| (|a|) (AND (REFVECP |a|) (> (|#| |a|) 5) (BOOT-EQUAL (GETDATABASE (ELT |a| 0) (QUOTE CONSTRUCTORKIND)) (QUOTE |domain|)))) 
+(DEFUN |isDomain| (|a|) (AND (REFVECP |a|) (> (|#| |a|) 5) (BOOT-EQUAL (GETDATABASE (SAFE-ELT |a| 0) (QUOTE CONSTRUCTORKIND)) (QUOTE |domain|)))) 
 ;-- variables used by browser
 ;$htHash      := MAKE_-HASH_-TABLE()
 
@@ -1497,7 +1497,7 @@ isDefaultPackageName x == (s := PNAME x).(MAXINDEX s) = char '_&
 
 ;;;     ***       |isDefaultPackageName| REDEFINED
 
-(DEFUN |isDefaultPackageName| (|x|) (PROG (|s|) (RETURN (BOOT-EQUAL (ELT (SPADLET |s| (PNAME |x|)) (MAXINDEX |s|)) (|char| (QUOTE &)))))) 
+(DEFUN |isDefaultPackageName| (|x|) (PROG (|s|) (RETURN (BOOT-EQUAL (SAFE-ELT (SPADLET |s| (PNAME |x|)) (MAXINDEX |s|)) (|char| (QUOTE &)))))) 
 ;;;Boot translation finished for g-util.boot
 
 @
diff --git a/src/interp/i-output.boot.pamphlet b/src/interp/i-output.boot.pamphlet
diff --git a/src/interp/macros.lisp.pamphlet b/src/interp/macros.lisp.pamphlet
index 44a6d3e..20ace6e 100644
--- a/src/interp/macros.lisp.pamphlet
+++ b/src/interp/macros.lisp.pamphlet
@@ -265,13 +265,14 @@ ends up being [[CONTAINED |$EmptyMode| Y]].
      `(OR (IS ,B ,A) (LET_ERROR ,(MK_LEFORM A) ,(MKQ B) ))))
  
 (defmacro RPLAC (&rest L)
-  (if (EQCAR (CAR L) 'ELT)
+  (if (or (EQCAR (CAR L) 'ELT)
+          (EQCAR (CAR L) 'SAFE-ELT))
       (LIST 'SETELT (CADAR L) (CADDR (CAR L)) (CADR L))
       (let ((A (CARCDREXPAND (CAR L) NIL)) (B (CADR L)))
-        (COND ((CDDR L) (ERROR 'RPLAC))
+        (COND ((CDDR L) (ERROR "RPLAC"))
               ((EQCAR A 'CAR) (LIST 'RPLACA (CADR A) B))
               ((EQCAR A 'CDR) (LIST 'RPLACD (CADR A) B))
-              ((ERROR 'RPLAC))))))
+              ((ERROR "RPLAC"))))))
  
 (MAPC #'(LAMBDA (J) (MAKEPROP (CAR J) 'SELCODE (CADR J)))
       '((CAR 2) (CDR 3) (CAAR 4) (CADR 5) (CDAR 6) (CDDR 7)
diff --git a/src/interp/nlib.lisp.pamphlet b/src/interp/nlib.lisp.pamphlet
index 9be8dfe..bfa29b1 100644
--- a/src/interp/nlib.lisp.pamphlet
+++ b/src/interp/nlib.lisp.pamphlet
@@ -371,27 +371,6 @@ but has been changed to read:
                                                (directory-namestring lfile))))))))
 
 
-#+:AKCL
-(defun spad-fixed-arg (fname )
-   (and (equal (symbol-package fname) (find-package "BOOT"))
-        (not (get fname 'compiler::spad-var-arg))
-	(search ";" (symbol-name fname))
-        (or (get fname 'compiler::fixed-args)
-	    (setf (get fname 'compiler::fixed-args) t)))
-   nil)
-
-#+:AKCL
-(defun compile-lib-file (fn &rest opts)
-  (unwind-protect
-      (progn
-	(trace (compiler::fast-link-proclaimed-type-p
-		:exitcond nil
-		:entrycond (spad-fixed-arg (car system::arglist))))
-	(trace (compiler::t1defun :exitcond nil
-		:entrycond (spad-fixed-arg (caar system::arglist))))
-	(apply #'compile-file fn opts))
-    (untrace compiler::fast-link-proclaimed-type-p compiler::t1defun)))
-#+:CCL
 (define-function 'compile-lib-file #'compile-file)
 
 ;; (RDROPITEMS filearg keys) don't delete, used in files.spad
diff --git a/src/interp/parse.boot.pamphlet b/src/interp/parse.boot.pamphlet
index 5d9a4be..b3a11e7 100644
--- a/src/interp/parse.boot.pamphlet
+++ b/src/interp/parse.boot.pamphlet
@@ -693,7 +693,7 @@ parseVCONS l == ["VECTOR",:parseTranList l]
 
 ;;;     ***       |parseLET| REDEFINED
 
-(DEFUN |parseLET| (#0=#:G2389) (PROG (|x| |y| |p|) (RETURN (PROGN (SPADLET |x| (CAR #0#)) (SPADLET |y| (CADR #0#)) (SPADLET |p| (CONS (QUOTE LET) (CONS (|parseTran| |x|) (CONS (|parseTranCheckForRecord| |y| (|opOf| |x|)) NIL)))) (COND ((BOOT-EQUAL (|opOf| |x|) (QUOTE |cons|)) (CONS (QUOTE LET) (CONS (|transIs| (ELT |p| 1)) (CONS (ELT |p| 2) NIL)))) ((QUOTE T) |p|)))))) 
+(DEFUN |parseLET| (#0=#:G2389) (PROG (|x| |y| |p|) (RETURN (PROGN (SPADLET |x| (CAR #0#)) (SPADLET |y| (CADR #0#)) (SPADLET |p| (CONS (QUOTE LET) (CONS (|parseTran| |x|) (CONS (|parseTranCheckForRecord| |y| (|opOf| |x|)) NIL)))) (COND ((BOOT-EQUAL (|opOf| |x|) (QUOTE |cons|)) (CONS (QUOTE LET) (CONS (|transIs| (SAFE-ELT |p| 1)) (CONS (SAFE-ELT |p| 2) NIL)))) ((QUOTE T) |p|)))))) 
 ;
 ;parseLETD [x,y] == ['LETD,parseTran x,parseTran parseType y]
 
@@ -862,7 +862,7 @@ parseVCONS l == ["VECTOR",:parseTranList l]
 
 ;;;     ***       |specialModeTran| REDEFINED
 
-(DEFUN |specialModeTran| (|form|) (PROG (|op| |argl| |sop| |s0| |argKey| |numArgs| |zeroOrOne| |isDmp| |LETTMP#1| |vl| |extraDomain| |s3| |isUpOrMp| |domainPart| |argPart| |n| |polyForm|) (RETURN (SEQ (COND ((AND (PAIRP |form|) (PROGN (SPADLET |op| (QCAR |form|)) (SPADLET |argl| (QCDR |form|)) (QUOTE T))) (COND ((NULL (ATOM |op|)) |form|) ((BOOT-EQUAL (SPADLET |s0| (ELT (SPADLET |sop| (PNAME |op|)) 0)) (QUOTE *)) (SPADLET |n| (|#| |sop|)) (COND ((EQL |n| 1) |form|) ((QUOTE T) (SPADLET |argKey| (ELT |sop| 1)) (SPADLET |numArgs| (SPADDIFFERENCE (|#| |argl|) (COND ((BOOT-EQUAL |argKey| (QUOTE |1|)) 1) ((QUOTE T) 0)))) (SPADLET |zeroOrOne| (OR (BOOT-EQUAL |argKey| (QUOTE |0|)) (BOOT-EQUAL |argKey| (QUOTE |1|)))) (SPADLET |isDmp| (COND ((> 10 |numArgs|) (AND (EQL |n| 6) (BOOT-EQUAL (MAKESTRING "DMP") (SUBSTRING |sop| 3 3)) |zeroOrOne|)) ((QUOTE T) (AND (EQL |n| 7) (BOOT-EQUAL (MAKESTRING "DMP") (SUBSTRING |sop| 4 3)) |zeroOrOne|)))) (COND (|isDmp| (COND ((BOOT-EQUAL |argKey| (QU!
 OTE |0|)) (SPADLET |extraDomain| |$EmptyMode|) (SPADLET |vl| |argl|)) ((QUOTE T) (SPADLET |LETTMP#1| (REVERSE |argl|)) (SPADLET |extraDomain| (CAR |LETTMP#1|)) (SPADLET |vl| (NREVERSE (CDR |LETTMP#1|))) |argl|)) (CONS (QUOTE |DistributedMultivariatePolynomial|) (CONS (CONS (QUOTE |construct|) |vl|) (CONS (|specialModeTran| |extraDomain|) NIL)))) ((AND (EQL |n| 4) (BOOT-EQUAL (SPADLET |s3| (ELT |sop| 3)) (QUOTE M)) |zeroOrOne|) (|specialModeTran| (PROGN (SPADLET |extraDomain| (COND ((BOOT-EQUAL |argKey| (QUOTE |0|)) (CONS |$EmptyMode| NIL)) ((QUOTE T) NIL))) (COND ((EQL (SPADLET |n| (PARSE-INTEGER (PNAME (ELT |sop| 2)))) 1) (CONS (QUOTE |SquareMatrix|) (APPEND |argl| |extraDomain|))) ((EQL |n| 2) (CONS (QUOTE |RectangularMatrix|) (APPEND |argl| |extraDomain|))) ((QUOTE T) |form|))))) ((QUOTE T) (SPADLET |isUpOrMp| (COND ((> 10 |numArgs|) (OR (AND (EQL |n| 4) (BOOT-EQUAL (SPADLET |s3| (ELT |sop| 3)) (QUOTE P)) |zeroOrOne|) (AND (EQL |n| 5) (BOOT-EQUAL (SPADLET |s3| (ELT |sop|!
  3)) (QUOTE R)) (BOOT-EQUAL (ELT |sop| 4) (QUOTE F)) |zeroOrOne|))) ((
QUOTE T) (OR (AND (EQL |n| 5) (BOOT-EQUAL (SPADLET |s3| (ELT |sop| 4)) (QUOTE P)) |zeroOrOne|) (AND (EQL |n| 6) (BOOT-EQUAL (SPADLET |s3| (ELT |sop| 4)) (QUOTE R)) (BOOT-EQUAL (ELT |sop| 5) (QUOTE F)) |zeroOrOne|))))) (COND (|isUpOrMp| (SPADLET |polyForm| (PROGN (SPADLET |domainPart| (COND ((BOOT-EQUAL |argKey| (QUOTE |0|)) |$EmptyMode|) ((QUOTE T) (|last| |argl|)))) (SPADLET |argPart| (COND ((BOOT-EQUAL |argKey| (QUOTE |0|)) |argl|) ((QUOTE T) (DROP (SPADDIFFERENCE 1) |argl|)))) (COND ((AND (> 10 |numArgs|) (EQL (SPADLET |n| (PARSE-INTEGER (PNAME (ELT |sop| 2)))) 1)) (CONS (QUOTE UP) (APPEND |argPart| (CONS |domainPart| NIL)))) ((QUOTE T) (CONS (QUOTE MP) (CONS (CONS (QUOTE |construct|) |argPart|) (CONS |domainPart| NIL))))))) (|specialModeTran| (COND ((BOOT-EQUAL |s3| (QUOTE R)) (CONS |$QuotientField| (CONS |polyForm| NIL))) ((QUOTE T) |polyForm|)))) ((QUOTE T) (CONS (CAR |form|) (PROG (#0=#:G2725) (SPADLET #0# NIL) (RETURN (DO ((#1=#:G2730 (CDR |form|) (CDR #1#)) (|x| NIL!
 )) ((OR (ATOM #1#) (PROGN (SETQ |x| (CAR #1#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS (|specialModeTran| |x|) #0#))))))))))))))) ((QUOTE T) (CONS (CAR |form|) (PROG (#2=#:G2740) (SPADLET #2# NIL) (RETURN (DO ((#3=#:G2745 (CDR |form|) (CDR #3#)) (|x| NIL)) ((OR (ATOM #3#) (PROGN (SETQ |x| (CAR #3#)) NIL)) (NREVERSE0 #2#)) (SEQ (EXIT (SETQ #2# (CONS (|specialModeTran| |x|) #2#))))))))))) ((QUOTE T) |form|)))))) 
+(DEFUN |specialModeTran| (|form|) (PROG (|op| |argl| |sop| |s0| |argKey| |numArgs| |zeroOrOne| |isDmp| |LETTMP#1| |vl| |extraDomain| |s3| |isUpOrMp| |domainPart| |argPart| |n| |polyForm|) (RETURN (SEQ (COND ((AND (PAIRP |form|) (PROGN (SPADLET |op| (QCAR |form|)) (SPADLET |argl| (QCDR |form|)) (QUOTE T))) (COND ((NULL (ATOM |op|)) |form|) ((BOOT-EQUAL (SPADLET |s0| (SAFE-ELT (SPADLET |sop| (PNAME |op|)) 0)) (QUOTE *)) (SPADLET |n| (|#| |sop|)) (COND ((EQL |n| 1) |form|) ((QUOTE T) (SPADLET |argKey| (SAFE-ELT |sop| 1)) (SPADLET |numArgs| (SPADDIFFERENCE (|#| |argl|) (COND ((BOOT-EQUAL |argKey| (QUOTE |1|)) 1) ((QUOTE T) 0)))) (SPADLET |zeroOrOne| (OR (BOOT-EQUAL |argKey| (QUOTE |0|)) (BOOT-EQUAL |argKey| (QUOTE |1|)))) (SPADLET |isDmp| (COND ((> 10 |numArgs|) (AND (EQL |n| 6) (BOOT-EQUAL (MAKESTRING "DMP") (SUBSTRING |sop| 3 3)) |zeroOrOne|)) ((QUOTE T) (AND (EQL |n| 7) (BOOT-EQUAL (MAKESTRING "DMP") (SUBSTRING |sop| 4 3)) |zeroOrOne|)))) (COND (|isDmp| (COND ((BOOT-EQUAL |a!
 rgKey| (QUOTE |0|)) (SPADLET |extraDomain| |$EmptyMode|) (SPADLET |vl| |argl|)) ((QUOTE T) (SPADLET |LETTMP#1| (REVERSE |argl|)) (SPADLET |extraDomain| (CAR |LETTMP#1|)) (SPADLET |vl| (NREVERSE (CDR |LETTMP#1|))) |argl|)) (CONS (QUOTE |DistributedMultivariatePolynomial|) (CONS (CONS (QUOTE |construct|) |vl|) (CONS (|specialModeTran| |extraDomain|) NIL)))) ((AND (EQL |n| 4) (BOOT-EQUAL (SPADLET |s3| (SAFE-ELT |sop| 3)) (QUOTE M)) |zeroOrOne|) (|specialModeTran| (PROGN (SPADLET |extraDomain| (COND ((BOOT-EQUAL |argKey| (QUOTE |0|)) (CONS |$EmptyMode| NIL)) ((QUOTE T) NIL))) (COND ((EQL (SPADLET |n| (PARSE-INTEGER (PNAME (SAFE-ELT |sop| 2)))) 1) (CONS (QUOTE |SquareMatrix|) (APPEND |argl| |extraDomain|))) ((EQL |n| 2) (CONS (QUOTE |RectangularMatrix|) (APPEND |argl| |extraDomain|))) ((QUOTE T) |form|))))) ((QUOTE T) (SPADLET |isUpOrMp| (COND ((> 10 |numArgs|) (OR (AND (EQL |n| 4) (BOOT-EQUAL (SPADLET |s3| (SAFE-ELT |sop| 3)) (QUOTE P)) |zeroOrOne|) (AND (EQL |n| 5) (BOOT-EQUAL!
  (SPADLET |s3| (SAFE-ELT |sop| 3)) (QUOTE R)) (BOOT-EQUAL (SAFE-ELT |s
op| 4) (QUOTE F)) |zeroOrOne|))) ((QUOTE T) (OR (AND (EQL |n| 5) (BOOT-EQUAL (SPADLET |s3| (SAFE-ELT |sop| 4)) (QUOTE P)) |zeroOrOne|) (AND (EQL |n| 6) (BOOT-EQUAL (SPADLET |s3| (SAFE-ELT |sop| 4)) (QUOTE R)) (BOOT-EQUAL (SAFE-ELT |sop| 5) (QUOTE F)) |zeroOrOne|))))) (COND (|isUpOrMp| (SPADLET |polyForm| (PROGN (SPADLET |domainPart| (COND ((BOOT-EQUAL |argKey| (QUOTE |0|)) |$EmptyMode|) ((QUOTE T) (|last| |argl|)))) (SPADLET |argPart| (COND ((BOOT-EQUAL |argKey| (QUOTE |0|)) |argl|) ((QUOTE T) (DROP (SPADDIFFERENCE 1) |argl|)))) (COND ((AND (> 10 |numArgs|) (EQL (SPADLET |n| (PARSE-INTEGER (PNAME (SAFE-ELT |sop| 2)))) 1)) (CONS (QUOTE UP) (APPEND |argPart| (CONS |domainPart| NIL)))) ((QUOTE T) (CONS (QUOTE MP) (CONS (CONS (QUOTE |construct|) |argPart|) (CONS |domainPart| NIL))))))) (|specialModeTran| (COND ((BOOT-EQUAL |s3| (QUOTE R)) (CONS |$QuotientField| (CONS |polyForm| NIL))) ((QUOTE T) |polyForm|)))) ((QUOTE T) (CONS (CAR |form|) (PROG (#0=#:G2725) (SPADLET #0# NIL) (R!
 ETURN (DO ((#1=#:G2730 (CDR |form|) (CDR #1#)) (|x| NIL)) ((OR (ATOM #1#) (PROGN (SETQ |x| (CAR #1#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS (|specialModeTran| |x|) #0#))))))))))))))) ((QUOTE T) (CONS (CAR |form|) (PROG (#2=#:G2740) (SPADLET #2# NIL) (RETURN (DO ((#3=#:G2745 (CDR |form|) (CDR #3#)) (|x| NIL)) ((OR (ATOM #3#) (PROGN (SETQ |x| (CAR #3#)) NIL)) (NREVERSE0 #2#)) (SEQ (EXIT (SETQ #2# (CONS (|specialModeTran| |x|) #2#))))))))))) ((QUOTE T) |form|)))))) 
 ;
 ;parseHas [x,y] ==
 ;  if $InteractiveMode then
diff --git a/src/interp/setvars.boot.pamphlet b/src/interp/setvars.boot.pamphlet
index 864ced0..69535e8 100644
--- a/src/interp/setvars.boot.pamphlet
+++ b/src/interp/setvars.boot.pamphlet
@@ -2072,7 +2072,7 @@ describeSetStreamsCalculate() == sayKeyedMsg("S2IV0001",[$streamCount])
 ;        '"have the same effect as",:bright '"on",'"and",:bright '"off",
 ;          '"respectively."]
 
-(DEFUN |displaySetOptionInformation| (|arg| |setData|) (PROG (|st| |current|) (RETURN (SEQ (PROGN (SPADLET |st| (ELT |setData| 3)) (COND ((BOOT-EQUAL |st| (QUOTE TREE)) (|displaySetVariableSettings| (ELT |setData| 5) (ELT |setData| 0))) ((QUOTE T) (|centerAndHighlight| (STRCONC (MAKESTRING "The ") (|object2String| |arg|) (MAKESTRING " Option")) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|sayBrightly| (CONS (QUOTE |%l|) (APPEND (|bright| (MAKESTRING "Description:")) (CONS (ELT |setData| 1) NIL)))) (COND ((BOOT-EQUAL |st| (QUOTE FUNCTION)) (TERPRI) (COND ((|functionp| (ELT |setData| 4)) (FUNCALL (ELT |setData| 4) (QUOTE |%describe%|))) ((QUOTE T) (|sayMSG| (MAKESTRING "   Function not implemented."))))) ((BOOT-EQUAL |st| (QUOTE INTEGER)) (|sayMessage| (CONS (MAKESTRING " The") (APPEND (|bright| |arg|) (CONS (MAKESTRING "option") (CONS (MAKESTRING " may be followed by an integer in the range") (APPEND (|bright| (ELT (ELT |setData| 5) 0)) (CONS (MAKESTRING "to") (CONS (QUOTE !
 |%l|) (APPEND (|bright| (ELT (ELT |setData| 5) 1)) (CONS (MAKESTRING "inclusive.") (CONS (MAKESTRING " The current setting is") (|bright| (|eval| (ELT |setData| 4))))))))))))))) ((BOOT-EQUAL |st| (QUOTE STRING)) (|sayMessage| (CONS (MAKESTRING " The") (APPEND (|bright| |arg|) (CONS (MAKESTRING "option") (CONS (MAKESTRING " is followed by a string enclosed in double quote marks.") (CONS (QUOTE |%l|) (CONS (MAKESTRING " The current setting is") (|bright| (CONS (QUOTE |"|) (CONS (|eval| (ELT |setData| 4)) (CONS (QUOTE |"|) NIL)))))))))))) ((BOOT-EQUAL |st| (QUOTE LITERALS)) (PROGN (|sayMessage| (CONS (MAKESTRING " The") (APPEND (|bright| |arg|) (CONS (MAKESTRING "option") (CONS (MAKESTRING " may be followed by any one of the following:") NIL))))) (SPADLET |current| (|translateTrueFalse2YesNo| (|eval| (ELT |setData| 4)))) (DO ((#0=#:G2796 (ELT |setData| 5) (CDR #0#)) (|name| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |name| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (COND ((BOOT-EQUAL |name| |cu!
 rrent|) (|sayBrightly| (CONS (MAKESTRING " ->") (|bright| (|object2Str
ing| |name|))))) ((QUOTE T) (|sayBrightly| (CONS (MAKESTRING "    ") (CONS (|object2String| |name|) NIL)))))))) (|sayMessage| (MAKESTRING " The current setting is indicated within the list.")) (COND ((OR (BOOT-EQUAL (ELT |setData| 5) (QUOTE (|yes| |no| |on| |off|))) (BOOT-EQUAL (ELT |setData| 5) (QUOTE (|yes| |no| |on| |off| |long|)))) (|sayMessage| (APPEND (|bright| (MAKESTRING "yes")) (CONS (MAKESTRING "and") (APPEND (|bright| (MAKESTRING "no")) (CONS (MAKESTRING "have the same effect as") (APPEND (|bright| (MAKESTRING "on")) (CONS (MAKESTRING "and") (APPEND (|bright| (MAKESTRING "off")) (CONS (MAKESTRING "respectively.") NIL)))))))))) ((QUOTE T) NIL)))))))))))) 
+(DEFUN |displaySetOptionInformation| (|arg| |setData|) (PROG (|st| |current|) (RETURN (SEQ (PROGN (SPADLET |st| (ELT |setData| 3)) (COND ((BOOT-EQUAL |st| (QUOTE TREE)) (|displaySetVariableSettings| (ELT |setData| 5) (ELT |setData| 0))) ((QUOTE T) (|centerAndHighlight| (STRCONC (MAKESTRING "The ") (|object2String| |arg|) (MAKESTRING " Option")) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|sayBrightly| (CONS (QUOTE |%l|) (APPEND (|bright| (MAKESTRING "Description:")) (CONS (ELT |setData| 1) NIL)))) (COND ((BOOT-EQUAL |st| (QUOTE FUNCTION)) (TERPRI) (COND ((|functionp| (ELT |setData| 4)) (FUNCALL (ELT |setData| 4) (QUOTE |%describe%|))) ((QUOTE T) (|sayMSG| (MAKESTRING "   Function not implemented."))))) ((BOOT-EQUAL |st| (QUOTE INTEGER)) (|sayMessage| (CONS (MAKESTRING " The") (APPEND (|bright| |arg|) (CONS (MAKESTRING "option") (CONS (MAKESTRING " may be followed by an integer in the range") (APPEND (|bright| (SAFE-ELT (ELT |setData| 5) 0)) (CONS (MAKESTRING "to") (CONS (Q!
 UOTE |%l|) (APPEND (|bright| (SAFE-ELT (ELT |setData| 5) 1)) (CONS (MAKESTRING "inclusive.") (CONS (MAKESTRING " The current setting is") (|bright| (|eval| (ELT |setData| 4))))))))))))))) ((BOOT-EQUAL |st| (QUOTE STRING)) (|sayMessage| (CONS (MAKESTRING " The") (APPEND (|bright| |arg|) (CONS (MAKESTRING "option") (CONS (MAKESTRING " is followed by a string enclosed in double quote marks.") (CONS (QUOTE |%l|) (CONS (MAKESTRING " The current setting is") (|bright| (CONS (QUOTE |"|) (CONS (|eval| (ELT |setData| 4)) (CONS (QUOTE |"|) NIL)))))))))))) ((BOOT-EQUAL |st| (QUOTE LITERALS)) (PROGN (|sayMessage| (CONS (MAKESTRING " The") (APPEND (|bright| |arg|) (CONS (MAKESTRING "option") (CONS (MAKESTRING " may be followed by any one of the following:") NIL))))) (SPADLET |current| (|translateTrueFalse2YesNo| (|eval| (ELT |setData| 4)))) (DO ((#0=#:G2796 (ELT |setData| 5) (CDR #0#)) (|name| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |name| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (COND ((BOOT-EQUAL !
 |name| |current|) (|sayBrightly| (CONS (MAKESTRING " ->") (|bright| (|
object2String| |name|))))) ((QUOTE T) (|sayBrightly| (CONS (MAKESTRING "    ") (CONS (|object2String| |name|) NIL)))))))) (|sayMessage| (MAKESTRING " The current setting is indicated within the list.")) (COND ((OR (BOOT-EQUAL (ELT |setData| 5) (QUOTE (|yes| |no| |on| |off|))) (BOOT-EQUAL (ELT |setData| 5) (QUOTE (|yes| |no| |on| |off| |long|)))) (|sayMessage| (APPEND (|bright| (MAKESTRING "yes")) (CONS (MAKESTRING "and") (APPEND (|bright| (MAKESTRING "no")) (CONS (MAKESTRING "have the same effect as") (APPEND (|bright| (MAKESTRING "on")) (CONS (MAKESTRING "and") (APPEND (|bright| (MAKESTRING "off")) (CONS (MAKESTRING "respectively.") NIL)))))))))) ((QUOTE T) NIL)))))))))))) 
 ;displaySetVariableSettings(setTree,label) ==
 ;  if label = "" then label := '")set"
 ;    else label := STRCONC('" ",object2String label,'" ")
@@ -2259,7 +2259,7 @@ describeSetStreamsCalculate() == sayKeyedMsg("S2IV0001",[$streamCount])
 ;    sayKeyedMsg("S2IZ0049R",[x,$interpreterFrameName])
 ;    clearClams()
 
-(DEFUN |setExposeAddGroup| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The group Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|displayExposedGroups|) (|sayMSG| (MAKESTRING " ")) (|sayKeyedMsg| (QUOTE S2IZ0049G) (CONS (|namestring| (|pathname| (CONS "interp" (CONS "exposed" NIL)))) NIL)) (|sayMSG| (MAKESTRING " ")) (|sayAsManyPerLineAsPossible| (PROG (#0=#:G2946) (SPADLET #0# NIL) (RETURN (DO ((#1=#:G2951 |$globalExposureGroupAlist| (CDR #1#)) (|x| NIL)) ((OR (ATOM #1#) (PROGN (SETQ |x| (CAR #1#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS (|object2String| (CAR |x|)) #0#))))))))) ((QUOTE T) (DO ((#2=#:G2962 |arg| (CDR #2#)) (|x| NIL)) ((OR (ATOM #2#) (PROGN (SETQ |x| (CAR #2#)) NIL)) NIL) (SEQ (EXIT (PROGN (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((BOOT-EQUAL |x| (QUOTE |all|)) (SETELT |$localExposureData| 0 (PROG (#3=#:G2972) (SPADLET #3# NIL) (RETURN (DO ((#4=#:G2977 |$globalExposureGroupAlist| (CDR #4#)) (|!
 x| NIL)) ((OR (ATOM #4#) (PROGN (SETQ |x| (CAR #4#)) NIL)) (NREVERSE0 #3#)) (SEQ (EXIT (SETQ #3# (CONS (CAR |x|) #3#)))))))) (SETELT |$localExposureData| 1 NIL) (SETELT |$localExposureData| 2 NIL) (|displayExposedGroups|) (|sayMSG| (MAKESTRING " ")) (|displayExposedConstructors|) (|sayMSG| (MAKESTRING " ")) (|displayHiddenConstructors|) (|clearClams|)) ((NULL (GETALIST |$globalExposureGroupAlist| |x|)) (|sayKeyedMsg| (QUOTE S2IZ0049H) (CONS |x| NIL))) ((|member| |x| (ELT |$localExposureData| 0)) (|sayKeyedMsg| (QUOTE S2IZ0049I) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (SETELT |$localExposureData| 0 (MSORT (CONS |x| (ELT |$localExposureData| 0)))) (|sayKeyedMsg| (QUOTE S2IZ0049R) (CONS |x| (CONS |$interpreterFrameName| NIL))) (|clearClams|))))))))))))) 
+(DEFUN |setExposeAddGroup| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The group Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|displayExposedGroups|) (|sayMSG| (MAKESTRING " ")) (|sayKeyedMsg| (QUOTE S2IZ0049G) (CONS (|namestring| (|pathname| (CONS "interp" (CONS "exposed" NIL)))) NIL)) (|sayMSG| (MAKESTRING " ")) (|sayAsManyPerLineAsPossible| (PROG (#0=#:G2946) (SPADLET #0# NIL) (RETURN (DO ((#1=#:G2951 |$globalExposureGroupAlist| (CDR #1#)) (|x| NIL)) ((OR (ATOM #1#) (PROGN (SETQ |x| (CAR #1#)) NIL)) (NREVERSE0 #0#)) (SEQ (EXIT (SETQ #0# (CONS (|object2String| (CAR |x|)) #0#))))))))) ((QUOTE T) (DO ((#2=#:G2962 |arg| (CDR #2#)) (|x| NIL)) ((OR (ATOM #2#) (PROGN (SETQ |x| (CAR #2#)) NIL)) NIL) (SEQ (EXIT (PROGN (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((BOOT-EQUAL |x| (QUOTE |all|)) (SETELT |$localExposureData| 0 (PROG (#3=#:G2972) (SPADLET #3# NIL) (RETURN (DO ((#4=#:G2977 |$globalExposureGroupAlist| (CDR #4#)) (|!
 x| NIL)) ((OR (ATOM #4#) (PROGN (SETQ |x| (CAR #4#)) NIL)) (NREVERSE0 #3#)) (SEQ (EXIT (SETQ #3# (CONS (CAR |x|) #3#)))))))) (SETELT |$localExposureData| 1 NIL) (SETELT |$localExposureData| 2 NIL) (|displayExposedGroups|) (|sayMSG| (MAKESTRING " ")) (|displayExposedConstructors|) (|sayMSG| (MAKESTRING " ")) (|displayHiddenConstructors|) (|clearClams|)) ((NULL (GETALIST |$globalExposureGroupAlist| |x|)) (|sayKeyedMsg| (QUOTE S2IZ0049H) (CONS |x| NIL))) ((|member| |x| (SAFE-ELT |$localExposureData| 0)) (|sayKeyedMsg| (QUOTE S2IZ0049I) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (SETELT |$localExposureData| 0 (MSORT (CONS |x| (SAFE-ELT |$localExposureData| 0)))) (|sayKeyedMsg| (QUOTE S2IZ0049R) (CONS |x| (CONS |$interpreterFrameName| NIL))) (|clearClams|))))))))))))) 
 ;setExposeAddConstr arg ==
 ;  (null arg) =>
 ;    centerAndHighlight ("The constructor Option",$LINELENGTH,
@@ -2281,7 +2281,7 @@ describeSetStreamsCalculate() == sayKeyedMsg("S2IV0001",[$streamCount])
 ;    clearClams()
 ;    sayKeyedMsg("S2IZ0049P",[x,$interpreterFrameName])
 
-(DEFUN |setExposeAddConstr| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The constructor Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|displayExposedConstructors|)) ((QUOTE T) (DO ((#0=#:G2998 |arg| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (PROGN (SPADLET |x| (|unabbrev| |x|)) (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((NULL (GETDATABASE |x| (QUOTE CONSTRUCTORKIND))) (|sayKeyedMsg| (QUOTE S2IZ0049J) (CONS |x| NIL))) ((|member| |x| (ELT |$localExposureData| 1)) (|sayKeyedMsg| (QUOTE S2IZ0049K) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (COND ((|member| |x| (ELT |$localExposureData| 2)) (SETELT |$localExposureData| 2 (|delete| |x| (ELT |$localExposureData| 2))))) (SETELT |$localExposureData| 1 (MSORT (CONS |x| (ELT |$localExposureData| 1)))) (|clearClams|) (|sayKeyedMsg| (QUOTE S2IZ0049P) (CONS |x| (CONS |$interpreterFrameName| NIL))))))))))))))) 
+(DEFUN |setExposeAddConstr| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The constructor Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|displayExposedConstructors|)) ((QUOTE T) (DO ((#0=#:G2998 |arg| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (PROGN (SPADLET |x| (|unabbrev| |x|)) (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((NULL (GETDATABASE |x| (QUOTE CONSTRUCTORKIND))) (|sayKeyedMsg| (QUOTE S2IZ0049J) (CONS |x| NIL))) ((|member| |x| (SAFE-ELT |$localExposureData| 1)) (|sayKeyedMsg| (QUOTE S2IZ0049K) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (COND ((|member| |x| (SAFE-ELT |$localExposureData| 2)) (SETELT |$localExposureData| 2 (|delete| |x| (SAFE-ELT |$localExposureData| 2))))) (SETELT |$localExposureData| 1 (MSORT (CONS |x| (SAFE-ELT |$localExposureData| 1)))) (|clearClams|) (|sayKeyedMsg| (QUOTE S2IZ0049P) (CONS |x| (CONS |$interpreterFrameName| NIL)))))))!
 )))))))) 
 ;setExposeDrop arg ==
 ;  (null arg) =>
 ;    centerAndHighlight ("The drop Option",$LINELENGTH,specialChar 'hbar)
@@ -2323,7 +2323,7 @@ describeSetStreamsCalculate() == sayKeyedMsg("S2IV0001",[$streamCount])
 ;      sayKeyedMsg("S2IZ0049I",[x,$interpreterFrameName])
 ;    sayKeyedMsg("S2IZ0049H",[x])
 
-(DEFUN |setExposeDropGroup| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The group Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|sayKeyedMsg| (QUOTE S2IZ0049L) NIL) (|sayMSG| (MAKESTRING " ")) (|displayExposedGroups|)) ((QUOTE T) (DO ((#0=#:G3031 |arg| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (PROGN (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((BOOT-EQUAL |x| (QUOTE |all|)) (SETELT |$localExposureData| 0 NIL) (SETELT |$localExposureData| 1 NIL) (SETELT |$localExposureData| 2 NIL) (|displayExposedGroups|) (|sayMSG| (MAKESTRING " ")) (|displayExposedConstructors|) (|sayMSG| (MAKESTRING " ")) (|displayHiddenConstructors|) (|clearClams|)) ((|member| |x| (ELT |$localExposureData| 0)) (SETELT |$localExposureData| 0 (|delete| |x| (ELT |$localExposureData| 0))) (|clearClams|) (|sayKeyedMsg| (QUOTE S2IZ0049S) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((GETALIST |$globalExposur!
 eGroupAlist| |x|) (|sayKeyedMsg| (QUOTE S2IZ0049I) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (|sayKeyedMsg| (QUOTE S2IZ0049H) (CONS |x| NIL)))))))))))))) 
+(DEFUN |setExposeDropGroup| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The group Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|sayKeyedMsg| (QUOTE S2IZ0049L) NIL) (|sayMSG| (MAKESTRING " ")) (|displayExposedGroups|)) ((QUOTE T) (DO ((#0=#:G3031 |arg| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (PROGN (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((BOOT-EQUAL |x| (QUOTE |all|)) (SETELT |$localExposureData| 0 NIL) (SETELT |$localExposureData| 1 NIL) (SETELT |$localExposureData| 2 NIL) (|displayExposedGroups|) (|sayMSG| (MAKESTRING " ")) (|displayExposedConstructors|) (|sayMSG| (MAKESTRING " ")) (|displayHiddenConstructors|) (|clearClams|)) ((|member| |x| (SAFE-ELT |$localExposureData| 0)) (SETELT |$localExposureData| 0 (|delete| |x| (SAFE-ELT |$localExposureData| 0))) (|clearClams|) (|sayKeyedMsg| (QUOTE S2IZ0049S) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((GETALIST |$glo!
 balExposureGroupAlist| |x|) (|sayKeyedMsg| (QUOTE S2IZ0049I) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (|sayKeyedMsg| (QUOTE S2IZ0049H) (CONS |x| NIL)))))))))))))) 
 ;setExposeDropConstr arg ==
 ;  (null arg) =>
 ;    centerAndHighlight ("The constructor Option",$LINELENGTH,
@@ -2347,7 +2347,7 @@ describeSetStreamsCalculate() == sayKeyedMsg("S2IV0001",[$streamCount])
 ;    clearClams()
 ;    sayKeyedMsg("S2IZ0049Q",[x,$interpreterFrameName])
 
-(DEFUN |setExposeDropConstr| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The constructor Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|sayKeyedMsg| (QUOTE S2IZ0049N) NIL) (|sayMSG| (MAKESTRING " ")) (|displayExposedConstructors|) (|sayMSG| (MAKESTRING " ")) (|displayHiddenConstructors|)) ((QUOTE T) (DO ((#0=#:G3050 |arg| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (PROGN (SPADLET |x| (|unabbrev| |x|)) (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((NULL (GETDATABASE |x| (QUOTE CONSTRUCTORKIND))) (|sayKeyedMsg| (QUOTE S2IZ0049J) (CONS |x| NIL))) ((|member| |x| (ELT |$localExposureData| 2)) (|sayKeyedMsg| (QUOTE S2IZ0049O) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (COND ((|member| |x| (ELT |$localExposureData| 1)) (SETELT |$localExposureData| 1 (|delete| |x| (ELT |$localExposureData| 1))))) (SETELT |$localExposureData| 2 (MSORT (CONS |x| (ELT |$localExposureData|!
  2)))) (|clearClams|) (|sayKeyedMsg| (QUOTE S2IZ0049Q) (CONS |x| (CONS |$interpreterFrameName| NIL))))))))))))))) 
+(DEFUN |setExposeDropConstr| (|arg|) (PROG (|x|) (RETURN (SEQ (COND ((NULL |arg|) (|centerAndHighlight| (QUOTE |The constructor Option|) $LINELENGTH (|specialChar| (QUOTE |hbar|))) (|sayKeyedMsg| (QUOTE S2IZ0049N) NIL) (|sayMSG| (MAKESTRING " ")) (|displayExposedConstructors|) (|sayMSG| (MAKESTRING " ")) (|displayHiddenConstructors|)) ((QUOTE T) (DO ((#0=#:G3050 |arg| (CDR #0#)) (|x| NIL)) ((OR (ATOM #0#) (PROGN (SETQ |x| (CAR #0#)) NIL)) NIL) (SEQ (EXIT (PROGN (SPADLET |x| (|unabbrev| |x|)) (COND ((PAIRP |x|) (SPADLET |x| (QCAR |x|)))) (COND ((NULL (GETDATABASE |x| (QUOTE CONSTRUCTORKIND))) (|sayKeyedMsg| (QUOTE S2IZ0049J) (CONS |x| NIL))) ((|member| |x| (SAFE-ELT |$localExposureData| 2)) (|sayKeyedMsg| (QUOTE S2IZ0049O) (CONS |x| (CONS |$interpreterFrameName| NIL)))) ((QUOTE T) (COND ((|member| |x| (SAFE-ELT |$localExposureData| 1)) (SETELT |$localExposureData| 1 (|delete| |x| (SAFE-ELT |$localExposureData| 1))))) (SETELT |$localExposureData| 2 (MSORT (CONS |x| (SAFE-ELT !
 |$localExposureData| 2)))) (|clearClams|) (|sayKeyedMsg| (QUOTE S2IZ0049Q) (CONS |x| (CONS |$interpreterFrameName| NIL))))))))))))))) 
 ;setFortTmpDir arg ==
 ;  arg = "%initialize%" =>
 ;    $fortranTmpDir := '"/tmp/"
diff --git a/src/interp/spaderror.lisp.pamphlet b/src/interp/spaderror.lisp.pamphlet
index 3db7dcd..d3e821d 100644
--- a/src/interp/spaderror.lisp.pamphlet
+++ b/src/interp/spaderror.lisp.pamphlet
@@ -87,7 +87,7 @@
 ;;      (if (NULL val) |$numericFailure| (cons 0 (car val)))))
 
 ;; the following form embeds around the akcl error handler
-#+:akcl
+#+:GCL
 (eval-when
  (load eval)
  (unembed 'system:universal-error-handler)
@@ -102,7 +102,8 @@
 			   (|systemError| (error-format error-string args)))
 			  ((and (eq |$BreakMode| '|trapNumerics|)
 				(eq type :ERROR))
-			   (setq |$BreakMode| nil)			   (throw '|trapNumerics| |$numericFailure|))
+			   (setq |$BreakMode| nil)
+			   (throw '|trapNumerics| |$numericFailure|))
                           ((and (eq |$BreakMode| '|trapNumerics|)
 				(boundp '|$oldBreakMode|)
 				(setq |$BreakMode| |$oldBreakMode|)
diff --git a/src/interp/sys-pkg.lisp.pamphlet b/src/interp/sys-pkg.lisp.pamphlet
index 6ac6d4f..28968b5 100644
--- a/src/interp/sys-pkg.lisp.pamphlet
+++ b/src/interp/sys-pkg.lisp.pamphlet
@@ -129,11 +129,11 @@ idioms from prior ports (like rdefiostream and fileactq)
    "RDEFIOSTREAM" "RDROPITEMS" "RE-ENABLE-INT" "RECLAIM" "RECOMPILE-DIRECTORY"
    "RECOMPILE-LIB-FILE-IF-NECESSARY" "REFVECP" "REMAINDER" "REMOVEQ" "REROOT"
    "RESETQ" "RKEYIDS" "RNUMP" "RPACKFILE" "RPLACSTR" "RPLNODE" "RPLPAIR" "RPLQ"
-   "RREAD" "RSETCLASS" "RSHUT" "RVECP" "RWRITE" "SEQ" "SETANDFILEQ"
-   "SETDIFFERENCE" "SETDIFFERENCEQ" "SETELT" "SETQP" "SETSIZE" "SFP" "SHUT"
-   "SINTP" "SIZE" "SMINTP" "SORTBY" "SORTGREATERP" "STACKLIFO" "STATEP" "STRCONC"
-   "STRGREATERP" "STRING2ID-N" "STRINGIMAGE" "STRINGLENGTH" "STRPOS" "STRPOSL"
-   "SUB1" "SUBLOAD" "SUBRP" "SUBSTQ" "SUBSTRING" "SUFFIX" "SYSTEM" "TAB"
+   "RREAD" "RSETCLASS" "RSHUT" "RVECP" "RWRITE" "SAFE-ELT" "SAFE-SETELT" "SEQ" 
+   "SETANDFILEQ" "SETDIFFERENCE" "SETDIFFERENCEQ" "SETELT" "SETQP" "SETSIZE" "SFP"
+   "SHUT" "SINTP" "SIZE" "SMINTP" "SORTBY" "SORTGREATERP" "STACKLIFO" "STATEP"
+   "STRCONC" "STRGREATERP" "STRING2ID-N" "STRINGIMAGE" "STRINGLENGTH" "STRPOS"
+   "STRPOSL" "SUB1" "SUBLOAD" "SUBRP" "SUBSTQ" "SUBSTRING" "SUFFIX" "SYSTEM" "TAB"
    "TEMPUS-FUGIT" "TEREAD" "THROW-PROTECT" "TIMES" "TRIMSTRING" "TRUEFN" "U-CASE"
    "UEQUAL" "UNEMBED" "UNIONQ" "UPCASE" "USE-VMLISP-SYNTAX" "VEC-SETELT"
    "VEC2LIST" "VECP" "VM/" "VMPRINT" "VMREAD" "assoc" "directoryp" "idChar?"
diff --git a/src/interp/vmlisp.lisp.pamphlet b/src/interp/vmlisp.lisp.pamphlet
index fe3cf7a..5c6116d 100644
--- a/src/interp/vmlisp.lisp.pamphlet
+++ b/src/interp/vmlisp.lisp.pamphlet
@@ -589,9 +589,30 @@ Contributed by Juergen Weiss.
    (setq ,id ,item)
    (lam\,fileactq ',id (list 'setq ',id (list 'quote ,id)))))
 
-#-:CCL
+(defun safe-elt (seq n)
+  (declare (type sequence seq)
+           (type unsigned-byte n))
+  (if (consp seq)
+      (do ((tail seq (cdr tail)))
+          ((zerop n)
+           (if (consp tail) (car tail) tail))
+        (decf n))
+      (elt seq n)))
+
+(defun safe-setelt (seq n val)
+  (declare (type sequence seq)
+           (type unsigned-byte n))
+  (if (consp seq)
+      (if (zerop n)
+          (setf (car seq) val)
+          (let ((tail (nthcdr (1- n) seq)))
+            (if (consp (cdr tail))
+                (setf (cadr tail) val)
+                (setf (cdr tail) val))))
+      (setf (elt seq n) val)))
+
 (defmacro setelt (vec ind val)
- `(setf (elt ,vec ,ind) ,val))
+  `(safe-setelt ,vec ,ind ,val))
 
 (defmacro setqp (&whole form pattern exp)
  (declare (ignore form))

--=-=-=--

\start
Date: Thu, 2 Aug 2007 01:05:22 +0200
From: Ondrej Certik
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

> | So it cannot go to the Debian main distribution, and that of course is
> | a major problem, at least for me.
>
> The linux distribution I've been for a decade now has a button that
> let me install "non-open source" software of highly practical value to me.

The technical thing is not a problem - it will be in the Debian
non-free and thus could be installed as easily as anything else. The
major problem for me is simply that it is not opensource.

\start
Date: Wed, 1 Aug 2007 19:34:17 -0500 (CDT)
From: Gabriel Dos Reis
To: Ondrej Certik
Subject: Re: Axiom meeting at ISSAC

On Thu, 2 Aug 2007, Ondrej Certik wrote:

| > | So it cannot go to the Debian main distribution, and that of course is
| > | a major problem, at least for me.
| >
| > The linux distribution I've been for a decade now has a button that
| > let me install "non-open source" software of highly practical value to me.
| 
| The technical thing is not a problem - it will be in the Debian
| non-free and thus could be installed as easily as anything else.

OK.

| The major problem for me is simply that it is not opensource.

OK; thanks for clarifying that.

\start
Date: Wed, 1 Aug 2007 19:35:58 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| 
| > (iii) of course, the answer is yes.  As I mentioned earlier, there are two
| >     parser in Axiom, an old and a new.  You're looking at the old compiler.
| 
| Of course I am looking at the old compiler, it is the only compiler.

Indeed, Earth is flat.

\start
Date: Wed, 1 Aug 2007 19:36:58 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

|           If you dont understand the issues, thats your problem.

No, I have no problem.  You have a problem.

\start
Date: Wed, 1 Aug 2007 19:38:40 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| > | The system is not extensible or flexible by any rational
| > | measurement.  
| > 
| > I suspect it is more accurate to say:
| > 
| >   The system is not extensible or flexible by any Stephen Wilson's
| >   measurement.
| > 
| > Care should be exercised before generalizing to "rational".
| 
| Yep, absolutely.  That is my opinion.  Rational thinking was used to
| formulate it.

In light of your postings, it is legitime to have profound doubt about
the last sentence.

\start
Date: 01 Aug 2007 21:09:35 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: Axiom meeting at ISSAC

Gaby,

I am frustrated with the current environment in the Axiom community.
It is a subjective opinion of mine that some comments you make are
intended to be abrasive more than informative.  I do try to look past
this personal impression, and to seek opportunities for compromise and
understanding.  I do try and remain objective, but clearly I fail at
times.  But it would seem there is so little common ground.  I feel
there is a wide chasm and the only means to communicate is thru a pair
of tin cans and some string.  Yelling (to extend the metaphor), is no
better.

Unfortunately, I read meaning into your initial comments about the
parser work which you may not have intended.  I apologize for allowing
a debate to ensue which took a tone I would have much rather avoided.

\start
Date: Wed, 1 Aug 2007 21:50:26 -0500 (CDT)
From: Gabriel Dos Reis
To: list
Subject: LastCxArg

It looks to me that the variable $LastCxArg in the routine
/foobar from src/interp/spad.lisp is a type for |$LastCxArg|.

\start
Date: Wed, 1 Aug 2007 22:00:15 -0500 (CDT)
From: Gabriel Dos Reis
To: list
Subject: sequence

When compiling with an ANSI common lisp compiler, the use of "sequence"
in src/interp/parsing.lisp is resoled as referring to the standard symbol
sequence, which belongs to locked standard packages.  I would suggest
to rename it to rule-sequence, and propagate the change down to the
parser.

\start
Date: Wed, 1 Aug 2007 22:03:42 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

On Wed, 1 Aug 2007, Stephen Wilson wrote:

| Unfortunately, I read meaning into your initial comments about the
| parser work which you may not have intended.  I apologize for allowing
| a debate to ensue which took a tone I would have much rather avoided.

Apologies accepted.  
Let's move on technical issues.

\start
Date: 01 Aug 2007 22:10:27 -0500
From: Gabriel Dos Reis
To: list
Subject: Re: sequence

Gabriel Dos Reis writes:

| When compiling with an ANSI common lisp compiler, the use of "sequence"
| in src/interp/parsing.lisp is resoled as referring to the standard symbol
| sequence, which belongs to locked standard packages.  I would suggest
| to rename it to rule-sequence, and propagate the change down to the
| parser.

similarly, "count" from the same file conflicts with standard count.

\start
Date: Thu, 02 Aug 2007 12:18:57 +0200
From: Ralf Hemmecke
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC

> Another example is Aldors generators.  It is planned that these will
> be supported in the new SPAD as a special case of continuations.
> Thus, generators in SPAD will become an algebra item, not a builtin.

Could you demonstrate some SPAD-code-to-be which uses continuations and 
solves a problem that cannot be solved easily by an Aldor equivalent?

Do you think that SPAD-continuations are important for implementing 
mathematical algorithms? Examples?

\start
Date: 02 Aug 2007 12:06:16 -0400
From: Stephen Wilson
To: Ralf Hemmecke
Subject: Re: Axiom meeting at ISSAC

Hi Ralf,

The idea of exploring the use of continuations came about as a result
of considering that there is high probability it could be used at the
algebra level to implement provisos in a natural way.

It was further motivated by the possibility of representing SPAD
programs in Continuation Passing Style internally within the compiler.
Now, this approach does not require continuations in SPAD itself to be
useful.  Rather, if a CPS representation is used, continuations become
that much easier to integrate into the language.

Ralf Hemmecke writes:
> Could you demonstrate some SPAD-code-to-be which uses continuations
> and solves a problem that cannot be solved easily by an Aldor
> equivalent?

I am not to sure what you want me to give. Writing a lot of pseudo
code is not terribly useful in all cases. Knuth wrote in TAOCP in
section 1.4.2 "It is rather difficult to find short, simple examples
of coroutines that illustrate the importance of the idea; the most
useful coroutine applications are generally quite lengthy".  Now,
coroutines are a generalization of generators, and continuations are a
generalization of coroutines.  I am having a though time thinking
about a useful, simple, example.  I could give an example of how
continuations could be used to implement generators which would likely
be short and perhaps informative -- is that what you are looking for?


> Do you think that SPAD-continuations are important for implementing
> mathematical algorithms? Examples?

Well, I think Tim already gave a better list than I could off the top
of my head:

 http://lists.gnu.org/archive/html/axiom-developer/2007-07/msg00169.html

Just remember that coroutines are basically just a powerful form of
control flow which also happens to lend itself nicely to parallel
execution (you can use the concept of continuation to implement the
notion of a thread) and analysis by a compiler.  So, yes, I think they
can be important for implementing algorithms.

\start
Date: Thu, 02 Aug 2007 18:42:56 +0200
From: Ralf Hemmecke
To: Stephen Wilson
Subject: Continuations in SPAD

> Ralf Hemmecke writes:
>> Could you demonstrate some SPAD-code-to-be which uses continuations
>>  and solves a problem that cannot be solved easily by an Aldor 
>> equivalent?
> 
> I am not to sure what you want me to give. Writing a lot of pseudo 
> code is not terribly useful in all cases.

No not pseudo code. Define a syntax for continuations in SPAD-to-be. And 
then write real SPAD-to-be code.

> Knuth wrote in TAOCP in section 1.4.2 "It is rather difficult to find
> short, simple examples of coroutines that illustrate the importance
> of the idea; the most useful coroutine applications are generally
> quite lengthy".

Of course, if Knuth says it, coroutines are important. ;-)

> Now, coroutines are a generalization of generators,
> and continuations are a generalization of coroutines.  I am having a
> though time thinking about a useful, simple, example.  I could give
> an example of how continuations could be used to implement generators
> which would likely be short and perhaps informative -- is that what
> you are looking for?

Actually not, but maybe it would be illustrative anyway.

I am looking for something that would cause me headaches to implement in 
(current) Aldor and which would be easy with continuations. Is must be 
related to implementing mathematics. I don't yet see how useful 
continuations are in a mathematical library context.

You mentioned parallel execution, but there is also
http://www.inf.ethz.ch/personal/mannhart/piit/
http://www.ph.ed.ac.uk/~bj/paraldor/WWW/


>> Do you think that SPAD-continuations are important for implementing
>>  mathematical algorithms? Examples?

> Well, I think Tim already gave a better list than I could off the top
>  of my head:
> 
> http://lists.gnu.org/archive/html/axiom-developer/2007-07/msg00169.html

I've read that already and it did not yet convince me. I want to see 
real algebra code that looks natural to implement by means of continuations.

\start
Date: 02 Aug 2007 13:38:39 -0400
From: Camm Maguire
To: Stephen Wilson
Subject: Re: gclcvs-2.7.0 and Axiom

Stephen Wilson writes:

> Hello Camm,
> 
> I am interested in your opinion about the following error, which is
> occurring for me during the compilation of src/algebra/tree.spad:
> 
> -------
>  Error: 
>  Fast links are on: do (si::use-fast-links nil) for debugging
>  Signalled by |NEWLOOKUPINADDCHAIN|.
>  Condition in |newLookupInAddChain| [or a callee]: INTERNAL-SIMPLE-TYPE-ERROR: #<FREE OBJECT 01ce05c8> is not of type FUNCTION: 
> 
>  Broken at |NEWLOOKUPINADDCHAIN|.  Type :H for Help.
>   1 (Continue) Return to top level.
>  BOOT>>:bt
> 
>  #0   newLookupInAddChain {loc0=|empty?|,loc1=((|Boolean|) $),loc2=#<vector 01f8d9f0>,loc3=#<vector 01f8d9...} [ihs=14]
>  #1   genDeltaEntry {loc0=(|empty?| (#1=(|List| s) (|Boolean|) (|List| s)) (t (elt #1# #))),loc1=(el...} [ihs=13]
>  #2   compForm3 {loc0=(|empty?| |ls|),loc1=|$EmptyMode|,loc2=(((# # # ...))),loc3=(((#1=# # #) (...} [ihs=12]
>  #3   compForm {loc0=(|empty?| |ls|),loc1=|$EmptyMode|,loc2=(((# # # ...))),loc3=nil,loc4=speci...} [ihs=11]
>  #4   setqSingle {loc0=#:g2300,loc1=(|empty?| |ls|),loc2=|NoValueMode|,loc3=(((# # # ...))),loc4=...} [ihs=10]
>  #5   compSeq1 {loc0=((let #1=#:g2300 (|empty?| |ls|)) (|exit| 1 (if #1# # ...))),loc1=($),loc2...} [ihs=9]
>  #6   compDefineCapsuleFunction {loc0=(def (|tree| |ls|) (nil nil) ...),loc1=|$EmptyMode|,loc2=(((# # # ...))),l...} [ihs=8]
>  #7   compCapsuleInner {loc0=((mdef (|cycleTreeMax|) (nil) ...) (qsetrefv $ 7 ...) (|:| |t| $) ...),loc...} [ihs=7]
>  #8   comp {loc0=(|where| (def (|Tree| s) (# nil) ...) (|:| s (|SetCategory|))),loc1=|$Empt...} [ihs=6]
>  #9   SpadInterpretStream {loc0=1,loc1=(tim daly ?),loc2=t,loc3=nil,loc4="doc",loc5="spadhelp",loc6="axiom...} [ihs=3]
>  #10   spad {loc0=|.axiom|,loc1=nil,loc2=nil,loc3=#<synonym stream to *terminal-io*>,loc4=25...} [ihs=2]
> -------
> 
> The function |newLookupInAddChain| is defined in
> src/interp/nrunfast.boot.pamphlet, and everything appears to be in
> order on the Axiom side, however:
> 
> This is proving to be very difficult to debug, since I cannot
> reproduce except by starting Axiom and immediately compiling the file.
> If I do (si::use-fast-links nil) the problem goes away. Attempting to
> trace any of the above functions, or even typing "1+1" at the axiom
> prompt before compiling, the problem goes away.
> 
> This behavior is new, so I suspect a change in gclcvs. If this is a
> GCL issue, I am hoping that you might be able to understand what this
> problem could be, or perhaps suggest a technique to debug it.  If
> there is anything I can do to provide more information please let me
> know.
> 

Unfortunately, this looks like a gc bug, which really cannot be found
without running under gdb.  Last night I built silver with your patch
and gclcvs compiled with --enable-debug  all the way up to the viewman
stage (I didn't have libXpm.a installed) -- I take it this is past
your problem area above.  Am retrying with more C optimization, but
with -g in place of -fomit-frame-pointer.  Once I can reproduce, I'll
post more.

I take it by 'new' you mean new vis a vis 2.6.8 -- or do you mean not
present in a slightly older 2.7.0?  If so, what are the date bounds?

\start
Date: 02 Aug 2007 14:39:59 -0400
From: Stephen Wilson
To: Ralf Hemmecke
Subject: Re: Continuations in SPAD

Hi Ralf,

Ralf Hemmecke writes:

> > Ralf Hemmecke writes:
> >> Could you demonstrate some SPAD-code-to-be which uses continuations
> >>  and solves a problem that cannot be solved easily by an Aldor
> >> equivalent?
> > I am not to sure what you want me to give. Writing a lot of pseudo
> > code is not terribly useful in all cases.
> 
> No not pseudo code. Define a syntax for continuations in
> SPAD-to-be. And then write real SPAD-to-be code.

Well, for that you might need to wait a while :) I understand the
motivation for asking, but it is not really practical at this point.

[...]
> I am looking for something that would cause me headaches to implement
> in (current) Aldor and which would be easy with continuations. Is must
> be related to implementing mathematics. I don't yet see how useful
> continuations are in a mathematical library context.
> 
> You mentioned parallel execution, but there is also
> http://www.inf.ethz.ch/personal/mannhart/piit/
> http://www.ph.ed.ac.uk/~bj/paraldor/WWW/

Perhaps the following paper would be worth looking at:
   
    www.csd.uwo.ca/~watt/pub/reprints/1995-issac-dynev.pdf

Which gives some of the basic ideas behind continuations, how they can
be implemented and incorporated into Aldor, and gives examples of the
kinds of (non-trivial) algorithms for which continuations are a
natural fit.

I am not really advocating anything new by adopting the notion of
continuations in SPAD.

\start
Date: 02 Aug 2007 16:05:22 -0400
From: Stephen Wilson
To: Camm Maguire
Subject: Re: gclcvs-2.7.0 and Axiom

Camm Maguire writes:

> Greetings!
> 
> Stephen Wilson writes:
> 
> > Hello Camm,
> > 
> > I am interested in your opinion about the following error, which is
> > occurring for me during the compilation of src/algebra/tree.spad:
> > 
> > -------
> >  Error: 
> >  Fast links are on: do (si::use-fast-links nil) for debugging
> >  Signalled by |NEWLOOKUPINADDCHAIN|.
> >  Condition in |newLookupInAddChain| [or a callee]: INTERNAL-SIMPLE-TYPE-ERROR: #<FREE OBJECT 01ce05c8> is not of type FUNCTION: 
> > 
> >  Broken at |NEWLOOKUPINADDCHAIN|.  Type :H for Help.
> >   1 (Continue) Return to top level.
> >  BOOT>>:bt
> > 
> >  #0   newLookupInAddChain {loc0=|empty?|,loc1=((|Boolean|) $),loc2=#<vector 01f8d9f0>,loc3=#<vector 01f8d9...} [ihs=14]
> >  #1   genDeltaEntry {loc0=(|empty?| (#1=(|List| s) (|Boolean|) (|List| s)) (t (elt #1# #))),loc1=(el...} [ihs=13]
> >  #2   compForm3 {loc0=(|empty?| |ls|),loc1=|$EmptyMode|,loc2=(((# # # ...))),loc3=(((#1=# # #) (...} [ihs=12]
> >  #3   compForm {loc0=(|empty?| |ls|),loc1=|$EmptyMode|,loc2=(((# # # ...))),loc3=nil,loc4=speci...} [ihs=11]
> >  #4   setqSingle {loc0=#:g2300,loc1=(|empty?| |ls|),loc2=|NoValueMode|,loc3=(((# # # ...))),loc4=...} [ihs=10]
> >  #5   compSeq1 {loc0=((let #1=#:g2300 (|empty?| |ls|)) (|exit| 1 (if #1# # ...))),loc1=($),loc2...} [ihs=9]
> >  #6   compDefineCapsuleFunction {loc0=(def (|tree| |ls|) (nil nil) ...),loc1=|$EmptyMode|,loc2=(((# # # ...))),l...} [ihs=8]
> >  #7   compCapsuleInner {loc0=((mdef (|cycleTreeMax|) (nil) ...) (qsetrefv $ 7 ...) (|:| |t| $) ...),loc...} [ihs=7]
> >  #8   comp {loc0=(|where| (def (|Tree| s) (# nil) ...) (|:| s (|SetCategory|))),loc1=|$Empt...} [ihs=6]
> >  #9   SpadInterpretStream {loc0=1,loc1=(tim daly ?),loc2=t,loc3=nil,loc4="doc",loc5="spadhelp",loc6="axiom...} [ihs=3]
> >  #10   spad {loc0=|.axiom|,loc1=nil,loc2=nil,loc3=#<synonym stream to *terminal-io*>,loc4=25...} [ihs=2]
> > -------
> > 
> > The function |newLookupInAddChain| is defined in
> > src/interp/nrunfast.boot.pamphlet, and everything appears to be in
> > order on the Axiom side, however:
> > 
> > This is proving to be very difficult to debug, since I cannot
> > reproduce except by starting Axiom and immediately compiling the file.
> > If I do (si::use-fast-links nil) the problem goes away. Attempting to
> > trace any of the above functions, or even typing "1+1" at the axiom
> > prompt before compiling, the problem goes away.
> > 
> > This behavior is new, so I suspect a change in gclcvs. If this is a
> > GCL issue, I am hoping that you might be able to understand what this
> > problem could be, or perhaps suggest a technique to debug it.  If
> > there is anything I can do to provide more information please let me
> > know.
> > 
> 
> Unfortunately, this looks like a gc bug, which really cannot be found
> without running under gdb.  Last night I built silver with your patch
> and gclcvs compiled with --enable-debug  all the way up to the viewman
> stage (I didn't have libXpm.a installed) -- I take it this is past
> your problem area above.  Am retrying with more C optimization, but
> with -g in place of -fomit-frame-pointer.  Once I can reproduce, I'll
> post more.

Yes, the building of viewman is past the point of difficulty.

Appologies for passing around patches.  This is clearly not the most
efficient way to ensure our trees are identical.

I have uploaded a tarball of the current tree I am working with to
axiom-developer.org.  I believe you have an account there? It is
available at:

   /home/swilson/silver-gclcvs.tar.gz
 
Hopefully building off of this tree might yield the problem I am
seeing.  (As with my previous patches, you need gcl-2.7.0 ANSI
pre-built and in your path).

> I take it by 'new' you mean new vis a vis 2.6.8 -- or do you mean not
> present in a slightly older 2.7.0?  If so, what are the date bounds?

This is w.r.t 2.7.0.  I have not been following cvs as closely the
last few weeks as I have in the past but this change seems to have
occurred between the latest commits 2.7.0-78 and 2.7.0-79 (reading from
the debian changelog).

\start
Date: 02 Aug 2007 16:28:06 -0400
From: Camm Maguire
To: Stephen Wilson
Subject: Re: gclcvs-2.7.0 and Axiom

Greetings, and thanks!  Will look at your tree....

Mine just got this, in layer 18:

compiling QUATCAT.spad to QUATCAT.nrlib
copying QUATCAT.nrlib to QUATCAT.o
cp: cannot stat `/fix/t1/camm/axiom/int/algebra/QUATCAT.nrlib/code.o': No such file or directory
make[3]: *** [/fix/t1/camm/axiom/mnt/linux/algebra/QUATCAT.o] Error 1
make[3]: Leaving directory `/fix/t1/camm/axiom/src/algebra'
make[2]: *** [algebradir] Error 2
make[2]: Leaving directory `/fix/t1/camm/axiom/src'
make[1]: *** [srcdir] Error 2
make[1]: Leaving directory `/fix/t1/camm/axiom'
make: *** [all] Error 2

How can I get a reproducible failing sequence of commands from failed
make output?

\start
Date: 02 Aug 2007 16:53:18 -0400
From: Stephen Wilson
To: Camm Maguire
Subject: Re: gclcvs-2.7.0 and Axiom

Camm Maguire writes:

> Greetings, and thanks!  Will look at your tree....

Great!

> Mine just got this, in layer 18:
> 
> compiling QUATCAT.spad to QUATCAT.nrlib
> copying QUATCAT.nrlib to QUATCAT.o
> cp: cannot stat `/fix/t1/camm/axiom/int/algebra/QUATCAT.nrlib/code.o': No such file or directory
> make[3]: *** [/fix/t1/camm/axiom/mnt/linux/algebra/QUATCAT.o] Error 1
> make[3]: Leaving directory `/fix/t1/camm/axiom/src/algebra'
> make[2]: *** [algebradir] Error 2
> make[2]: Leaving directory `/fix/t1/camm/axiom/src'
> make[1]: *** [srcdir] Error 2
> make[1]: Leaving directory `/fix/t1/camm/axiom'
> make: *** [all] Error 2

I do not recall the build failing at this particular point in the
past, but it is further along in the build than I can manage at the
moment (TREE.spad fails at layer 14 IIRC), so at the moment I am at a
loss to provide an explanation.

> How can I get a reproducible failing sequence of commands from failed
> make output?

Unfortunately, there is no way to see the explicit commands issued via
make.  However, when a build command fails, one can look at the file
./obj/tmp/trace which is created afresh after most commands issued via
make, and in general contain the output of the most recently failed
stanza.

In the case of algebra failures, a reasonable way to reproduce the state
is to issue from the root of the build tree:

  DAASE=./src/share ./obj/linux/bin/interpsys

  (1) -> )co ./int/algebra/QUATCAT.spad

This is effectively what the makefile invokes and gives a first hand
look at the failure.

\start
Date: Thu, 2 Aug 2007 22:30:33 -0400
From: Bill Page
To: Stephen Wilson
Subject: Re: Axiom meeting at ISSAC
Cc: Gabriel Dos Reis

Perviously Stephen Wilson wrote:

 | There is also the question of being able to provide the compiler
 | components in the form of a library which can be used by other aspects
 | Axiom.  For example, one would be able to use the new parser and
 | (forthcoming) type checker to support an IDE.

Previously Gabriel Dos Reis wrote:
> People may note that, in Axiom as of today, one can already get the
> syntax tree from both the old and the new parsers, and in fact use the
> parser as a library -- as has been done the algorithmic
> differentiation project.  You don't need to wait for a
> functional new compiler to do that.

On 01 Aug 2007 15:57:14 -0400, Stephen Wilson wrote:

> Can it incrementally parse input as the user is typing, thus making it
> a usable component in an IDE?  Is the AST itself specified?  Does it
> the representation past the lexical analysis phase contain line and
> column number information?  Is the current implementation easily
> modifiable and extensible?
>

On 8/1/07, Gabriel Dos Reis wrote:
>
> Stephen Wilson asked the following questions:
> ...
>   (iii) Does it the representation past the lexical analysis phase contain
>        line and column number information?
> ...
> (iii) of course, the answer is yes.  As I mentioned earlier, there are two
>     parser in Axiom, an old and a new.  You're looking at the old compiler.

On 01 Aug 2007 18:03:08 -0400, Stephen Wilson wrote:

> Of course I am looking at the old compiler, it is the only compiler.

Just so I am clear: Are you saying that there is only one Spad
compiler in Axiom but there are two parsers?

> It accepts one AST, not two.

Do you mean that only one of the two existing parsers can be used with SPAD?

> That AST does not contain line/column information.  The AST which
> Axiom uses does not contain line/column information.

Is there a good reason why it does not use the 2nd parser?

> That information is intentionally erased at one point of parsing or another,
> old or new, it does not matter.
> ...

I hope this is a sufficiently technical issue that it is possible to
reach an agreement. Is it possible now to use "the compiler components
in the form of a library which can be used by other aspects Axiom"? Or
not?

If the answer is yes, then some documentation on how to do this would
be much more useful than having to refer to the source code.

\start
Date: Thu, 2 Aug 2007 21:41:05 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: Axiom meeting at ISSAC

On Thu, 2 Aug 2007, Bill Page wrote:

| > It accepts one AST, not two.
| 
| Do you mean that only one of the two existing parsers can be used with SPAD?

Both parsers are used.  The new parser is used by the interpreter, and the pld
parser is used by the old compiler.  It is also possible to have the new
parser used to compile algebras -- but you would a few function to 
make the connection.  The long term view is to use the new parser 
everywhere.  

(It would be interesting to know why the new compiler was disconnected when
Axiom was made open source).

| > That AST does not contain line/column information.  The AST which
| > Axiom uses does not contain line/column information.
| 
| Is there a good reason why it does not use the 2nd parser?

Nobody has done the connection.

When Jacob originally did the AD project, he used the old AST.  Then, I
rewrote the connection to the front-end so that it uses the new parser.
So we end up with interface to both the interpreter and compiler.

[...]

| I hope this is a sufficiently technical issue that it is possible to
| reach an agreement. Is it possible now to use "the compiler components
| in the form of a library which can be used by other aspects Axiom"?

Not only, it is possible, but it has been done.

| If the answer is yes, then some documentation on how to do this would
| be much more useful than having to refer to the source code.

I fully agree.

\start
Date: Thu, 2 Aug 2007 21:58:53 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: Parser documentation

Bill writes:
>> I hope this is a sufficiently technical issue that it is possible to
>> reach an agreement. Is it possible now to use "the compiler components
>> in the form of a library which can be used by other aspects Axiom"?

Gaby writes:
> Not only, it is possible, but it has been done

Bill writes:
>> If the answer is yes, then some documentation on how to do this would
>> be much more useful than having to refer to the source code.

Gaby writes:
> I fully agree

Documentation! Excellent! Where?

\start
Date: Thu, 2 Aug 2007 22:02:06 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: Parser documentation

On Thu, 2 Aug 2007, Tim Daly wrote:

| Where?

Partly on my development machine, partly in my mind.

We were planning to submit the documentation along with the
algebras -- we developed a typed representation of Spad
programs (In Spad).

\start
Date: Thu, 2 Aug 2007 22:05:03 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: Parser documentation

On Thu, 2 Aug 2007, Tim Daly wrote:

| Gaby writes:
| > I fully agree
| 
| Documentation! Excellent! Where?

I must also note that a subset of Spad is also documented in the
ISSAC paper (Tim, I know you know it, this is just general information).

Andrew -- I'll answer your request by tomorrow.

\start
Date: 03 Aug 2007 01:32:49 -0400
From: Camm Maguire
To: Stephen Wilson
Subject: Re: gclcvs-2.7.0 and Axiom

Greetings!  Just a note -- --enable-debug on axiom-developer.org is
carrying the build past nrunfast.  WIll try with gcc optimization
tomorrow.

\start
Date: Fri, 3 Aug 2007 09:48:05 +0200
From: Juergen Weiss
To: Gabriel Dos Reis, Bill Page
Subject: RE: Axiom meeting at ISSAC

> -----Original Message-----

> (It would be interesting to know why the new compiler was
> disconnected when
> Axiom was made open source).

As far as I know, the ``new compiler'' has been abandoned
around 1990. I think, sources from 1991 did not contain that compiler.
It has never been used in ``production'' even with Scratchpad II.
As a replacement (for the old compiler and the never used new
one) A# was developed (later known as Aldor) -- around 1991 and 1992.
So this was before Axiom became a commercial product by NAG and
long before Axiom became open souce.

\start
Date: Fri, 3 Aug 2007 06:58:47 -0500 (CDT)
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: RE: Axiom meeting at ISSAC

On Fri, 3 Aug 2007, Weiss, Juergen wrote:

| 
| > -----Original Message-----
| >  
| > (It would be interesting to know why the new compiler was 
| > disconnected when
| > Axiom was made open source).
| 
| As far as I know, the ``new compiler'' has been abandoned 
| around 1990. I think, sources from 1991 did not contain that compiler.
| It has never been used in ``production'' even with Scratchpad II.
| As a replacement (for the old compiler and the never used new
| one) A# was developed (later known as Aldor) -- around 1991 and 1992. 
| So this was before Axiom became a commercial product by NAG and
| long before Axiom became open souce.

Many thanks!

\start
Date: 03 Aug 2007 12:40:03 -0400
From: Stephen Wilson
To: Camm Maguire
Subject: Re: gclcvs-2.7.0 and Axiom

Hi Camm,

While debugging, I stumbled across another issue.  One which I hope is
reproducible this time :)


=--- test.lisp ---
(declaim (noinline foo*/bar))
(defun foo*/bar () 'foo)

(defun test () (foo*/bar))
=-----------------


The issue is that the symbol 'foo*/bar prematurely ends comments
emitted within the generated C.


GCL (GNU Common Lisp)  2.7.0 ANSI    Jul 30 2007 16:58:56
Source License: LGPL(gcl,gmp,pargcl), GPL(unexec,bfd,xgcl)
Binary License:  GPL due to GPL'ed components: (XGCL READLINE BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.

Temporary directory for compiler files set to /tmp/

>(compile-file "test.lisp")

;; Compiling test.lisp.
Warning: SIMPLE-WARNING: The declaration specifier NOINLINE is unknown.
Warning: SIMPLE-WARNING: The declaration specifier NOINLINE is unknown.
;; End of Pass 1.  
;; End of Pass 2.  
test.c: In function `LI2__TEST__e_steve_tmp_test':
test.c:10184: error: `BAR' undeclared (first use in this function)
test.c:10184: error: (Each undeclared identifier is reported only once
test.c:10184: error: for each function it appears in.)
test.c:10184: error: syntax error before '/' token
test.c:10184: error: syntax error before ')' token

Correctable error: 
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by COMPILE-FILE.
If continued: Continues anyway.
SIMPLE-ERROR: (SYSTEM "gcc -c -I/usr/X11R6/include -fsigned-char -pipe -Wall   -I/home/steve/local/stow/gclcvs-2.7.0/lib/gcl-2.7.0/unixport/../h  -Os -fomit-frame-pointer -c test.c -o test.o ") returned a non-zero value 0.

Broken at COMPILE-FILE.  Type :H for Help.
 1 (Continue) Continues anyway.
 2 Retry compiling file "test.lisp".
 3 Retry compiling file "test.lisp".
 4 Return to top level.



=--- test.c [snipped] ----

static object LI2__TEST__e_steve_tmp_test()

{        VMB2 VMS2 VMV2
        goto TTL;
TTL:;
        {object V2 = (/* FOO*/BAR */(*LnkLI1)());VMR2
        (V2);}
        return Cnil;
}

=------------------------

\start
Date: 03 Aug 2007 15:03:49 -0400
From: Stephen Wilson
To: axiom-devel <list>
Subject: i-output and decimal width

*,

There was some discussion a while ago about the rounding behaviours of
GCL w.r.t base 10 logarithms, and the impact it has in counting the
number of digits in a radix 10 expansion.

We have the following code in i-output.boot.pamphlet:

   u < MOST_-POSITIVE_-LONG_-FLOAT => 1+negative+FLOOR ((LOG10 u) + 0.0000001)
   -- Rough guess: integer-length returns log2 rounded up, so divide it by
   -- roughly log2(10). This should return an over-estimate, but for objects
   -- this big does it matter?
   FLOOR(INTEGER_-LENGTH(u)/3.3)


Here, u is a positive integer.  The first case which tests against a
bound on most-positive-long-float is almost OK but it adjusts the call
to LOG10 by a small delta which is not enough on some machines.

The final case using integer-length is just not right.  The algorithm
returns an extra `digit' to account for a minus sign, which is missed
by this calculation, and it also returns an over estimation.


Could I suggest the following to replace these two cases:

    (+ 1 |negative| (round (log n 10)))

\start
Date: 03 Aug 2007 15:11:32 -0400
From: Stephen Wilson
To: Stephen Wilson
Subject: Re: i-output and decimal width

Sorry all, 

I meant to save the last message as a draft but bit the wrong key
binding:

Stephen Wilson writes:
> Could I suggest the following to replace these two cases:
> 
>     (+ 1 |negative| (round (log n 10)))


This should _not_ be used to replace both cases, but only the first.
I believe the second case might be OK unless the `over estimation'
is not enough account for the width in the negative case.

However, these messages are now adrift a bit premature, so perhaps
someone may know of a better solution?

\start
Date: Fri, 3 Aug 2007 15:09:53 -0500
From: Tim Daly
To: Stephen Wilson
Subject: i-output and decimal width

Stephen,

A couple questions. 

Where does the problem arise?

Can you show before-and-after examples of the change?

Is computing the log of very large numbers efficient?
(This isn't an issue if we only cover the first case)

Since there are only a few cases might it be cheaper
to compute the length of numbers by range and do
 u < 10 ==> 1
 u < 100 ==> 2
 u < 1000 ==> 3
rather than compute the log?

The change seems quite benign so I don't see any problem.

\start
Date: 03 Aug 2007 16:39:00 -0400
From: Stephen Wilson
To: Tim Daly
Subject: Re: i-output and decimal width

Tim Daly writes:

> Stephen,
> 
> A couple questions. 
> 
> Where does the problem arise?

On my machine, a call to log10:

  (1) -> )lisp (log10 1000)

  Value = 2.9999998211860652

So the delta 0.0000001 is not enough to push the result so that floor
gives the needed result (hence the version I posted which uses round).

> Can you show before-and-after examples of the change?

On my machine:

   (1) -> )lisp (1+ (floor (+ (log10 100) 0.0000001)))

   Value = 2
   (1) -> )lisp (1+ (round (log10 100)))
 
   Value = 3
   (1) -> )lisp (1+ (floor (+ (log10 1000) 0.0000001)))

   Value = 3
   (1) -> )lisp (1+ (round (log10 1000)))

   Value = 4

I believe this is accurate for integers less than
most-positive-long-float.

> 
> Is computing the log of very large numbers efficient?
> (This isn't an issue if we only cover the first case)

It is not so much efficiency as it is concern for overflow in the
intermediate float calculations.

Ideally, we could just call out to mpz_sizeinbase for very large
numbers, but this is not a portable solution. 


> Since there are only a few cases might it be cheaper
> to compute the length of numbers by range and do
>  u < 10 ==> 1
>  u < 100 ==> 2
>  u < 1000 ==> 3
> rather than compute the log?

If efficiency is not a concern, we could just do repeated divisions
and count the iterations.  I think this would be OK.  We could handle
all cases (small or large integers) this way and we would at least get
exact results (which we need in this situation to guide the output
routines).  If this sounds reasonable I could get a patch together
tonight.

\start
Date: Fri, 3 Aug 2007 15:54:55 -0500
From: Tim Daly
To: Stephen Wilson
Subject: i-output and decimal width

A patch seems fine.

\start
Date: Fri, 3 Aug 2007 22:17:14 -0500
From: Tim Daly
To: Camm Maguire
Subject: gmp functions

Can we reach the gmp functions explicitly in gcl?
That is, can I do something like:

(mpz_mod n d) ==> result=n mod d

\start
Date: Sat, 4 Aug 2007 18:45:16 -0500
From: Tim Daly
To: Alasdair McAndrew
Subject: Axiom command in LaTeX documents

I wrote two commands
\spadcommand
\returntype
which handle these kinds of things. These two commands are in
the axiom.sty style file. You can ask Axiom to show output as latex 
)set output tex 
and then just cut-and-paste the result.

\start
Date: Sat, 4 Aug 2007 19:22:57 -0500
From: Tim Daly
To: Alasdair McAndrew
Subject: Axiom command in LaTeX documents

You're welcome to suggest extensions or alternatives.
I'll see what I can do to help.

\start
Date: Sun, 5 Aug 2007 00:19:16 -0500 (CDT)
From: Gabriel Dos Reis
To: list
Subject: $SendXEventToHyperTeX

The global variable $SendXEventToHyperTeX is set twice:

  (1) once as a constant in sockio.lisp.pamphlet

       (defconstant |$SendXEventToHyperTeX| SendXEventToHyperTeX)

  (2) a second time in hypertex.boot.pamphlet

      SETANDFILEQ($SendXEventToHyperTeX, 8)

Once of them must go.  I suggest to remove the definition in
hypertex.boot.pamphlet.

\start
Date: 05 Aug 2007 21:09:34 -0400
From: Stephen Wilson
To: Tim Daly
Subject: Axiom and streams
Cc: Camm Maguire

Tim, *,

One of the non-standard extensions (that is, not defined by the ANSI
Lisp specification) which most Lisp systems offer in one form or
another is a CLOS based stream library.  The most widespread of which
are Gray Streams[1], and a newer design promoted by Franz known as Simple
Streams[2]. 

I am curious of any thoughts about using either of these items or
similar in Axiom as a long term goal. I believe that Axioms
implementation could benefit immensely by adopting one of these
libraries.  The significant advantage is that these are extensible
designs, and provide consistent interfaces for a variety of stream
objects.  For example, reading a character stream backed by a file or
off a network can be handled through single API.

A large drawback is that neither, to my knowledge, have been
implemented atop GCL.  I am seriously considering writing an
implementation.  I have a personal preference for using Simple Streams
as I believe it mostly succeeded in addressing issues with the Gray
Streams model.

Any thoughts on this would be very much appreciated.  Should this be
an aim at all?  Pros/cons between the Gray/Simple stream designs?
Alternative approaches?

Take care,
Steve


[1] http://www.nhplace.com/kent/CL/Issues/stream-definition-by-user.html

[2] http://www.franz.com/support/documentation/6.2/doc/streams.htm

\start
Date: Sun, 5 Aug 2007 21:13:57 -0500
From: Tim Daly
To: Stephen Wilson
Subject: Axiom and streams

You're way ahead of me on the curve on this one. 
I'm unable to use CLOS until Axiom lives under ANSI.

That said, I do see the long term advantage of taking streams
from various places using a common API. A networked version of
Axiom, a browser-based version of Axiom (something I've looked at),
a wxAxiom (using wxMaxima codebase, which I've looked at), doing
bi-directional graphics control, etc could all benefit.

I have no opinion on either path and will follow your lead on this.

\start
Date: Sun, 5 Aug 2007 21:07:30 -0700 (PDT)
From: Cliff Yapp
To: Stephen Wilson, Tim Daly
Subject: Re: Axiom and streams
Cc: Camm Maguire

--- Stephen Wilson wrote:
 
> A large drawback is that neither, to my knowledge, have been
> implemented atop GCL.  I am seriously considering writing an
> implementation.  I have a personal preference for using Simple
> Streams as I believe it mostly succeeded in addressing issues
> with the Gray Streams model.

Steve, I'm with Tim on this one - I will follow your lead.

> Any thoughts on this would be very much appreciated.  Should this be
> an aim at all?  Pros/cons between the Gray/Simple stream designs?
> Alternative approaches?

Probably either Gray or Simple streams will be better than rolling our
own, unless maybe we can make a "best of both" setup.

Concerns that pop into my head, in no particular order:

1)  The copyright statement on the Allegro simple streams documentation
doesn't seem to have anything that gives permission for any use, and I
assume the Simple Streams code is present only in Allegro at the
moment.  Would it be worthwhile to contact Franz and see if they would
consider making the Simple Streams code part of their open source
effort?  Re-doing a simple streams library for generic CL would require
redoing both documentation and code, as it stands now.

2)  Are there libraries out there using gray streams that we would be
interesting in using and need to convert to simple streams?  If so, how
hard would that be?

3)  Would such a library implemented for GCL need to be GCL specific,
or could it rest atop ANSI CL?

Cheers, and thanks for looking into this!

\start
Date: Mon, 6 Aug 2007 14:23:17 +1000
From: Alasdair McAndrew
To: list
Subject: Axiom under Mac OS X?

There's instructions for building Axiom on Mac OS X at

http://wiki.axiom-developer.org/BuildAxiom

Are these instructions current?  I have a student who would like to
use Axiom on Mac OS X, and would prefer a native version, rather than
a windows or linux version running in an emulator.

\start
Date: 06 Aug 2007 12:36:40 -0400
From: Stephen Wilson
To: Tim Daly
Subject: Re: i-output and decimal width

The following patch fixes the i-output issue.  I figured the best
approach would be to write a utility function, digits-by-radix, which
allows one to determine the width of an integer given any radix.  It
attempts to be reasonably efficient. I added this function to
vmlisp.lisp.pamphlet.

--=-=-=

diff --git a/changelog b/changelog
index 962132e..4c80778 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,6 @@
+20070805 sxw src/interp/i-output.boot use digits-by-radix
+20070805 sxw src/interp/sys-pkg.lisp add digits-by-radix export
+20070805 sxw src/interp/vmlisp.lisp add digits-by-radix function
 20070722 tpd src/interp/Makefile cleanup latex warnings
 20070721 wxh src/interp/spad.lisp make evalSharpOne declare arg specials
 20070721 tpd src/interp/setq.lisp update contributor name list
diff --git a/src/interp/i-output.boot.pamphlet b/src/interp/i-output.boot.pamphlet
index 10cd956..97ef9b1 100644
--- a/src/interp/i-output.boot.pamphlet
+++ b/src/interp/i-output.boot.pamphlet
@@ -9,25 +9,6 @@
 \eject
 \tableofcontents
 \eject
-\section{GCL\_log10\_bug}
-In some versions of GCL the LOG10 function returns improperly rounded values.
-The symptom is:
-\begin{verbatim}
-(24) -> [1000]
-   (24)  [100]
-\end{verbatim}
-The common lisp failure can be shown with:
-\begin{verbatim}
-(25) -> )lisp (log10 1000)
-Value = 2.9999999999999996
-\end{verbatim}
-This previous boot code was:
-\begin{verbatim}
-    u < MOST_-POSITIVE_-LONG_-FLOAT => 1+negative+FLOOR LOG10 u
-\end{verbatim}
-and should be restored when the GCL bug is fixed.
-<<GCLlog10bug>>=
-    u < MOST_-POSITIVE_-LONG_-FLOAT => 1+negative+FLOOR ((LOG10 u) + 0.0000001)
 @ 
 \section{License}
 <<license>>=
@@ -887,18 +868,12 @@ WIDTH u ==
     u.0="%" and ((u.1 = char 'b) or (u.1 = char 'd)) => 1
     #u
   INTEGERP u => 
+    u = 0 => 1
     if (u < 1) then 
       negative := 1
-      u := -u
     else
       negative := 0
-    -- Try and be fairly exact for smallish integers:
-    u = 0 => 1
-<<GCLlog10bug>>
-    -- Rough guess: integer-length returns log2 rounded up, so divide it by
-    -- roughly log2(10). This should return an over-estimate, but for objects
-    -- this big does it matter?
-    FLOOR(INTEGER_-LENGTH(u)/3.3)
+    DIGITS_-BY_-RADIX(u, 10) + negative
   atom u => # atom2String u
   putWidth u is [[.,:n],:.] => n
   THROW('outputFailure,'outputFailure)
diff --git a/src/interp/sys-pkg.lisp.pamphlet b/src/interp/sys-pkg.lisp.pamphlet
index 850237d..4801566 100644
--- a/src/interp/sys-pkg.lisp.pamphlet
+++ b/src/interp/sys-pkg.lisp.pamphlet
@@ -337,7 +337,7 @@ provides support for compiler code.
 <<GCL.DEFINE-MACRO>>
 <<GCL.MEMQ>>
 <<GCL.PNAME>>
-         VMLISP::PUT
+         VMLISP::PUT VMLISP::DIGITS-BY-RADIX
 	 VMLISP::QVELT-1 VMLISP::QSETVELT-1 vmlisp::throw-protect
 	 VMLISP::|directoryp| VMLISP::EQCAR
 	 VMLISP::DEFIOSTREAM VMLISP::RDEFIOSTREAM VMLISP::MLAMBDA
diff --git a/src/interp/vmlisp.lisp.pamphlet b/src/interp/vmlisp.lisp.pamphlet
index 7247d7a..2478e04 100644
--- a/src/interp/vmlisp.lisp.pamphlet
+++ b/src/interp/vmlisp.lisp.pamphlet
@@ -95,6 +95,62 @@ Contributed by Juergen Weiss.
 (defun get-current-directory ()
   (namestring (truename "")))
 
+@ 
+\section{The digits-by-radix function} 
+The purpose of the following function is to calculate the number of
+digits in the radix $B$ expansion of an arbitrary Lisp integer $n$.
+The width of an integer can be determined rapidly when the radix is a
+power of two, otherwise an approach based on successive divisions is
+used.
+
+<<digits-by-radix>>=
+(defun digits-by-radix (n &optional (radix 10))
+  (flet (<<power-of-two-width>>
+         <<iterative-width>>)
+    (assert (>= radix 2) (radix) 
+            "Bad radix ~D < 2 given to DIGITS-BY-RADIX." radix)
+    (setq n (abs n))
+    (cond
+      ((zerop n) (values 1))
+      ((zerop (logand radix (1- radix))) (power-of-two-width n radix))
+      (t (iterative-width n radix)))))
+
+@ When the radix $B$ is of the form $2^b$, $b$ bits are needed to
+represent one radix $B$ digit. The radix $B$ width of $n$ is obtained
+by dividing the width of the binary representation of $n$ by $b$, and
+incrementing the result when the remainder is non-zero.
+
+<<power-of-two-width>>=
+ (power-of-two-width (n radix)
+   (let ((bits (integer-length n))
+         (radix-bits (1- (integer-length radix))))
+     (multiple-value-bind (quo rem) (floor bits radix-bits)
+       (if (zerop rem) quo (1+ quo)))))
+
+@ When the radix is not a power of two, we choose a power $p$ of the
+radix $B$ and use $B^p$ as a divisor.  Each division counts as $p$
+digits in the radix $B$ expansion.  The power, bound to the variable
+[[digits]] below, is chosen so that $B^p <$
+\texttt{most-positive-long-float}. This allows use of [[log]] to
+compute $p$ without concern for floating point overflow.  Once a
+quotient is produced which is smaller than the divisor, we complete
+the calculation by repeated divisions using the radix itself.
+
+<<iterative-width>>=
+ (iterative-width (n radix)
+   (multiple-value-bind (q width)
+       (let* ((target (if (< n most-positive-long-float)
+                          (values n)
+                          (values most-positive-long-float)))
+              (digits (let ((d (floor (log target radix))))
+                        (if (zerop d) 1 d)))
+              (div (expt radix digits)))
+         (loop for q = n then (floor q div)
+               until (< q div) sum digits into width
+               finally (return (values q width))))
+     (+ width (loop for r = q then (floor r radix)
+                    until (zerop r) count t))))
+
 @
 \section{License}
 <<license>>=
@@ -133,6 +189,7 @@ Contributed by Juergen Weiss.
 <<*>>=
 <<license>>
 
+
 ;      VM LISP EMULATION PACKAGE
 ;      Lars Ericson, Barry Trager, Martial Schor, tim daly, LVMCL, et al
 ;      IBM Thomas J. Watson Research Center
@@ -945,6 +1002,8 @@ Contributed by Juergen Weiss.
 
 ; 12.0 Operations on Numbers
 
+<<digits-by-radix>>
+
 ; 12.1 Conversion
 
 (define-function 'FIX #'truncate)

--=-=-=--

\start
Date: 06 Aug 2007 13:10:18 -0400
From: Stephen Wilson
To: Cliff Yapp
Subject: Re: Axiom and streams
Cc: Camm Maguire

Cliff Yapp writes:

> --- Stephen Wilson wrote:
>  
> > A large drawback is that neither, to my knowledge, have been
> > implemented atop GCL.  I am seriously considering writing an
> > implementation.  I have a personal preference for using Simple
> > Streams as I believe it mostly succeeded in addressing issues
> > with the Gray Streams model.
> 
> Steve, I'm with Tim on this one - I will follow your lead.

OK.  Even though I have a leaning towards Simple streams, there are
many issues involved which will take time to understand.  I'll write a
few of my thoughts below.

For now, the simplest route would likely be to get Gray Streams
working under GCL.  When I wrote that I am "considering writing an
implementation" I should of said "considering porting ...".  The Gray
streams which SBCL uses (public domain) should be fairly easy to port.
I think such work would be of interest to GCL since many applications
use Gray streams.

[...]
> Concerns that pop into my head, in no particular order:
> 
> 1)  The copyright statement on the Allegro simple streams documentation
> doesn't seem to have anything that gives permission for any use, and I
> assume the Simple Streams code is present only in Allegro at the
> moment.  Would it be worthwhile to contact Franz and see if they would
> consider making the Simple Streams code part of their open source
> effort?  Re-doing a simple streams library for generic CL would require
> redoing both documentation and code, as it stands now.

SBCL also has a Simple streams implementation, but the README says it
is still alpha quality code.  Of course, some open code is better than
no code.

Unlike Gray streams, I do not think the Simple streams document was
intended to be used as a defacto `standard' which other implementers
should follow to the letter.  I view the document as a good
specification to work from in order to provide a decent library for
Axiom to use.  My inclination is to borrow from the document and
provide a library developed with Axiom in mind -- the literate
implementation I am sure would be quite different.

> 2)  Are there libraries out there using gray streams that we would be
> interesting in using and need to convert to simple streams?  If so, how
> hard would that be?

There are certainly lots of libs using Gray streams -- far more, I
think, than Simple streams.  As far as what libraries are interesting
to Axiom, and how they are to be integrated into the system, I do not
really know yet.  Porting issues too.  Its tough to make general
statements that attempt to be accurate.

On the other hand, we certainly can provide compatibility layers
between Axiom internals and other libraries when necessary.

> 3)  Would such a library implemented for GCL need to be GCL specific,
> or could it rest atop ANSI CL?

For Gray streams one needs to integrate the root of the class
hierarchy into Lisps built-in type system and redefine a handful of CL
functions as methods.  So this is not strictly portable, but the
issues are fairly minor.

Similar issues are involved with implementing Simple streams, but as
mentioned above, I think of Simple streams as motivation for an Axiom
specific library.  Even though Allegro defines the API in a way which
requires a system-level implementation I do not think we must bind
ourselves to those details.  It will take more thought and experiment,
but my hope would be to leverage a GCL Gray streams package as well as
our own extensions.  Some extensions -- for example a stream for
network connections -- demand system specific code.  But the main
point is to have a generic interface which abstracts these details
away.  We can port the interface to other Lisps if needed.

I will start on getting some preliminary work done.  Any more
questions/thoughts would be greatly appreciated.

\start
Date: Mon, 6 Aug 2007 10:29:17 -0700 (PDT)
From: Cliff Yapp
To: Stephen Wilson
Subject: Re: Axiom and streams
Cc: Camm Maguire

--- Stephen Wilson wrote:

> I will start on getting some preliminary work done.  Any more
> questions/thoughts would be greatly appreciated.

Not a particularly useful question, but I am curious - how serious is
the collision conceptually between Gray Streams and Simple Streams?  Is
one a special case of the other, for example?  (I.e. could Simple
Streams be regarded as a special case layer on top of Gray Streams, or
doesn't that make sense?)

\start
Date: Mon, 6 Aug 2007 13:31:26 -0400
From: Bill Page
To: Alasdair McAndrew
Subject: Re: Axiom under Mac OS X?

On 8/6/07, Alasdair McAndrew wrote:
> There's instructions for building Axiom on Mac OS X at
>
> http://wiki.axiom-developer.org/BuildAxiom
>
> Are these instructions current?  I have a student who would like to
> use Axiom on Mac OS X, and would prefer a native version, rather than
> a windows or linux version running in an emulator.
>

No they are not particularly current (> 1 year). They are waiting for
someone to try this build again and update the instructions. Certainly
you must use either build-improvements or wh-sandbox (has better
support for HyperDoc). Please let us know about any problem you
encounter.

In the near future I will also be testing the build of FriCAS on Mac
OS X as part of the new version of axiom4sage.

\start
Date: 06 Aug 2007 13:02:50 -0500
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: Axiom under Mac OS X?

Bill Page writes:

[...]

| In the near future I will also be testing the build of FriCAS on Mac
| OS X as part of the new version of axiom4sage.

Bill --

  I've made some recent changes to build-improvements; please, could
try a build as of today and send me report?

  Semester start is nearing and I need to get things in a state where
I could just tell students "go to Axiom website, download, and build
with configure && make && make install".

\start
Date: 06 Aug 2007 14:48:22 -0400
From: Stephen Wilson
To: Cliff Yapp
Subject: Re: Axiom and streams
Cc: Camm Maguire


Cliff Yapp writes:
> Not a particularly useful question, but I am curious - how serious is
> the collision conceptually between Gray Streams and Simple Streams?  Is
> one a special case of the other, for example?  (I.e. could Simple
> Streams be regarded as a special case layer on top of Gray Streams, or
> doesn't that make sense?)

I think they take different approaches, where both have advantages and
disadvantages in certain applications.  For example, I think Simple
streams have a good interface for dealing with common byte-based
operations like reading files, compressed data, encrypted bits, etc.
Gray streams take more of an abstract approach, so that a stream of
objects, say, being sent to a graphics engine for display, fits better
in the Gray streams model IMHO.

You might be able to define one in terms of the other, but then you
would not have a `true' Gray stream or Simple stream implementation,
as both define what the fundamental objects are and how they interact
with ANSI lisps stream substrate.  What would result, I think, is a
`best of both worlds' model.

Some interesting comments were made about the issues involved here:

 http://common-lisp.net/pipermail/streams-standard-discuss/2004-September.txt

\start
Date: Mon, 6 Aug 2007 12:13:39 -0700 (PDT)
From: Cliff Yapp
To: Stephen Wilson
Subject: Re: Axiom and streams
Cc: Camm Maguire

--- Stephen Wilson wrote:

> I think they take different approaches, where both have advantages
> and disadvantages in certain applications.  For example, I think
> Simple streams have a good interface for dealing with common byte-
> based operations like reading files, compressed data, encrypted
> bits, etc. Gray streams take more of an abstract approach, so that a
> stream of objects, say, being sent to a graphics engine for display,
> fits better in the Gray streams model IMHO.

Hmm.  Are they mutually exclusive?  Perhaps it would be useful to have
both available, as I can see both byte-based operations and abstract
objects being of interest.

I'm guessing at the current stage the Simple Streams approach would be
more useful, and later on the more abstract objects will become
interesting.

> You might be able to define one in terms of the other, but then you
> would not have a `true' Gray stream or Simple stream implementation,
> as both define what the fundamental objects are and how they interact
> with ANSI lisps stream substrate.  What would result, I think, is a
> `best of both worlds' model.

Hmm.  If possible, that might not be bad.  Sounds like it might not be
so simple though...

> Some interesting comments were made about the issues involved here:
> 
> 
>
http://common-lisp.net/pipermail/streams-standard-discuss/2004-September.txt

Good find - I'll take a look at that.  Thanks!

\start
Date: Mon, 6 Aug 2007 21:44:18 +0200 (CEST)
From: Waldek Hebisch
To: Gabriel Dos Reis
Subject: Re: sequence

> Gabriel Dos Reis writes:
> 
> | When compiling with an ANSI common lisp compiler, the use of "sequence"
> | in src/interp/parsing.lisp is resoled as referring to the standard symbol
> | sequence, which belongs to locked standard packages.  I would suggest
> | to rename it to rule-sequence, and propagate the change down to the
> | parser.
> 
> similarly, "count" from the same file conflicts with standard count.
> 

"count" is unused and I removed it from wh-sandbox.  It looks also
that "sequence" is unused, but no Lisp implementation I use
obected to it (they barfed on "count") so I did not notice it.

\start
Date: Mon, 6 Aug 2007 14:51:12 -0500 (CDT)
From: Gabriel Dos Reis
To: Waldek Hebisch
Subject: Re: sequence

On Mon, 6 Aug 2007, Waldek Hebisch wrote:

| > Gabriel Dos Reis writes:
| > 
| > | When compiling with an ANSI common lisp compiler, the use of "sequence"
| > | in src/interp/parsing.lisp is resoled as referring to the standard symbol
| > | sequence, which belongs to locked standard packages.  I would suggest
| > | to rename it to rule-sequence, and propagate the change down to the
| > | parser.
| > 
| > similarly, "count" from the same file conflicts with standard count.
| > 
| 
| "count" is unused and I removed it from wh-sandbox.  It looks also
| that "sequence" is unused, but no Lisp implementation I use
| obected to it (they barfed on "count") so I did not notice it.

I was under the impression that Sequence was used by the "New meta"
parser generator; but after further inspection I believe you're right:
It is unused junk.

SBCL complained about modification to locked package COMMON-LISP when it sees
sequence's definition -- the conditions I ran into that were that I was trying
to get all lisp codes compiled (that is needed for ECL).

\start
Date: Mon, 6 Aug 2007 21:56:26 +0200 (CEST)
From: Waldek Hebisch
To: Stephen Wilson
Subject: Re: i-output and decimal width

Stephen Wilson wrote:
> Stephen Wilson writes:
> > Could I suggest the following to replace these two cases:
> > 
> >     (+ 1 |negative| (round (log n 10)))
> 
> 
> This should _not_ be used to replace both cases, but only the first.
> I believe the second case might be OK unless the `over estimation'
> is not enough account for the width in the negative case.
> 
> However, these messages are now adrift a bit premature, so perhaps
> someone may know of a better solution?
> 

I looked at this code and I belive that I have written a better
version (commited to wh-sandbox).  Some remarks:

- Ansi says that for exact arguments results are either exact or
  single precision.  I feel that single precision give us no
  help so I use double precision arguments (as type gcl does not
  distingiush between single and double, but it stil gave only
  single precision result).
- for moderate lengths if numerical result is suspect I use
  extra verification.
- for large arguments I use over-estimate. 

\start
Date: Mon, 6 Aug 2007 22:11:51 +0200 (CEST)
From: Waldek Hebisch
To: Gabriel Dos Reis
Subject: Re: $SendXEventToHyperTeX

Gabriel Dos Reis wrote:
> 
> The global variable $SendXEventToHyperTeX is set twice:
> 
>   (1) once as a constant in sockio.lisp.pamphlet
> 
>        (defconstant |$SendXEventToHyperTeX| SendXEventToHyperTeX)
> 
>   (2) a second time in hypertex.boot.pamphlet
> 
>       SETANDFILEQ($SendXEventToHyperTeX, 8)
> 
> Once of them must go.  I suggest to remove the definition in
> hypertex.boot.pamphlet.
> 

We should remove version in hypertex.boot.pamphlet.  However,
AFAICS $SendXEventToHyperTeX and SendXEventToHyperTeX is unused
so we could also remove both.

\start
Date: Mon, 6 Aug 2007 22:20:22 +0200 (CEST)
From: Waldek Hebisch
To: Gabriel Dos Reis
Subject: Re: LastCxArg

Gabriel Dos Reis wrote:
> 
> It looks to me that the variable $LastCxArg in the routine
> /foobar from src/interp/spad.lisp is a type for |$LastCxArg|.
> 

This rotine (and several others nearby) is probably junk.
It looks like debugging helper that got bitrotten and is
useless now.

\start
Date: 06 Aug 2007 16:37:35 -0400
From: Stephen Wilson
To: Cliff Yapp
Subject: Re: Axiom and streams
Cc: Camm Maguire

Cliff Yapp writes:
> Are they mutually exclusive?  

In a sense, yes.  Take a look at the Simple streams doc and see how
the traditional common lisp functions are redefined to support both
approaches. The starting point would probably be here:

 http://www.franz.com/support/documentation/6.2/doc/streams.htm#cl-funs-2

> Perhaps it would be useful to have both available, as I can see both
> byte-based operations and abstract objects being of interest.

One of the main advantages of Simple streams is that they do not
require a call through a generic function to do things like read-char,
write-byte, etc.  Its not that Gray streams cant do these things, its
just that the interface is somewhat heavy.

> I'm guessing at the current stage the Simple Streams approach would be
> more useful, and later on the more abstract objects will become
> interesting.

I tend to agree.  I ported the SBCL Gray streams code over to GCL this
morning in the form of a user library (that is, its not redefining CL
functions or sub-classing CL's stream type -- its portable code similar
to Corman Lisps implementation).  Next will be to attempt the same
with SBCL's Simple stream implementation.  Once both portable versions
are running I can look at how they can be embedded in GCL so as to
take advantage of implementation specifics.  Hopefully a lot of the
details, pros/cons, etc, will become clear by taking that approach.  

\start
Date: Mon, 6 Aug 2007 17:17:55 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: Axiom under Mac OS X?

On 06 Aug 2007 13:02:50 -0500, Gabriel Dos Reis wrote:
> Bill Page writes:
>
> [...]
>
> | In the near future I will also be testing the build of FriCAS on Mac
> | OS X as part of the new version of axiom4sage.
>
> Bill --
>
>   I've made some recent changes to build-improvements; please, could
> try a build as of today and send me report?
>
>   Semester start is nearing and I need to get things in a state where
> I could just tell students "go to Axiom website, download, and build
> with configure && make && make install".
>

Sorry. I don't own an Mac so I can't do this right away. However the
Sage project has offered to given me remote access to a Mac sometime
in the next few days to test the new axiom4sage package. I will let
you know as soon as I have done this.

\start
Date: 06 Aug 2007 17:33:10 -0400
From: Camm Maguire
To: Tim Daly
Subject: Re: gmp functions

Greetings!  Not yet, but I have been meaning to do this for some time,
and this may provide the needed impetus.  It is really quite simple,
but cannot be achieved via the generic external shared library
interface described previously, due to the need to wrap the gmp
function calls to protect their relocatable memory allocation.

(At some point, maybe someone knowledgeable could describe to me a
better malloc like algorithm for the unmoveable contiguous GCL memory
space.  Right now we use a linked list sorted by block size -- this is
the slowest type of memory GCL maintains.)

I'll try to put in a GMP package soon and post when done.

Take care,

Tim Daly writes:

> Camm,
> 
> Can we reach the gmp functions explicitly in gcl?
> That is, can I do something like:
> 
> (mpz_mod n d) ==> result=n mod d

\start
Date: Tue, 7 Aug 2007 07:48:15 +1000
From: Alasdair McAndrew
To: Bill Page, list
Subject: Re: Axiom under Mac OS X?

I have asked my student to try installing wh-sandbox, and to keep a
record of how he does it.  If he's successful, I'll let you know.  If
he's unsuccessful, I'll ask here again!

Thanks,
Alasdair

On 8/7/07, Bill Page wrote:
> On 06 Aug 2007 13:02:50 -0500, Gabriel Dos Reis wrote:
> > Bill Page writes:
> >
> > [...]
> >
> > | In the near future I will also be testing the build of FriCAS on Mac
> > | OS X as part of the new version of axiom4sage.
> >
> > Bill --
> >
> >   I've made some recent changes to build-improvements; please, could
> > try a build as of today and send me report?
> >
> >   Semester start is nearing and I need to get things in a state where
> > I could just tell students "go to Axiom website, download, and build
> > with configure && make && make install".
> >
>
> Sorry. I don't own an Mac so I can't do this right away. However the
> Sage project has offered to given me remote access to a Mac sometime
> in the next few days to test the new axiom4sage package. I will let
> you know as soon as I have done this.

\start
Date: 06 Aug 2007 18:13:38 -0400
From: Camm Maguire
To: Tim Daly
Subject: Re: gmp functions

Just checking -- all that is of interest are the mpz functions, right?
(please see gmp docs if this does not make sense.)

Take care,

Tim Daly writes:

> Camm,
> 
> Can we reach the gmp functions explicitly in gcl?
> That is, can I do something like:
> 
> (mpz_mod n d) ==> result=n mod d

\start
Date: 06 Aug 2007 18:17:21 -0400
From: Camm Maguire
To: Stephen Wilson
Subject: Re: Axiom and streams

Greetings!  This stuff sounds great, and likely can be included in the
gcl distribution proper even though it is an ansi extension.  I think
slime depends on gray streams, right?  That would be reason enough.
But perhaps support should be in the form of an autoloadable module.

Take care,

Stephen Wilson writes:

> Cliff Yapp writes:
> > Are they mutually exclusive?  
> 
> In a sense, yes.  Take a look at the Simple streams doc and see how
> the traditional common lisp functions are redefined to support both
> approaches. The starting point would probably be here:
> 
>  http://www.franz.com/support/documentation/6.2/doc/streams.htm#cl-funs-2
> 
> > Perhaps it would be useful to have both available, as I can see both
> > byte-based operations and abstract objects being of interest.
> 
> One of the main advantages of Simple streams is that they do not
> require a call through a generic function to do things like read-char,
> write-byte, etc.  Its not that Gray streams cant do these things, its
> just that the interface is somewhat heavy.
> 
> > I'm guessing at the current stage the Simple Streams approach would be
> > more useful, and later on the more abstract objects will become
> > interesting.
> 
> I tend to agree.  I ported the SBCL Gray streams code over to GCL this
> morning in the form of a user library (that is, its not redefining CL
> functions or sub-classing CL's stream type -- its portable code similar
> to Corman Lisps implementation).  Next will be to attempt the same
> with SBCL's Simple stream implementation.  Once both portable versions
> are running I can look at how they can be embedded in GCL so as to
> take advantage of implementation specifics.  Hopefully a lot of the
> details, pros/cons, etc, will become clear by taking that approach.  
> 

\start
Date: 06 Aug 2007 18:25:55 -0400
From: Stephen Wilson
To: Waldek Hebisch
Subject: Re: i-output and decimal width

Hi Waldek,

Waldek Hebisch writes:

> Stephen Wilson wrote:
> > Stephen Wilson writes:
> > > Could I suggest the following to replace these two cases:
> > > 
> > >     (+ 1 |negative| (round (log n 10)))
> > 
> > 
> > This should _not_ be used to replace both cases, but only the first.
> > I believe the second case might be OK unless the `over estimation'
> > is not enough account for the width in the negative case.
> > 
> > However, these messages are now adrift a bit premature, so perhaps
> > someone may know of a better solution?
> > 
> 
> I looked at this code and I belive that I have written a better
> version (commited to wh-sandbox).  Some remarks:
> 
> - Ansi says that for exact arguments results are either exact or
>   single precision.  I feel that single precision give us no
>   help so I use double precision arguments (as type gcl does not
>   distingiush between single and double, but it stil gave only
>   single precision result).
> - for moderate lengths if numerical result is suspect I use
>   extra verification.
> - for large arguments I use over-estimate. 

I think a log10 function like the one you implemented would certainly
be useful.  A few questions:

  - Has the code been tested on various lisps?  I see the following
    under gcl-2.7.0 for example:

       (|axiom_log_10| 10) ==> 0

  - Would you be willing to submit a patch with pamphlet
    documentation?

We could use your log10 function to optimize the base 10 case.  I
would also like to look into using mpz_sizeinbase as a more general
solution. Currently, exact calculation becomes slow when there are
more than 100000 decimal digits -- this is a fairly practical range
for the pretty printing of expressions, so there is not urgent need to
optimize IMHO.

\start
Date: 06 Aug 2007 19:07:44 -0400
From: Stephen Wilson
To: Camm Maguire
Subject: Re: Axiom and streams

Camm Maguire writes:

> Greetings!  This stuff sounds great, and likely can be included in the
> gcl distribution proper even though it is an ansi extension.  I think
> slime depends on gray streams, right?  That would be reason enough.
> But perhaps support should be in the form of an autoloadable module.

OK.  Thats great you support this!  

Yes, Slime requires Gray streams to the best of my knowledge.

The main implementation specific bit is to connect
'fundamental-stream, the root of the Gray stream hierarchy, into the
CL type system.  We need to have both 'cl:stream and
'cl:standard-object as superclasses, so this might need to be done at
the PCL level.

An autoloadable module would be ideal, for at that time further
extensions to the CL name space could be made (we would need to
redefine cl:close, cl:streamp, and a few others, as generic
functions).

I will see what I can come up with and hopefully provide an initial
proposal for GCL.

Thanks,
Steve


> 
> Take care,
> 
> Stephen Wilson writes:
> 
> > Cliff Yapp writes:
> > > Are they mutually exclusive?  
> > 
> > In a sense, yes.  Take a look at the Simple streams doc and see how
> > the traditional common lisp functions are redefined to support both
> > approaches. The starting point would probably be here:
> > 
> >  http://www.franz.com/support/documentation/6.2/doc/streams.htm#cl-funs-2
> > 
> > > Perhaps it would be useful to have both available, as I can see both
> > > byte-based operations and abstract objects being of interest.
> > 
> > One of the main advantages of Simple streams is that they do not
> > require a call through a generic function to do things like read-char,
> > write-byte, etc.  Its not that Gray streams cant do these things, its
> > just that the interface is somewhat heavy.
> > 
> > > I'm guessing at the current stage the Simple Streams approach would be
> > > more useful, and later on the more abstract objects will become
> > > interesting.
> > 
> > I tend to agree.  I ported the SBCL Gray streams code over to GCL this
> > morning in the form of a user library (that is, its not redefining CL
> > functions or sub-classing CL's stream type -- its portable code similar
> > to Corman Lisps implementation).  Next will be to attempt the same
> > with SBCL's Simple stream implementation.  Once both portable versions
> > are running I can look at how they can be embedded in GCL so as to
> > take advantage of implementation specifics.  Hopefully a lot of the
> > details, pros/cons, etc, will become clear by taking that approach.  

\start
Date: 06 Aug 2007 22:40:18 -0400
From: Stephen Wilson
To: Camm Maguire
Subject: Re: gclcvs-2.7.0 and Axiom

Camm,

A quick update on this issue.  

I have tried compiling with --enable-debug on my main machine, and
have tried both with and without --enable-debug on a second box.
Unfortunately, I cannot reproduce the failure under any of these
conditions.

I can work around the issue locally, and if this does represent a gc
problem hopefully a better opportunity will present itself to debug
the condition.

FYI, the patch-set I have been working on now allows Silver to build
to completion with only one failure in Axioms test-suite.  We are very
close to getting Axiom working without issue atop gcl-2.7.0.

Many thanks for all your help with this!

Sincerely,
Steve

Camm Maguire writes:

> Greetings!  Just a note -- --enable-debug on axiom-developer.org is
> carrying the build past nrunfast.  WIll try with gcc optimization
> tomorrow.

\start
Date: Tue, 07 Aug 2007 15:12:49 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Unsuccessful build-improvements

Hi Gaby,

I am unlucky for some reason.

woodpecker:~/SVK/axiom/branches/build-improvements>svk info
Checkout Path: /home/hemmecke/SVK/axiom/branches/build-improvements
Depot Path: /mirror/axiom/branches/build-improvements
Revision: 779
Last Changed Rev.: 779
Mirrored From: https://axiom.svn.sourceforge.net/svnroot/axiom, Rev. 695
Copied From: /axiom/trunk/axiom, Rev. 33
Merged From: /axiom/trunk/axiom, Rev. 33

woodpecker:~/OTHER/Axiom/out-of-source-build-improvements> 
~/SVK/axiom/branches/build-improvements/configure 
--prefix=/home/hemmecke/scratch/AXIOM
woodpecker:~/OTHER/Axiom/out-of-source-build-improvements> 
date>TIME;make|tee rhx.log;date>>TIME

The last thing I see on my screen is given at the end. The rest you find at

http://portal.axiom-developer.org/Members/hemmecke/build-improvements/rhx.log/file_view

If you need more information, just ask.

BTW, /home/hemmecke/config/emacs is actually supposed to be my .emacs 
file, but in fact it is unused. I have no idea why the build machinary 
wants to write anything outside /home/hemmecke/scratch/AXIOM or 
~/OTHER/Axiom/out-of-source-build-improvements. Any ideas?

I must say, I find this quite scary that something accesses anything 
that I did not specify.


Ralf

===================================================================


GCL (GNU Common Lisp)  2.6.8 CLtL1    Aug  7 2007 14:51:20
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License:  GPL due to GPL'ed components: (BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/

 >
NIL

 >if [ -e "unixport/rsym" ] ; then cp unixport/rsym 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/unixport/ 
; fi
if [ -d "" ] ; then  \
         cat gcl-tk/gcltksrv | \
         sed -e 
"s!GCL_TK_DIR=.*!GCL_TK_DIR=/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/gcl-tk!g" 
  \
         -e "s!TK_LIBRARY=.*!TK_LIBRARY=!g" > \
 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/gcl-tk/gcltksrv 
; \
         chmod a+x 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/gcl-tk/gcltksrv 
; fi
if test 
"/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp/" 
!= "" ; then (cd elisp ; make install DESTDIR=) ; fi
make[3]: Entering directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl/elisp'
mkdir -p 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp/
cp *.el 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp/
if [ "./configure: line 6354: /home/hemmecke/config/emacs: Permission 
denied" != "" ] ; then \
         if test -f "./configure: line 6354: 
/home/hemmecke/config/emacs: Permission denied" ; then \
         cat ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied | sed -e '/BEGIN gcl/,/END gcl/d' > 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
; \
         mv ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied.prev ; \
           rm -f  ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission deniedc ; \
           cat add-default.el >> 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
; cp 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
./configure: line 6354: /home/hemmecke/config/emacs: Permission denied ; \
           rm -f 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
; else \
         cp  add-default.el ./configure: line 6354: 
/home/hemmecke/config/emacs: Permission denied ; fi ; \
         chmod a+r ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied ; fi
cp: target `denied' is not a directory
chmod: cannot access `./configure:': No such file or directory
chmod: cannot access `line': No such file or directory
chmod: cannot access `6354:': No such file or directory
chmod: cannot access `/home/hemmecke/config/emacs:': No such file or 
directory
chmod: cannot access `Permission': No such file or directory
chmod: cannot access `denied': No such file or directory
make[3]: *** [install] Error 1
make[3]: Leaving directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl/elisp'
make[2]: *** [install1] Error 2
make[2]: Leaving directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl'
make[1]: *** [install] Error 2
make[1]: Leaving directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl'
make: *** [build/i686-pc-linux/bin/gcl] Error 2

\start
Date: 07 Aug 2007 09:31:47 -0400
From: Camm Maguire
To: Stephen Wilson
Subject: Re: gclcvs-2.7.0 and Axiom

Greetings, and thanks!

If you have the failing binary with a set of reproducible triggering
commands, that still could be useful even if compiled without
debugging.  (si::nani address) where address is the hex number printed
in the FREE OBJECT error output will give you the object in question
if you invoke this command prior to the failing gc call.  (setq
si::*notify-gbc* t) helps here too.  There is also a gc hook.  But
maybe the easiest is to grant me read/execute permissions on the
failing setup.

Take care,

Stephen Wilson writes:

> Camm,
> 
> A quick update on this issue.  
> 
> I have tried compiling with --enable-debug on my main machine, and
> have tried both with and without --enable-debug on a second box.
> Unfortunately, I cannot reproduce the failure under any of these
> conditions.
> 
> I can work around the issue locally, and if this does represent a gc
> problem hopefully a better opportunity will present itself to debug
> the condition.
> 
> FYI, the patch-set I have been working on now allows Silver to build
> to completion with only one failure in Axioms test-suite.  We are very
> close to getting Axiom working without issue atop gcl-2.7.0.
> 
> Many thanks for all your help with this!
> 
> Sincerely,
> Steve
> 
> Camm Maguire writes:
> 
> > Greetings!  Just a note -- --enable-debug on axiom-developer.org is
> > carrying the build past nrunfast.  WIll try with gcc optimization
> > tomorrow.

\start
Date: 07 Aug 2007 09:52:22 -0500
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Unsuccessful build-improvements

Ralf Hemmecke writes:

| Hi Gaby,
| 
| I am unlucky for some reason.
| 
| woodpecker:~/SVK/axiom/branches/build-improvements>svk info
| Checkout Path: /home/hemmecke/SVK/axiom/branches/build-improvements
| Depot Path: /mirror/axiom/branches/build-improvements
| Revision: 779
| Last Changed Rev.: 779
| Mirrored From: https://axiom.svn.sourceforge.net/svnroot/axiom, Rev. 695
| Copied From: /axiom/trunk/axiom, Rev. 33
| Merged From: /axiom/trunk/axiom, Rev. 33
| 
| woodpecker:~/OTHER/Axiom/out-of-source-build-improvements>
| ~/SVK/axiom/branches/build-improvements/configure
| --prefix=/home/hemmecke/scratch/AXIOM
| woodpecker:~/OTHER/Axiom/out-of-source-build-improvements>
| date>TIME;make|tee rhx.log;date>>TIME
| 
| The last thing I see on my screen is given at the end. The rest you find at
| 
| http://portal.axiom-developer.org/Members/hemmecke/build-improvements/rhx.log/file_view

Thanks.  Woaw, that is scary indeed.  For some reason, GCL
configuration must have failed or found something wrong.  Please
could you send me (probably privately) the config.log you find in the
subdirectory gcl?  Also send me the makefile in gcl/elisp.  It seems
to contain wrong things -- as far as I can determine from the above
log.

Thanks!

| If you need more information, just ask.
| 
| BTW, /home/hemmecke/config/emacs is actually supposed to be my .emacs
| file, but in fact it is unused. I have no idea why the build machinary
| wants to write anything outside /home/hemmecke/scratch/AXIOM or
| ~/OTHER/Axiom/out-of-source-build-improvements. Any ideas?

I believe that is the GCL configuration at work -- I have no control
on it.  Maybe the gcl/config.log will tell us more about what is going
on. 

\start
Date: Tue, 7 Aug 2007 10:45:09 -0500
From: Tim Daly
To: Ralf Hemmecke
Subject: ssh problem

Ralf,

It appears that sshd is not running on parrot.risc.uni-linz.ac.at

\start
Date: Tue, 7 Aug 2007 11:19:24 -0500
From: Tim Daly
To: Stephen Wilson
Subject: i-output and decimal width

Stephen,

Patch accepted and applied. 
I've put it in the queue for a test cycle.
If it passes the tests I'll promote it.

\start
Date: Tue, 7 Aug 2007 11:38:13 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Unsuccessful build-improvements

On Tue, 7 Aug 2007, Ralf Hemmecke wrote:

| gcl/config.log and gcl/elisp/Makefile are attached.
| 
| It seems that I am missing some library, right?

Thanks!

I believe GCL's configure tested to see where it could install
Emacs .el files.  The test did not succeed, but for some reasons
the variable EMACS_DEFAULT_EL was not properly cleared.  Hence the error
later.  

\start
Date: 08 Aug 2007 00:08:34 +0200
From: Martin Rubey
To: Tim Daly
Subject: typo in the guessing package pamphlet,	was: Re: Algebra and literate documentation

Tim Daly writes:

> Martin,
> 
> Normally I wouldn't mention this as an on-list post but....

??? WHY ???

> I spent the last two weeks rearranging Axiom so people can add
> algebra code to the system.

Great.

> I started adding your algebra to the system. I ran into a problem.
> It appears that mantepse.spad.pamphlet will not format correctly.
> When I looked into the problem you define a chunk:
> 
>   <<domain UFPS UnivariateFormalPowerSeries>>=

yes, all of these are typos, no idea why they weren't caught by wh-sandbox.
Just make them into <<dom: ...>>= and <<pkg: ...>>== etc. everywhere.  I will
fix this in the next version.

> Please post a working pamphlet file (English is preferred), 

I definitively do not have time to do that now.

> along with test cases. I cannot construct cases for things like GUESSINT.

there are plenty of test cases on MathAction (Guessingformulasforsequences).
You can also look at my article at arxiv.org, that explains some of the design
in detail.  In a nutshell, the syntax is

guessPRec [1,2,3,4]

and axiom is clever enough to call guessPRec$GUESSINT, since it figures that
[1,2,3,4] is a list of integers.  Similarly, 

guessPRec(q)([1,q,q^2,q^3], [])

will call guessPRec: Symbol -> Guesser from GUESSP, since axiom figures that
[1,q,q^2,q^3] is a list of polynomials.


Martin

PS: I have to prepare a one semester course within the next 10 days (and I am
starting only tomorrow), so I'll answer mail very selectively.  I.e.,, I'll
mainly answer things I can answer without much thinking.

\start
Date: 07 Aug 2007 17:34:36 -0500
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: typo in the guessing package pamphlet, was: Re: Algebra and literate documentation

Martin Rubey writes:

| > Please post a working pamphlet file (English is preferred), 
| 
| I definitively do not have time to do that now.

Martin --

   I hope you had good time.

   I believe an English explanation of what you're doing will be helpful.
At ISSAC'07, Tim, Bill, Stephen W., Barry and I (and probably others) tried
to get your algebra compile.  However, we did not succeed and I was
not fully confident about the changes we made because I could not
read/understand what the code is supposed to compute and *why* it is
doing what it is doing. 

\start
Date: 07 Aug 2007 17:35:24 -0500
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Unsuccessful build-improvements

Gabriel Dos Reis writes:

[...]

| | If you need more information, just ask.
| | 
| | BTW, /home/hemmecke/config/emacs is actually supposed to be my .emacs
| | file, but in fact it is unused. I have no idea why the build machinary
| | wants to write anything outside /home/hemmecke/scratch/AXIOM or
| | ~/OTHER/Axiom/out-of-source-build-improvements. Any ideas?
| 
| I believe that is the GCL configuration at work -- I have no control
| on it.  Maybe the gcl/config.log will tell us more about what is going
| on. 

I installed Camm's suggestion at revision 699.

\start
Date: Tue, 7 Aug 2007 18:49:21 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: typo in the guessing package pamphlet,

On 07 Aug 2007 17:34:36 -0500, Gabriel Dos Reis wrote:
> Martin Rubey writes:
>
> | > Please post a working pamphlet file (English is preferred),
> |
> | I definitively do not have time to do that now.
>
> Martin --
>
>    I hope you had good time.
>
>    I believe an English explanation of what you're doing will be helpful.
> At ISSAC'07, Tim, Bill, Stephen W., Barry and I (and probably others) tried
> to get your algebra compile.  However, we did not succeed and I was
> not fully confident about the changes we made because I could not
> read/understand what the code is supposed to compute and *why* it is
> doing what it is doing.
>

Although I did not have time to look at the problem deeply, my
understanding from what Tim showed me was that the problem is likely
due to how the old build system handles updates to the database files.
The Martin's algebra code is known to compile under wh-sandbox and
FriCAS. Very likely (I haven't tried) it can also be made to compile
under build-improvements.

\start
Date: 08 Aug 2007 01:09:38 +0200
From: Martin Rubey
To: Gabriel Dos Reis
Subject: Re: typo in the guessing package pamphlet, was: Re: Algebra and literat

Gabriel Dos Reis writes:

> Martin Rubey writes:
> 
> | > Please post a working pamphlet file (English is preferred), 
> | 
> | I definitively do not have time to do that now.
> 
> Martin --
> 
>    I hope you had good time.

Partially, thanks...

>    I believe an English explanation of what you're doing will be helpful.

explanation of me doing what?  

* design decisions => arxiv.org / pamphlet files

* implementation decisions => pamphlet files

* build instructions for gold: hairy, but can be found in the axiom-developer.

> At ISSAC'07, Tim, Bill, Stephen W., Barry and I (and probably others) tried
> to get your algebra compile.  

Oops.  Well, from a running axiom system, you should compile things for example
in the following order:

SUPEXPR FAMR2 NEWTON UFPS GOPT GUESSF1 UTSSOL FFFG UFPS1 GOPT0 EXPRSOL FFFGF 
RECOP GUESS GUESSINT GUESSP GUESSF

(note that, for example, GUESSINT depends on GUESS, which depends on GOPT0
which depends on GOPT0 and so on)

It should be sufficient to say in a fresh axiom

)co fffg.spad
)co ssolve.spad
)co recop.spad
)co mantepse.spad

in this order.  Unfortunately, it depends on some algebra fixes that were not
applied to Gold.  But as far as I remember, these fixes should not affect the
compilation itself.

Do you recall what went wrong at ISSAC?

\start
Date: 08 Aug 2007 01:22:55 +0200
From: Martin Rubey
To: Andrey G. Grozin
Subject: re: Pamphlet format discussion

Andrey G. Grozin writes:


> Of course, this requires some programming, but quite trivial - LaTeX syntax
> is very simple and regular (unless we play dirty low-level TeX games with
> re-defining character classes, etc.; such tricks should be certainly banned
> in pamphlet files).

I disagree:  I love the xy package for diagrams, and it implements a whole new
language within LaTeX.  Including giving meaning to the @ character, by the
way.

> >> Ideally, we should have the possibliity to have chunks written in
> >> several languages in the same pamphlet, and to work with them
> >> comfortably from emacs. Currently, this is not possible; so, I don't
> >> think that the current setup is purfect and should not be improved.
> >
> > I am not sure what you mean here.  Noweb and similar tools are
> > language independent.  By specifying the root chunk to extract at the
> > tangle stage, you can extract source code in various languages from
> > the same pamphlet.

> I mean emacs mode only. Ideally, I'd like LaTeX in a pamphlet to be
> syntax-highlighted as LaTeX, spad code - as spad code (or as aldor, for which
> an emacs mode is available), Makefile parts - as Makefiles, lisp code - as
> lisp, etc. Even better if key bindings will be those of the lisp mode when
> the cursor is inside a lisp chunk, those of auctex when the cursor is in
> LaTeX, etc. All in a single pamphlet. Currently, this cannot be done :-(

Doesn't mmm-mode allow this?

\start
Date: 08 Aug 2007 01:28:23 +0200
From: Martin Rubey
To: Tim Daly
Subject: Re: Democracy!

Tim Daly writes:

> I'm not sure how Martin plans to garner 49 votes for anything but 
> that's his problem to solve. I say 49 votes because there are 97
> people registered on the mailing list. Every "democratic" process
> I'm aware of requires at least a simple majority to "pass". If an
> insufficient number of people vote, for whatever reason, the measure 
> is dropped.

Did you read my proposal on the voting system?  I do apologize for not making
it immediately clear that I do not suggest to wait for a simple majority but
only wait for a limited number of days.  I'll copy my voting scheme proposal to
MathAction.

\start
Date: Tue, 7 Aug 2007 19:42:37 -0400
From: Bill Page
To: Martin Rubey
Subject: Re: typo in the guessing package pamphlet, was: Re: Algebra and literate documentation
Cc: Gabriel Dos Reis

On 08 Aug 2007 01:09:38 +0200, Martin Rubey wrote:
> Gabriel Dos Reis writes:
>
> > At ISSAC'07, Tim, Bill, Stephen W., Barry and I (and probably others) tried
> > to get your algebra compile.
>
> Oops.  Well, from a running axiom system, you should compile things for example
> in the following order:
>
> SUPEXPR FAMR2 NEWTON UFPS GOPT GUESSF1 UTSSOL FFFG UFPS1 GOPT0 EXPRSOL FFFGF
> RECOP GUESS GUESSINT GUESSP GUESSF
>
> (note that, for example, GUESSINT depends on GUESS, which depends on GOPT0
> which depends on GOPT0 and so on)
>
> It should be sufficient to say in a fresh axiom
>
> )co fffg.spad
> )co ssolve.spad
> )co recop.spad
> )co mantepse.spad
>
> in this order.  Unfortunately, it depends on some algebra fixes that were not
> applied to Gold.  But as far as I remember, these fixes should not affect the
> compilation itself.
>
> Do you recall what went wrong at ISSAC?
>

This works just as you describe - even with Gold. But the problem
occurred when Tim tried to add the necessary commands to the
algebra/Makefile.pamphlet file to include the GUESS package in the
standard build. This is the same problem that was originally reported
by Alfredo Portes about this time last year.

During the build there are unexpected errors during the compile of
some modules, even when they are compiled in the required order. Tim
demonstrated to me that if he stopped the build at that point and
started Axiom normally, the )compile command which previously failed
during the build completes succesfully. My conclusion from this was
that during the build the wrong database files must accessed since
that is the only thing that I can think of that might be different
between the build environment and running Axiom from the command line.

\start
Date: 08 Aug 2007 01:50:45 +0200
From: Martin Rubey
To: Bill Page
Subject: adding new algebra,

Bill Page writes:

> This works just as you describe - even with Gold. 

great!

> But the problem occurred when Tim tried to add the necessary commands to the
> algebra/Makefile.pamphlet file to include the GUESS package in the standard
> build. This is the same problem that was originally reported by Alfredo
> Portes about this time last year.

Yes.  I recall describing on the list how to work around it by making the build
process semi-automatic, i.e., adding only the files in the first layer (i.e.,
RECOP, FAMR2, GOPT, etc.) to src/algebra/Makefile.pamphlet, finishing the
build, then adding the files in the second layer to Makefile.pamphlet, and
starting a new build, but specifying DAASE with

make DAASE=forgot/the/path/sorry

Too tired to look for the appropriate messages.

In any case, this semi-automatic build is stupid and can be avoided by using an
appropriate build scheme.  I guess, Tim is working on that.  Really, the
problem is the same as Franz Lehner's, I guess.

\start
Date: Tue, 7 Aug 2007 20:03:05 -0400
From: Bill Page
To: Martin Rubey
Subject: Re: adding new algebra,

On 08 Aug 2007 01:50:45 +0200, Martin Rubey wrote:
> Bill Page writes:
> ...
> > This is the same problem that was originally reported by Alfredo
> > Portes about this time last year.
>
> Yes.  I recall describing on the list how to work around it by making the build
> process semi-automatic, i.e., adding only the files in the first layer (i.e.,
> RECOP, FAMR2, GOPT, etc.) to src/algebra/Makefile.pamphlet, finishing the
> build, then adding the files in the second layer to Makefile.pamphlet, and
> starting a new build, but specifying DAASE with
>
> make DAASE=forgot/the/path/sorry
>
> Too tired to look for the appropriate messages.
>
> In any case, this semi-automatic build is stupid and can be avoided by using an
> appropriate build scheme.  I guess, Tim is working on that.  Really, the
> problem is the same as Franz Lehner's, I guess.
>

It is a similar problem but Franz' problem is even more difficult
because it attempts to make a basic change to some existing algebra
code deep down in the algebra hierachy. In this case the initial
databases that are in the share directory of the build can not be used
to compile this code. Thus there is no way to get the required
bootstrap started. The only version of Axiom that can currently
compile it is FriCAS since it has a more elaborate bootstrap system
that starts with empy databases.

\start
Date: 08 Aug 2007 02:05:26 +0200
From: Martin Rubey
To: Bill Page
Subject: Re: adding new algebra,

Bill Page writes:

> It is a similar problem but Franz' problem is even more difficult
> because it attempts to make a basic change to some existing algebra
> code deep down in the algebra hierachy. In this case the initial
> databases that are in the share directory of the build can not be used
> to compile this code. Thus there is no way to get the required
> bootstrap started. The only version of Axiom that can currently
> compile it is FriCAS since it has a more elaborate bootstrap system
> that starts with empy databases.

Oh yes, quite right.  Well, that's the way to do it in any case.  I hope for
many many many changes deep down the algebra...

\start
Date: Tue, 7 Aug 2007 20:09:28 -0500 (CDT)
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: typo in the guessing package pamphlet, was:

On Tue, 8 Aug 2007, Martin Rubey wrote:

| Do you recall what went wrong at ISSAC?

Many things :-)

More specifically:

 * short hand for unnamed functions do not work properly, so one has
   to use the syntax x +-> f(x)

 * the most recalcitrant was a package call to generalInterpolation()
   from some.

If you would like me to get your package bundled with build-improvements, I'm
afraid you would have to help me more than just instructing me to gather
information from several places...

\start
Date: Tue, 7 Aug 2007 20:13:53 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: typo in the guessing package pamphlet, was:

On Tue, 7 Aug 2007, Bill Page wrote:

[...]

| During the build there are unexpected errors during the compile of
| some modules, even when they are compiled in the required order. Tim
| demonstrated to me that if he stopped the build at that point and
| started Axiom normally, the )compile command which previously failed
| during the build completes succesfully. My conclusion from this was
| that during the build the wrong database files must accessed since
| that is the only thing that I can think of that might be different
| between the build environment and running Axiom from the command line.

I agree with that assessment.

Then, Tim and I tried to understand the failure and how to get it fixed or
worked around.  We (at least I) could not figured out properly what Martin 
was trying to achieve.  Mainly, there were mismatch between arguments and
parameters -- at least, that is what the compiler was reporting (I know, it is
a bug, but I would love to understand what your code is doing and why the
compiler is failing).

\start
Date: Tue, 7 Aug 2007 21:49:41 -0400
From: Bill Page
To: Martin Rubey
Subject: Re: adding new algebra,
Cc: Gabriel Dos Reis

On 08 Aug 2007 01:50:45 +0200, Martin Rubey wrote:
> ...
>  I recall describing on the list how to work around it by making the build
> process semi-automatic, i.e., adding only the files in the first layer (i.e.,
> RECOP, FAMR2, GOPT, etc.) to src/algebra/Makefile.pamphlet, finishing the
> build, then adding the files in the second layer to Makefile.pamphlet, and
> starting a new build, but specifying DAASE with
>
> make DAASE=forgot/the/path/sorry
>
> Too tired to look for the appropriate messages.
>

I think this is the right thread:

http://lists.nongnu.org/archive/html/axiom-developer/2006-09/msg00430.html

> In any case, this semi-automatic build is stupid and can be avoided by using an
> appropriate build scheme.  I guess, Tim is working on that.

I think your suggestions here:

http://lists.nongnu.org/archive/html/axiom-developer/2006-09/msg00491.html

"I guess that

* the daase files in int should be updated after every layer.

* after the first update, i.e., after LAYER0BOOTSTRAP or so, DAASE should point
  to int."

are right on.

\start
Date: 08 Aug 2007 06:56:46 +0200
From: Martin Rubey
To: Gabriel Dos Reis
Subject: Re: typo in the guessing package pamphlet,

Gabriel Dos Reis writes:

> On Tue, 8 Aug 2007, Martin Rubey wrote:
> 
> | Do you recall what went wrong at ISSAC?
> 
> Many things :-)
> 
> More specifically:
> 
>  * short hand for unnamed functions do not work properly, so one has
>    to use the syntax x +-> f(x)

Could you tell me in what places that happens, and what "do not work properly"
means exactly?  I depend on unnamed functions quite a bit, since at a few
points I actually construct such functions by code.  I do recall vividly that
these functions were extremely hard to compile.

>  * the most recalcitrant was a package call to generalInterpolation()
>    from some.

I guess you mean the following snippet from mantepse.spad.pamphlet.  By the
way, where did you get the sources of the package from?  wh-sandbox?  They are
outdated, since I am thinking of releasing newer code - because of the fork and
history - only under the GPL.  In no model I am contemplating this concerns
bug fixes, however.  In particular, I am aware of one argument mismatch
wh-sandbox didn't complain about, which was reported on the list, I think it
concerned testInterpolant, which had "list" as parameter twice...

-------------------------------------------------------------------------------
[[guessInterpolate]] calls the appropriate [[generalInterpolation]] from
[[FFFG]], for one vector of degrees, namely [[eta]].

<<implementation: Guess - guessInterpolate>>=
guessInterpolate(guessList: List SUP F, eta: List NNI, D: HPSPEC)
                : Matrix SUP S ==
    if F is S then 
        vguessList: Vector SUP S := vector(guessList pretend List(SUP(S)))
        generalInterpolation((D.C)(reduce(_+, eta)), D.A, 
                             vguessList, eta)$FFFG(S, SUP S)
    else if F is Fraction S then
        vguessListF: Vector SUP F := vector(guessList)
        generalInterpolation((D.C)(reduce(_+, eta)), D.A, 
                             vguessListF, eta)$FFFGF(S, SUP S, SUP F)

    else error "Type parameter F should be either equal to S or equal _
                to Fraction S"
@

[[guessInterpolate2]] calls the appropriate [[generalInterpolation]] from
[[FFFG]], for all degree vectors with given [[sumEta]] and [[maxEta]].

<<implementation: Guess - guessInterpolate2>>=
guessInterpolate2(guessList: List SUP F, 
                  sumEta: NNI, maxEta: NNI, 
                  D: HPSPEC): Stream Matrix SUP S ==
    if F is S then 
        vguessList: Vector SUP S := vector(guessList pretend List(SUP(S)))
        generalInterpolation((D.C)(sumEta), D.A, 
                             vguessList, sumEta, maxEta)
                            $FFFG(S, SUP S)
    else if F is Fraction S then
        vguessListF: Vector SUP F := vector(guessList)
        generalInterpolation((D.C)(sumEta), D.A, 
                             vguessListF, sumEta, maxEta)
                            $FFFGF(S, SUP S, SUP F)
    
    else error "Type parameter F should be either equal to S or equal _
                to Fraction S"
@
-------------------------------------------------------------------------------

But I really cannot see what could go wrong here.  Please help!  Ideally, I'd
like to be able to reproduce the problems you experienced.

(I definitively want to have it in build-improvements!  In fact, I want to have
it in Gold, too.)

\start
Date: Wed, 8 Aug 2007 01:47:43 -0500 (CDT)
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: typo in the guessing package pamphlet, was:

On Tue, 8 Aug 2007, Martin Rubey wrote:

| Gabriel Dos Reis writes:
| 
| > On Tue, 8 Aug 2007, Martin Rubey wrote:
| > 
| > | Do you recall what went wrong at ISSAC?
| > 
| > Many things :-)
| > 
| > More specifically:
| > 
| >  * short hand for unnamed functions do not work properly, so one has
| >    to use the syntax x +-> f(x)
| 
| Could you tell me in what places that happens, and what "do not work properly"
| means exactly?  I depend on unnamed functions quite a bit, since at a few
| points I actually construct such functions by code.  I do recall vividly that
| these functions were extremely hard to compile.


OK, all of this happened on Tim's machine.  I believe he has a trace/log
of many of the things.  Basically, there was an expression like a function
taking many arguments, say, foo(a, b, c).  then you wrote

     foo(a, #1, c)

to indicate an unnamed function of one argument.  That syntax was giving the
compiler a headache inferring the correct type of #1 (a bug!).  I suggested to
rewrite it as 

     x +-> foo(a, x, c)

and the compiler was happy.

| >  * the most recalcitrant was a package call to generalInterpolation()
| >    from some.
| 
| I guess you mean the following snippet from mantepse.spad.pamphlet.  By the
| way, where did you get the sources of the package from?  wh-sandbox?


I did not "get" the source.  I was helping Tim to solve the problem of
integrating your package into Silver.  Tim, do you still have the logs?

Thanks for your answers!  I'll return back to you.

\start
Date: Wed, 8 Aug 2007 01:49:07 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: adding new algebra, was: Re: typo in the

On Tue, 7 Aug 2007, Bill Page wrote:

| On 08 Aug 2007 01:50:45 +0200, Martin Rubey wrote:
| > ...
| >  I recall describing on the list how to work around it by making the build
| > process semi-automatic, i.e., adding only the files in the first layer (i.e.,
| > RECOP, FAMR2, GOPT, etc.) to src/algebra/Makefile.pamphlet, finishing the
| > build, then adding the files in the second layer to Makefile.pamphlet, and
| > starting a new build, but specifying DAASE with
| >
| > make DAASE=forgot/the/path/sorry
| >
| > Too tired to look for the appropriate messages.
| >
| 
| I think this is the right thread:
| 
| http://lists.nongnu.org/archive/html/axiom-developer/2006-09/msg00430.html
| 
| > In any case, this semi-automatic build is stupid and can be avoided by using an
| > appropriate build scheme.  I guess, Tim is working on that.
| 
| I think your suggestions here:
| 
| http://lists.nongnu.org/archive/html/axiom-developer/2006-09/msg00491.html
| 
| "I guess that
| 
| * the daase files in int should be updated after every layer.
| 
| * after the first update, i.e., after LAYER0BOOTSTRAP or so, DAASE should point
|   to int."
| 
| are right on.

Bill -- thanks for the detective work!

\start
Date: Wed, 8 Aug 2007 03:19:43 -0400
From: Bill Page
To: Martin Rubey
Subject: Re: typo in the guessing package pamphlet,
Cc: Gabriel Dos Reis

On 08 Aug 2007 06:56:46 +0200, Martin Rubey wrote:
> Gabriel Dos Reis writes:
> ...
> > More specifically:
> >
> >  * short hand for unnamed functions do not work properly, so one has
> >    to use the syntax x +-> f(x)
>
> Could you tell me in what places that happens, and what "do not work properly"
> means exactly?  I depend on unnamed functions quite a bit, since at a few
> points I actually construct such functions by code.  I do recall vividly that
> these functions were extremely hard to compile.

Well, just picking an example at random from your code (not
necessarily one that compiled with errors):

In mantepse.spad.pamphlet chunk <<implementation: Guess - Hermite-Pade
- Operators>>=
...
    diffHP(q: Symbol): (LGOPT -> HPSPEC) ==
        if displayAsGF(#1)$GOPT0 then
            partitions := FilteredPartitionStream #1
            [ADEguessStream(#1, partitions, qDiffDS(q, #1, #2), 1$UFPSF), _
             repeating([0$NNI])$Stream(NNI), _
             ADEtestStream(#1, partitions, qDiffDSF(q, #1, #2), 1$UFPSSUPF), _
             ADEEXPRRStream(#1, #2, partitions, qDiffDX(q, #1, #2,
#3), diff1X), _
             diffA, diffAF, diffAX, diffC]$HPSPEC
        else
            error "Guess: guessADE supports only displayAsGF"

----

where reference is made to the following definitions:

    LGOPT ==> List GuessOption

    HPSPEC ==> Record(guessStream:  UFPSF -> Stream UFPSF,
                      degreeStream: Stream NNI,
                      testStream:   UFPSSUPF -> Stream UFPSSUPF,
                      exprStream:   (EXPRR, Symbol) -> Stream EXPRR,
                      A:  DIFFSPECA,
                      AF: DIFFSPECAF,
                      AX: DIFFSPECAX,
                      C:  DIFFSPECC)

UFPSF ==> UnivariateFormalPowerSeries F

ADEguessStream(f: UFPSF, partitions: Stream List Integer,
               DS: DIFFSPECS, D1: DIFFSPEC1): Stream UFPSF ==
    map(termAsUFPSF(f, #1, DS, D1), partitions)
       $StreamFunctions2(List Integer, UFPSF)

---

Why do you use macros for types like HPSPEC?

What do expect the meaning of #2 and #3 to be?

As I understand Spad syntax, if I write

   ( #1 + #2 + #3 )

this is a shorthand for the following anonymous function

  (x,y,z) +-> x + y + z

Is that correct? Perhaps not since with this definition I can not make
sense of your code.

For example, where you write above:

  [ADEguessStream(#1, partitions, qDiffDS(q, #1, #2), 1$UFPSF), ... ]

we could rewrite this as:

  (x,y,z) +-> [ADEguessStream(x, partitions, qDiffDS(q, x, y), 1$UFPSF),...]

but the first component of HPSPEC is

   guessStream:  UFPSF -> Stream UFPSF

which seems to require a function with a single argument.

Also from diffHP we were supposed to return a function

  LGOPT -> HPSPEC

But the code apparently implies a function with 3 arguments.

Could you give an alternate explanation that makes better sense?

> ...

\start
Date: Wed, 8 Aug 2007 03:18:21 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: typo in the guessing package pamphlet, was:

On Wed, 8 Aug 2007, Bill Page wrote:

| On 08 Aug 2007 06:56:46 +0200, Martin Rubey wrote:
| > Gabriel Dos Reis writes:
| > ...
| > > More specifically:
| > >
| > >  * short hand for unnamed functions do not work properly, so one has
| > >    to use the syntax x +-> f(x)
| >
| > Could you tell me in what places that happens, and what "do not work properly"
| > means exactly?  I depend on unnamed functions quite a bit, since at a few
| > points I actually construct such functions by code.  I do recall vividly that
| > these functions were extremely hard to compile.
| 
| Well, just picking an example at random from your code (not
| necessarily one that compiled with errors):
| 
| In mantepse.spad.pamphlet chunk <<implementation: Guess - Hermite-Pade
| - Operators>>=
| ...
|     diffHP(q: Symbol): (LGOPT -> HPSPEC) ==
|         if displayAsGF(#1)$GOPT0 then
|             partitions := FilteredPartitionStream #1
|             [ADEguessStream(#1, partitions, qDiffDS(q, #1, #2), 1$UFPSF), _
|              repeating([0$NNI])$Stream(NNI), _
|              ADEtestStream(#1, partitions, qDiffDSF(q, #1, #2), 1$UFPSSUPF), _
|              ADEEXPRRStream(#1, #2, partitions, qDiffDX(q, #1, #2,
| #3), diff1X), _
|              diffA, diffAF, diffAX, diffC]$HPSPEC
|         else
|             error "Guess: guessADE supports only displayAsGF"
| 
| ----
| 
| where reference is made to the following definitions:
| 
|     LGOPT ==> List GuessOption
| 
|     HPSPEC ==> Record(guessStream:  UFPSF -> Stream UFPSF,
|                       degreeStream: Stream NNI,
|                       testStream:   UFPSSUPF -> Stream UFPSSUPF,
|                       exprStream:   (EXPRR, Symbol) -> Stream EXPRR,
|                       A:  DIFFSPECA,
|                       AF: DIFFSPECAF,
|                       AX: DIFFSPECAX,
|                       C:  DIFFSPECC)
| 
| UFPSF ==> UnivariateFormalPowerSeries F
| 
| ADEguessStream(f: UFPSF, partitions: Stream List Integer,
|                DS: DIFFSPECS, D1: DIFFSPEC1): Stream UFPSF ==
|     map(termAsUFPSF(f, #1, DS, D1), partitions)
|        $StreamFunctions2(List Integer, UFPSF)
| 
| ---
| 
| Why do you use macros for types like HPSPEC?
| 
| What do expect the meaning of #2 and #3 to be?
| 
| As I understand Spad syntax, if I write
| 
|    ( #1 + #2 + #3 )
| 
| this is a shorthand for the following anonymous function
| 
|   (x,y,z) +-> x + y + z
| 
| Is that correct?

I think so.

Note however, that in nested context, I believe the rules are a bit different.
That is:

    f(#1, g(#1, #2))

would be equivalent to

   x +-> f(x, (y, z) +-> g(y, z))

However, I can't find a documentation for that.

\start
Date: 08 Aug 2007 10:37:45 +0200
From: Martin Rubey
To: Gabriel Dos Reis
Subject: Re: typo in the guessing package pamphlet

Gabriel Dos Reis writes:

> | In mantepse.spad.pamphlet chunk <<implementation: Guess - Hermite-Pade
> | - Operators>>=
> | ...
> |     diffHP(q: Symbol): (LGOPT -> HPSPEC) ==
> |         if displayAsGF(#1)$GOPT0 then
> |             partitions := FilteredPartitionStream #1
> |             [ADEguessStream(#1, partitions, qDiffDS(q, #1, #2), 1$UFPSF), _
> |              repeating([0$NNI])$Stream(NNI), _
> |              ADEtestStream(#1, partitions, qDiffDSF(q, #1, #2), 1$UFPSSUPF), _
> |              ADEEXPRRStream(#1, #2, partitions, qDiffDX(q, #1, #2,
> | #3), diff1X), _
> |              diffA, diffAF, diffAX, diffC]$HPSPEC
> |         else
> |             error "Guess: guessADE supports only displayAsGF"
> | 
> | ----
> | 
> | where reference is made to the following definitions:
> | 
> |     LGOPT ==> List GuessOption
> | 
> |     HPSPEC ==> Record(guessStream:  UFPSF -> Stream UFPSF,
> |                       degreeStream: Stream NNI,
> |                       testStream:   UFPSSUPF -> Stream UFPSSUPF,
> |                       exprStream:   (EXPRR, Symbol) -> Stream EXPRR,
> |                       A:  DIFFSPECA,
> |                       AF: DIFFSPECAF,
> |                       AX: DIFFSPECAX,
> |                       C:  DIFFSPECC)
> | 
> | UFPSF ==> UnivariateFormalPowerSeries F
> | 
> | ADEguessStream(f: UFPSF, partitions: Stream List Integer,
> |                DS: DIFFSPECS, D1: DIFFSPEC1): Stream UFPSF ==
> |     map(termAsUFPSF(f, #1, DS, D1), partitions)
> |        $StreamFunctions2(List Integer, UFPSF)
> | 
> | ---
> | 
> | Why do you use macros for types like HPSPEC?

Because I use it 16 times in mantepse.spad.pamphlet.  Moreover, at times I
experienced trouble when trying to compile code like

f: MyType -> MyComplicatedType

f(n: MyType): MyComplicatedType ==
  ...

but I cannot be sure whether this trouble was due to my imagination or not.


In any case,

>     f(#1, g(#1, #2))

is "equivalent" (modulo bugs in the compiler) to

>    x +-> f(x, (y, z) +-> g(y, z))

> However, I can't find a documentation for that.

I guess there is no documentation for that. Moreover, I would prefer to use

 x +-> f(x, (y, z) +-> g(y, z)),

since this is also the aldor way and using #1, #2, ... is stupid for several
reasons, but I experienced trouble at times.  Since I experienced lots of
trouble getting code to compile, and since I am rather a hacker than a
programmer, I didn't care and tried to get things done.

If you find out that 

 x +-> f(x, (y, z) +-> g(y, z))

works everywhere or in most situations, PLEASE do not hesitate to send patches.
Please send them to me directly or via axiom-developer, not to MathAction,
because I update MathAction from time to time, and then these patches might be
lost.

\start
Date: Wed, 8 Aug 2007 03:46:24 -0500 (CDT)
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: typo in the guessing package pamphlet

On Wed, 8 Aug 2007, Martin Rubey wrote:

| If you find out that 
| 
|  x +-> f(x, (y, z) +-> g(y, z))
| 
| works everywhere or in most situations, PLEASE do not hesitate to send patches.
| Please send them to me directly or via axiom-developer, not to MathAction,
| because I update MathAction from time to time, and then these patches might be
| lost.

On the cases I discussed with Tim, it worked; I don't know whether Tim found
other places.  However, since we are busy doing many things and this is your
package, it would be helpful, in light of this discussion, that *you* made
those changes and resubmit your package so that we can all get it in main
Axiom distribution -- so that so some of us can focuse on the database issue
(e.g. compiler bugs).

\start
Date: Wed, 08 Aug 2007 11:47:36 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: Unsuccessful build-improvements
Cc: Camm Maguire

> I installed Camm's suggestion at revision 699.

The build still fails. That was not the right workaround.

Maybe to help finding the right workaround, I should tell you about my 
directory setup.

I usually use XEMACS, so my configuration files are in ~/.xemacs.

There is, however a ~/.emacs file that starts with the line

(setq load-path (append '("~/pub/elisp" "~/pub/elisp/emacs/mmm-mode") 
load-path))

and I nowhere else change the load-path.

woodpecker:~>ls -l .xemacs
total 740
lrwxrwxrwx 1 hemmecke hemmecke     31 2005-01-21 18:38 custom.el -> 
/home/hemmecke/config/custom.el
lrwxrwxrwx 1 hemmecke hemmecke     29 2005-01-21 18:38 init.el -> 
/home/hemmecke/config/init.el
drwx------ 6 hemmecke hemmecke   4096 2006-06-19 10:51 xemacs-packages

woodpecker:~>ls -l |grep config
lrwxrwxrwx  1 hemmecke hemmecke      11 2005-01-21 18:03 config -> 
HOME/config

woodpecker:~>ls -l HOME
lrwxrwxrwx 1 hemmecke hemmecke 14 2006-11-05 00:55 HOME -> SVK/HOME/trunk

No symlink after that anymore.

woodpecker:~>ls -l HOME/config |grep emacs
-rw------- 1 hemmecke hemmecke   276 2006-11-05 00:21 emacs

Clearly, that is not a directory.

I must say, it would be interesting to understand, why the GCL configure 
script is able at all to find /home/hemmecke/config.

| Greetings!  /home/.../config/emacs is erroneously picked up as the
| emacs site-lisp directory:

I am still not able to understand how GCL finds /home/hemmecke/config.

It is *not* in my (x-)emacs load-path. It was, however, in my $PATH.
Why should that matter for installing .el files???

Now I removed /home/hemmecke/config from my PATH environment variable 
and the build of build-improvements -r700 got after that error described 
here (still compiling).

Does that help someone to figure out where that bug lies?

Ralf

===============================================================

woodpecker:~/SVK/axiom/branches/build-improvements>svk info
Checkout Path: /home/hemmecke/SVK/axiom/branches/build-improvements
Depot Path: /mirror/axiom/branches/build-improvements
Revision: 784
Last Changed Rev.: 784
Mirrored From: https://axiom.svn.sourceforge.net/svnroot/axiom, Rev. 700
Copied From: /axiom/trunk/axiom, Rev. 33
Merged From: /axiom/trunk/axiom, Rev. 33

The log is at.
http://portal.axiom-developer.org/Members/hemmecke/build-improvements/rhx-r700.log/file_view

Last screen output  below.


GCL (GNU Common Lisp)  2.6.8 CLtL1    Aug  8 2007 10:31:58
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License:  GPL due to GPL'ed components: (BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/

 >
NIL

 >if [ -e "unixport/rsym" ] ; then cp unixport/rsym 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/unixport/ 
; fi
if [ -d "" ] ; then  \
         cat gcl-tk/gcltksrv | \
         sed -e 
"s!GCL_TK_DIR=.*!GCL_TK_DIR=/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/gcl-tk!g" 
  \
         -e "s!TK_LIBRARY=.*!TK_LIBRARY=!g" > \
 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/gcl-tk/gcltksrv 
; \
         chmod a+x 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/lib/gcl-2.6.8/gcl-tk/gcltksrv 
; fi
if test 
"/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp/" 
!= "" ; then (cd elisp ; make install DESTDIR=) ; fi
make[3]: Entering directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl/elisp'
mkdir -p 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp/
cp *.el 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp/
if [ "./configure: line 6354: /home/hemmecke/config/emacs: Permission 
denied" != "" ] ; then \
         if test -f "./configure: line 6354: 
/home/hemmecke/config/emacs: Permission denied" ; then \
         cat ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied | sed -e '/BEGIN gcl/,/END gcl/d' > 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
; \
         mv ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied.prev ; \
           rm -f  ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission deniedc ; \
           cat add-default.el >> 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
; cp 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
./configure: line 6354: /home/hemmecke/config/emacs: Permission denied ; \
           rm -f 
/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/build/i686-pc-linux/share/emacs/site-lisp//temp_emacs_default 
; else \
         cp  add-default.el ./configure: line 6354: 
/home/hemmecke/config/emacs: Permission denied ; fi ; \
         chmod a+r ./configure: line 6354: /home/hemmecke/config/emacs: 
Permission denied ; fi
cp: target `denied' is not a directory
chmod: cannot access `./configure:': No such file or directory
chmod: cannot access `line': No such file or directory
chmod: cannot access `6354:': No such file or directory
chmod: cannot access `/home/hemmecke/config/emacs:': No such file or 
directory
chmod: cannot access `Permission': No such file or directory
chmod: cannot access `denied': No such file or directory
make[3]: *** [install] Error 1
make[3]: Leaving directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl/elisp'
make[2]: *** [install1] Error 2
make[2]: Leaving directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl'
make[1]: *** [install] Error 2
make[1]: Leaving directory 
`/home/hemmecke/OTHER/Axiom/out-of-source-build-improvements/gcl'
make: *** [build/i686-pc-linux/bin/gcl] Error 2

\start
Date: Wed, 8 Aug 2007 05:02:02 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Unsuccessful build-improvements
Cc: Camm Maguire

On Wed, 8 Aug 2007, Ralf Hemmecke wrote:

| > I installed Camm's suggestion at revision 699.
| 
| The build still fails. That was not the right workaround.


Camm --

  We don't use GCL's Emacs .el at all when we build GCL; is there a way
to ask GCL's configure not to attempt anything with Emacs' file?

\start
Date: Wed, 08 Aug 2007 13:06:03 +0200
From: Ralf Hemmecke
To: Bill Wood
Subject: Re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work

I think you have just found a bug in the Axiom interpreter/compiler.

The following Aldor program compiles fine.

aldor -fx -laldor aaa.as

and gives as output

xs = [
   [0, 0]
   [0, 0]
   [10, 0]
]

ys = [
   [0, 0]
   [0, 0]
   [10, 0]
]

Don't be distracted by this output stuff (TextWriter). Your code 
basically appears in the main() function. And in Aldor that works.

Since this special form of assignment is actually a call to the function 
set! (Aldor) the line

   ys(2).k := 10;

is equivalent to

   set!(ys(2), k, 10);

There is no problem with the actual form of the first argument of set!. 
As long as there is a function

   set!: (R, Enumeration(k: Type), INT) -> INT

that should compile fine. Well, and "ys(2)" is of type R.
(Of course, all this is Aldor specific, but Axiom should try hard to get 
close.)

I have no idea, though, why Axiom is unable to deal correctly with that 
expression. That should be dealt with by our compiler experts.

Ralf




---BEGIN aaa.as
#include "aldor"
#include "aldorio"

INT == MachineInteger;
R ==> Record(k: INT, rad: INT);
import from R, INT;

initrec(): R == [0,0];

(tw: TextWriter) <= (r: R): TextWriter == {
   tw << "[" << r.k << ", " << r.rad << "]"
}
(tw: TextWriter) << (g: Generator R): TextWriter == {
   tw << "[" << newline;
   for r in g repeat tw << "  " <= r << newline;
   tw << "]" << newline;
}


main(): () == {
   xs: List R := [initrec() for i in 1..3];
   ys: Array R := [z for z in xs];
   ys(2).k := 10;
   stdout << "xs = " << generator xs << newline;
   stdout << "ys = " << generator ys << newline;
}

main();---END aaa.as

On 08/08/2007 11:41 AM, Bill Wood wrote:
> I'm just trying to assign to a field of a record in a one-dimensional
> array of records, but I get this incomprehensible message:
> =====================================================================
> (1) -> )clear all
>    All user variables and function definitions have been cleared.
> (1) -> )read foo.input
> -- File of Axiom definitions solving problem 124.
> -- Created 2007/08/08 by Bill Wood.
> 
> init_rec() ==
>   r : Record(k: INT, rad: INT) := [0,0]
>   r
> 
>                                            Type: Void
> (2) -> xs := [init_rec() for i in 1..3]
>    Compiling function initrec with type () -> Record(k: Integer,rad:
>       Integer)
> 
>    (2)  [[k= 0,rad= 0],[k= 0,rad= 0],[k= 0,rad= 0]]
>                       Type: List Record(k: Integer,rad: Integer)
> (3) -> ys := oneDimensionalArray(xs)
> (3) ->
>    (3)  [[k= 0,rad= 0],[k= 0,rad= 0],[k= 0,rad= 0]]
>            Type: OneDimensionalArray Record(k: Integer,rad: Integer)
> (4) -> ys
> (4) ->
>    (4)  [[k= 0,rad= 0],[k= 0,rad= 0],[k= 0,rad= 0]]
>            Type: OneDimensionalArray Record(k: Integer,rad: Integer)
> (5) -> ys(2).k := 10
>  5) ->
>    The form on the left hand side of an assignment must be a single
>       variable, a Tuple of variables or a reference to an entry in an
>       object supporting the setelt operation.
> (5) ->
> =======================================================================
> What do I have to do to set the fields of the records to desired
> values???

\start
Date: 08 Aug 2007 13:36:52 +0200
From: Martin Rubey
To: Ralf Hemmecke
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work
Cc: Bill Wood

Maybe you could try to compile the same thing with libaxiom?

Martin

Ralf Hemmecke writes:

> I think you have just found a bug in the Axiom interpreter/compiler.
> 
> The following Aldor program compiles fine.
> 
> aldor -fx -laldor aaa.as
> 
> and gives as output
> 
> xs = [
>    [0, 0]
>    [0, 0]
>    [10, 0]
> ]
> 
> ys = [
>    [0, 0]
>    [0, 0]
>    [10, 0]
> ]
> 
> Don't be distracted by this output stuff (TextWriter). Your code basically
> appears in the main() function. And in Aldor that works.
> 
> Since this special form of assignment is actually a call to the function set!
> (Aldor) the line
> 
>    ys(2).k := 10;
> 
> is equivalent to
> 
>    set!(ys(2), k, 10);
> 
> There is no problem with the actual form of the first argument of set!. As long
> as there is a function
> 
>    set!: (R, Enumeration(k: Type), INT) -> INT
> 
> that should compile fine. Well, and "ys(2)" is of type R.
> (Of course, all this is Aldor specific, but Axiom should try hard to get close.)
> 
> I have no idea, though, why Axiom is unable to deal correctly with that
> expression. That should be dealt with by our compiler experts.
> 
> Ralf
> 
> 
> 
> 
> ---BEGIN aaa.as
> #include "aldor"
> #include "aldorio"
> 
> INT == MachineInteger;
> R ==> Record(k: INT, rad: INT);
> import from R, INT;
> 
> initrec(): R == [0,0];
> 
> (tw: TextWriter) <= (r: R): TextWriter == {
>    tw << "[" << r.k << ", " << r.rad << "]"
> }
> (tw: TextWriter) << (g: Generator R): TextWriter == {
>    tw << "[" << newline;
>    for r in g repeat tw << "  " <= r << newline;
>    tw << "]" << newline;
> }
> 
> 
> main(): () == {
>    xs: List R := [initrec() for i in 1..3];
>    ys: Array R := [z for z in xs];
>    ys(2).k := 10;
>    stdout << "xs = " << generator xs << newline;
>    stdout << "ys = " << generator ys << newline;
> }
> 
> main();---END aaa.as
> 
> On 08/08/2007 11:41 AM, Bill Wood wrote:
> > I'm just trying to assign to a field of a record in a one-dimensional
> > array of records, but I get this incomprehensible message:
> > =====================================================================
> > (1) -> )clear all
> >    All user variables and function definitions have been cleared.
> > (1) -> )read foo.input
> > -- File of Axiom definitions solving problem 124.
> > -- Created 2007/08/08 by Bill Wood.
> > init_rec() ==
> >   r : Record(k: INT, rad: INT) := [0,0]
> >   r
> >                                            Type: Void
> > (2) -> xs := [init_rec() for i in 1..3]
> >    Compiling function initrec with type () -> Record(k: Integer,rad:
> >       Integer)
> >    (2)  [[k= 0,rad= 0],[k= 0,rad= 0],[k= 0,rad= 0]]
> >                       Type: List Record(k: Integer,rad: Integer)
> > (3) -> ys := oneDimensionalArray(xs)
> > (3) ->
> >    (3)  [[k= 0,rad= 0],[k= 0,rad= 0],[k= 0,rad= 0]]
> >            Type: OneDimensionalArray Record(k: Integer,rad: Integer)
> > (4) -> ys
> > (4) ->
> >    (4)  [[k= 0,rad= 0],[k= 0,rad= 0],[k= 0,rad= 0]]
> >            Type: OneDimensionalArray Record(k: Integer,rad: Integer)
> > (5) -> ys(2).k := 10
> >  5) ->
> >    The form on the left hand side of an assignment must be a single
> >       variable, a Tuple of variables or a reference to an entry in an
> >       object supporting the setelt operation.
> > (5) ->
> > =======================================================================
> > What do I have to do to set the fields of the records to desired
> > values???

\start
Date: Wed, 8 Aug 2007 07:57:00 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: typo in the guessing package pamphlet,

On 8/8/07, Gabriel Dos Reis wrote:
> On Wed, 8 Aug 2007, Bill Page wrote:
> ...
> | What do expect the meaning of #2 and #3 to be?
> |
> | As I understand Spad syntax, if I write
> |
> |    ( #1 + #2 + #3 )
> |
> | this is a shorthand for the following anonymous function
> |
> |   (x,y,z) +-> x + y + z
> |
> | Is that correct?
>
> I think so.
>
> Note however, that in nested context, I believe the rules are a bit different.
> That is:
>
>     f(#1, g(#1, #2))
>
> would be equivalent to
>
>    x +-> f(x, (y, z) +-> g(y, z))
>
> However, I can't find a documentation for that.
>

Ahhh, I see! Excellent.

Now there is documentation. :-) Thank you.

\start
Date: Wed, 08 Aug 2007 14:17:47 +0200
From: Ralf Hemmecke
To: Martin Rubey
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work
Cc: Bill Wood

I guess, that should be moved to issue tracker, but I haven't yet used 
it, so please excuse that this is just a sandbox.

I also wanted to link to the mailing list, but the post is not yet 
visible in the archive. :-(

http://wiki.axiom-developer.org/SandboxSetEltProblem

Ralf

On 08/08/2007 01:36 PM, Martin Rubey wrote:
 > Maybe you could try to compile the same thing with libaxiom?

\start
Date: 08 Aug 2007 14:51:48 +0200
From: Martin Rubey
To: Ralf Hemmecke
Subject: re: [Axiom-mail] Assigning to Element of Array	of Records Doesn't Seem to Work
Cc: Bill Wood

Ralf Hemmecke writes:

> I think you have just found a bug in the Axiom interpreter/compiler.

I just did the following:

-- assign.as --------------------------------------------------
#include "axiom"

INT ==> Integer;
R ==> Record(k: INT, rad: INT);
import from R, INT;

initrec(): R == [0,0];

main(): PrimitiveArray R == {
   xs: List R := [initrec() for i in 1..3];
   import from PrimitiveArray R, List R;
   ys: PrimitiveArray R := construct [z for z in xs];
   ys(2).k := 10;
   ys;
}
----------------------------------------------------------------

(1) -> )co assign
   Compiling AXIOM source code from file 
      /users/rubey/aldor-test/assign.as using AXIOM-XL compiler and 
      options 
-O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom -Y $AXIOM/algebra
      Use the system command )set compiler args to change these 
      options.
#1 (Warning) Deprecated message prefix: use `ALDOR_' instead of `_AXL'
   Compiling Lisp source code from file ./assign.lsp
   Issuing )library command for assign
   Reading /users/rubey/aldor-test/assign.asy
(1) -> main()

   (1)  [[k= 0,rad= 0],[k= 0,rad= 0],[k= 10,rad= 0]]
                         Type: PrimitiveArray Record(k: Integer,rad: Integer)

So it really really really should go away.

\start
Date: Wed, 08 Aug 2007 15:06:59 +0200
From: Ralf Hemmecke
To: list
Subject: Successful build-improvements compilation

Dear Gaby,

after I have removed /home/hemmecke/config from my PATH variable, I want 
to report a successful build.

But it is not completely obvious to me that with

~/SVK/axiom/branches/build-improvements/configure 
--prefix=/home/hemmecke/scratch/AXIOM

make

make install

I get the following:

woodpecker:~/scratch/AXIOM>ls -l
total 12
-rwxr-xr-x 1 hemmecke hemmecke 4953 2007-08-08 14:52 bin
drwx------ 3 hemmecke hemmecke 4096 2007-08-08 14:51 lib

Yes, "bin" is the axiom shell script not a directory.
That should be a bug, right?

Anyway, if I start "bin", I get the following message, see below.

Doesn't build-improvements come with hyperdoc? That would be a big minus.

Ralf
-----------------------------------------------------------------
woodpecker:~/scratch/AXIOM>bin
/bin/sh: 
/home/hemmecke/scratch/AXIOM/lib/axiom/target/i686-pc-linux/bin/hypertex: 
No such file or directory
/bin/sh: line 0: exec: 
/home/hemmecke/scratch/AXIOM/lib/axiom/target/i686-pc-linux/bin/hypertex: 
cannot execute: No such file or directory
GCL (GNU Common Lisp)  2.6.8 CLtL1    Aug  8 2007 11:35:36
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License:  GPL due to GPL'ed components: (BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/hemmecke/
                         AXIOM Computer Algebra System
              Version: Axiom build-improvements branch 2007-06-21
               Timestamp: Wednesday August 8, 2007 at 12:42:42
-----------------------------------------------------------------------------
    Issue )copyright to view copyright notices.
    Issue )summary for a summary of useful system commands.
    Issue )quit to leave AXIOM and return to shell.
-----------------------------------------------------------------------------

\start
Date: 08 Aug 2007 08:54:35 -0500
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Successful build-improvements compilation

Ralf Hemmecke writes:

| Dear Gaby,
| 
| after I have removed /home/hemmecke/config from my PATH variable, I
| want to report a successful build.

Thanks!

| 
| But it is not completely obvious to me that with
| 
| ~/SVK/axiom/branches/build-improvements/configure
| --prefix=/home/hemmecke/scratch/AXIOM
| 
| make
| 
| make install
| 
| I get the following:
| 
| woodpecker:~/scratch/AXIOM>ls -l
| total 12
| -rwxr-xr-x 1 hemmecke hemmecke 4953 2007-08-08 14:52 bin
| drwx------ 3 hemmecke hemmecke 4096 2007-08-08 14:51 lib
| 
| Yes, "bin" is the axiom shell script not a directory.
| That should be a bug, right?

You're found a bug.

For some reason, I cannot reproduce it here -- I just tested.
Maybe I have to start with a different machine.

| Anyway, if I start "bin", I get the following message, see below.
| 
| Doesn't build-improvements come with hyperdoc? That would be a big minus.

It does come with hyperdoc.  It looks to me that you've found another
bug.

Many thanks for the report.

\start
Date: Wed, 08 Aug 2007 16:37:52 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: Successful build-improvements compilation

Hi Gaby,

> | Doesn't build-improvements come with hyperdoc? That would be a big minus.

> It does come with hyperdoc.  It looks to me that you've found another
> bug.

Tell me whatever you need. I can zip my build directory

~/OTHER/Axiom/out-of-source-build-improvements

if you think that is helpful (about 118784487 bytes). Otherwise just 
tell me what you need.

\start
Date: 08 Aug 2007 09:57:02 -0500
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Successful build-improvements compilation

Ralf Hemmecke writes:

| Hi Gaby,
| 
| > | Doesn't build-improvements come with hyperdoc? That would be a big minus.
| 
| > It does come with hyperdoc.  It looks to me that you've found another
| > bug.
| 
| Tell me whatever you need. I can zip my build directory

I believe the second bug is a consequence of the first bug.
I should be able to fix the first bug shortly.

\start
Date: Wed, 08 Aug 2007 17:02:24 +0200
From: Ralf Hemmecke
To: Martin Rubey
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work
Cc: Bill Wood

Unfortunately, I don't know how to compile SPAD code inside MathAction.

The following program demonstrates that the issue
http://lists.nongnu.org/archive/html/axiom-mail/2007-08/msg00012.html
is an interpreter (not a SPAD compiler) problem.

Ralf

(1) -> )co bbb.spad
(1) -> zs := myfoo2()
    (1)  [[k= 0,rad= 0],[k= 10,rad= 0],[k= 0,rad= 0]]
    Type: OneDimensionalArray Record(k: Integer,rad: Integer)



---BEGIN bbb.spad
)abbrev package BBB MyPkg

INT==> Integer
R ==> Record(k: INT, rad: INT)

MyPkg(): with
   myfoo2: () -> OneDimensionalArray R
  == add
   initrec2(): R == [0,0]

   myfoo2(): OneDimensionalArray R ==
     xs: List R := [initrec2() for i in 1..3]
     ys: OneDimensionalArray R := oneDimensionalArray(xs)
     ys(2).k := 10
     ys
---END bbb.spad

\start
Date: Wed, 8 Aug 2007 11:24:51 -0400
From: Bill Page
To: Ralf Hemmecke
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work

On 8/8/07, Ralf Hemmecke wrote:
> Unfortunately, I don't know how to compile SPAD code inside MathAction.
> ...

??? Where have you been the last two years?!

I can't believe you said that! :-( Take a look at any page on the
Axiom wiki containing Spad code. Click 'edit' and you can see how it
is done.

I have updated the page:

http://wiki.axiom-developer.org/AxiomProgramming

just for you. :-)

\start
Date: Wed, 08 Aug 2007 17:46:01 +0200
From: Ralf Hemmecke
To: Bill Page
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work

On 08/08/2007 05:24 PM, Bill Page wrote:
> On 8/8/07, Ralf Hemmecke wrote:
>> Unfortunately, I don't know how to compile SPAD code inside
>> MathAction. ...
> 
> ??? Where have you been the last two years?!

Oh, Bill, please don't be angry with me. ;-)

> I can't believe you said that! :-( Take a look at any page on the 
> Axiom wiki containing Spad code. Click 'edit' and you can see how it 
> is done.
> 
> I have updated the page:
> 
> http://wiki.axiom-developer.org/AxiomProgramming
> 
> just for you. :-)

I would have guessed \begin{spad} but clicking on "Axiom" at the bottom of

   http://wiki.axiom-developer.org/SandboxSetEltProblem/editform

did not give any hint about the spad environment.
Maybe you could change that link to point to AxiomProgramming
instead of AxiomTutorial?

Can I claim that this could count as a bug?

\start
Date: Wed, 8 Aug 2007 12:36:07 -0400
From: Bill Page
To: Ralf Hemmecke
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work

On 8/8/07, Ralf Hemmecke wrote:
> On 08/08/2007 05:24 PM, Bill Page wrote:
> > On 8/8/07, Ralf Hemmecke wrote:
> >> Unfortunately, I don't know how to compile SPAD code inside
> >> MathAction. ...
> ...
> I would have guessed \begin{spad} but clicking on "Axiom" at the bottom of
>
>    http://wiki.axiom-developer.org/SandboxSetEltProblem/editform
>
> did not give any hint about the spad environment.
> Maybe you could change that link to point to AxiomProgramming
> instead of AxiomTutorial?
>
> Can I claim that this could count as a bug?
>

Ok. Bug fixed.

Thanks for the feedback. It seems that I hardly ever hear from anyone
using the Axiom wiki this way. Maybe this will help.

Let me know if you find anything else missing or unclear.

\start
Date: 08 Aug 2007 19:44:01 +0200
From: Martin Rubey
To: Bill Page
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work

Bill Page writes:

> > I would have guessed \begin{spad} but clicking on "Axiom" at the bottom of
> >
> >    http://wiki.axiom-developer.org/SandboxSetEltProblem/editform
> >
> > did not give any hint about the spad environment.  Maybe you could change
> > that link to point to AxiomProgramming instead of AxiomTutorial?

> Ok. Bug fixed.

Bill, it seems you duplicated the material from AxiomProgramming in
AxiomTutorial.  Don't you think it would be better to just provide a ink to
AxiomProgramming in AxiomTutorial?  I'm a little afraid that maintaining will
be harder in future.

I moved the material from SandBoxSetEltProblem into IssueTracker.  Ralf: to add
a new issue, just click on bug report, fill out the comment box, click add
issue.  After that you can edit the Issue just as any other page.

\start
Date: Wed, 8 Aug 2007 14:28:39 -0400
From: Bill Page
To: Martin Rubey
Subject: re: [Axiom-mail] Assigning to Element of Array of Records Doesn't Seem to Work

On 08 Aug 2007 19:44:01 +0200, Martin Rubey wrote:
> ...
> Bill, it seems you duplicated the material from AxiomProgramming in
> AxiomTutorial.  Don't you think it would be better to just provide a ink to
> AxiomProgramming in AxiomTutorial?  I'm a little afraid that maintaining will
> be harder in future.
> ...

You are right. I have removed the redundant parts from each page and
provided links from one to the other. I prefer to leave the
information about how to use Spad etc. in the wiki pages in the
AxiomTutorial page and remove it from AxiomProgramming since
AxiomTutorial is the page that is accessed in one click from the
"Axiom" help link in the editing assistant panel at the bottom of the
page.

\start
Date: Thu, 9 Aug 2007 00:08:47 -0500
From: Tim Daly
To: list
Subject: Jenks notes

Plowing thru my local library I came across this note from Dick Jenks.
Figured it might be of interest.



Every object belongs to a unique class: the class has a name called
the "type" of the object.  An object is called "basic" if the object
is itself not a class of objects.  A "basic class" is a class of basic
objects.

Every class of objects specifies a class of "functions" that usually,
but not necessarily, either create or otherwise manipulate an object
of the class. Functions denote executable procedures which take an
argument and return a value.

Functions are objects. They belong to the class Map (the class of all
maps).  Map is a primitve type whose objects are described by a
signature (syntax) of the form: A -> B where A and B are types.

Classes are objects. They belong to (a metaclass of basic objects
called) a "category".  Categories are objects belonging to the unique
class Category (the class of all categories), a subclass of Class (the
class of all classes).

Primitive types include Category, Class, Map, and Type (the class of 
all types -- that is, the class of all names of possible Axiom classes).
Also primitive are Tuples (of the form (A,...,B)), and Records and
Unions (of the form (a:A,...,b:B)).

A class A is a "subclass" of B (also, B is a "superclass" of A) if
there is an operation: "<: A -> B". The meaning of this operation is:
"If x is an instance of A, then x is also an instance of B". In
general, a class has many superclasses. If A < B and B < A, then A and
B are said to belong to a "class cycle".

Specification is orthogonal to implementation. Moreover, the
represenation of objects of a class need not be records (as is
customary in OOPLs) but may be any other class. Thus a linked list can
be implemented by a record, a sparse vector by a linked list, a sparse
matrix by a sparse vector, a graph by a sparse matrix. The
representation of a category is primitive.

The representation of a class in general is independent of that of a
superclass. the implementation of the operation "<: A -> B" operation
describes how an object of type A must be transformed in order to
become an instance of B.

For example, consider the chain:

 DiagonalMatrix < (BandedMatrix, SquareMatrix) < SquareMatrix
   < Matrix < 2DArray

Here, by the designer's choise, the last 3 use the same representation
(vector of vectors). Diagonal matrices and banded matrices use a more
economical representation. Common operations such as determinant and
trace are exported from the first 3 types, each impleented in their
own economical way. But more obscure operations such as "permanent"
may be defined only on square matrices. To perform this operation, a
banded matrix object must first be converted to a square matrix
operation. 

Categories correspond to abstract classes in C++. Unlike C++, however,
categories have instances, namely the classes of basic objects which
are its members. A category generall "<" another category. Hoever,
since categories all have the same (primitive) representation, the 
"<" operation between categories is always the identity function.

Note however that "<" is not equivalent to "embed". The number 2 is an
integer. Since Integer < RationalNumber, 2 is also a rational
number. However RationalNumber is a field. Since Field < Ring,
RationalNumber is also a ring.

All non-primitive classes are created by maps. The map
  "Integer: () -> Union(EuclideanDomain,OrderedSet,UFD)"
is the operation that creates the class of all integers. Most classes
are created by operations with parameters. The map
  "Fraction: IntegralDomain -> IntegralDomain with .."
is an operation taking a class as an argument and returning a class as
value. RationalNumber is a macro defined as Fraction(Integer).

A category also denotes a class, a metaclass of basic objects, and
therefore is also created by a map. Examples of parameterized
categories are:
  Module: Ring -> Category
  OrderedSet: ((Self,Self) -> Boolean) -> Category
(that is, OrderedSet takes a boolean-valued ordering operation as an
argument. 

A class generally implements methods (functions) for the operations
described by its type. When a method is not prescribed by a class, the
method is found by searching its defaults and its hierarchy.

A purpose of a class hierarchy is to find an operation. If x has class
A and foo(x) is defined, then the foo from A is applied. Otherwise if
A < B, look in B for foo and so on.

The purpose of a category hierarchy is polymorphism. The polymorphic
function sort can be defined as follows:
  S: OrderedSet
  A: FiniteIterableAggregate(S) with shallowlyMutable
  sort(A,(S,S)->Boolean) -> A

The first line means S is of type OrderedSet, a category denoting the
class of all ordered sets. Examples of ordered sets are Integer (the
class of all integers), and so on, which, when defined, declare
themselves to have type OrderedSet, e.g.
  Integer: (...,OrderedSet,...) == implementation

The second line says that A is a finite iterable aggregate with the
"attribute" shallowlyMutable. Such aggreates have finite length and
have an iterator to walk over the successive elements. 
ShallowlyMutable is an attribute meaning that the elements of the
aggregate can be change "in place". Examples of data structures are
lists, strings, vectors, and so on.

\start
Date: Thu, 09 Aug 2007 11:06:32 +0200
From: Ralf Hemmecke
To: Martin Rubey
Subject: Re: [JenksNotes] (new) Notes of Dick Jenks

Why did you write to axiom-mail?

On 08/09/2007 10:58 AM, Martin Rubey wrote:
> Dear Ralf,
> 
> thanks for putting this online.  However, one general thing:  please avoid
> usage of 
> 
>> \begin{verbatim}
> 
> long text
> 
>> \end{verbatim}
> 
> since this causes the long text to be saved and downloaded as an image, which
> is a nuisance if your internet connection is not that good.

Oh, I did not know that. Sorry. I've changed it and it seems to look 
readable, as well.

\start
Date: Thu, 9 Aug 2007 16:07:02 +0200 (CEST)
From: Franz Lehner
To: list
Subject: aldor stream oddities

is there a way to get hold of generate$Stream using the aldor compiler?
I spent quite some time until figuring out that generate is probably
a keyword in aldor (I could not check as the aldor site seems to be down)
and this causes strange error messages.
The following two snippets do not work, note that the second leads to a 
segfault:

=================================================
#include "axiom"

teststream: with {
         zerostream:()->Stream Integer;
} == add {
         zerostream():Stream Integer == {
                 import from Integer;
                 generate((x:Integer):Integer +-> 0@Integer,0@Integer);
}
}
=================================================
aldor -Fasy -Fao -Flsp  -laxiom -DAxiom -Y/home/lehner/usr/local/lib/wh-sandbox_s1/target/x86_64-unknown-linux/algebra test1.as
"test1.as", line 8:
                 generate((x:Integer):Integer +-> 0@Integer,0@Integer);
.........................^
[L8 C26] #1 (Error) Have determined 1 possible types for the expression.
         Meaning 1: (x: Integer) -> Integer, Integer
   The context requires an expression of type Stream(Integer).

make: *** [test.ao] Fehler 1

=========================================================
#include "axiom"

teststream: with {
         zerostream:()->Stream Integer;
} == add {
         zerostream():Stream Integer == {
                 import from Integer;
                 generate(():Integer +-> 0@Integer);
}
}
=========================================================
aldor -Fasy -Fao -Flsp  -laxiom -DAxiom -Y/home/lehner/usr/local/lib/wh-sandbox_s1/target/x86_64-unknown-linux/algebra test2.as
Program fault (segmentation violation).#3 (Error) Program fault 
(segmentation violation).
"test2.as", line 6:         zerostream():Stream Integer == {
                    .......................................^
[L6 C40] #1 (Error) Have determined 0 possible types for the expression.
   Subexpression `import from Integer':
         Meaning 1: (0 types)

"test.as", line 9:                 generate(():Integer +-> 0@Integer);
                    .........................^
[L9 C26] #2 (Error) Have determined 0 possible types for the expression.

make: *** [test.ao] Fehler 1

\start
Date: 09 Aug 2007 17:34:34 +0200
From: Martin Rubey
To: Franz Lehner
Subject: Re: aldor stream oddities

Franz Lehner writes:

> is there a way to get hold of generate$Stream using the aldor compiler?

Not easily, because:

> I spent quite some time until figuring out that generate is probably
> a keyword in aldor 

yes it is.

I wrote the following hack to be able to coerce Aldor generators to Axiom
Streams. Maybe this is of help.

What the thing below really does is to make "delay" available to Aldor, only
under a different name, because delay is a keyword in Aldor, too, I think.

--combinat/src/examples.as-------------------------------------------------

The following makes generators coercible to streams in \xAxiom.  Be warned,
however, that the coercion steps the generator.

<<ext: Generator>>=
extend Generator(S:Type): with {
        CoercibleTo Stream S;
} == add {
        <<get the magic NonNullStream symbol>>
        myDelay(f: () -> Stream S): Stream S == {
                [NonNullStream, f pretend Stream S]$REC pretend Stream S;
        }
        coerce(x: %): Stream S == {
                aux(): Stream S == {
                        import from Partial S;
                        n := partialNext! x pretend Partial S; 
                        if failed?(n)$Partial(S)
                        then empty()
                        else cons(retract(n)$Partial(S), myDelay aux);
                }
                myDelay(aux);
        }
}
@

The following piece of code fetches the magic \adcode|NonNullStream| symbol
used in \xAxiom{} to indicate a lazy stream.  As we can see in
stream.spad.pamphlet, a lazy stream is represented as follows:
\begin{adsnippet}
    NullStream:    S := _$NullStream$Lisp    pretend S
    Rep := Record(firstElt: S, restOfStream: %)
    delay(fs:()->%) == [NonNullStream, fs pretend %]
\end{adsnippet}

Unfortunately, the \adcode|delay| function is not available via libaxiom, so we
have to provide our own.  The only tricky part is to get hold of the lisp
symbol \adcode|$NullStream$Lisp|.  We are in luck however, since the libaxiom
exports a lazy stream via \adcode|integers$StreamTaylorSeriesOperations|.  More
precisely, its first element is non-lazy, but the second is.

<<get the magic NonNullStream symbol>>=
        import from Integer, StreamTaylorSeriesOperations Integer;
        import from Stream Integer;
        REC == Record(firstElt: S, restOfStream: Stream S);
        import from REC;
        NonNullStream: S := ((rst integers 0) pretend REC).firstElt;
@

\start
Date: Thu, 9 Aug 2007 11:55:37 -0400
From: Bill Page
To: Franz Lehner
Subject: Re: aldor stream oddities

On 8/9/07, Franz Lehner wrote:
> Hello,
>
> is there a way to get hold of generate$Stream using the aldor compiler?
> I spent quite some time until figuring out that generate is probably
> a keyword in aldor (I could not check as the aldor site seems to be down)
> and this causes strange error messages.
...

Yes. See the example at:

http://wiki.axiom-developer.org/SandBoxAldorGenerator#msg20070809105309-0500@wiki.axiom-developer.org

"The important thing is to escape the keyword generator by prefix with _."

\start
Date: Thu, 09 Aug 2007 18:08:22 +0200
From: Ralf Hemmecke
To: Bill Page
Subject: Re: aldor stream oddities
Cc: Franz Lehner

Hello,

I was about to finish my answer, (see below) but the "_"-trick is by far 
better.

Ralf

> http://wiki.axiom-developer.org/SandBoxAldorGenerator#msg20070809105309-0500@wiki.axiom-developer.org


Hi Franz,

On 08/09/2007 04:07 PM, Franz Lehner wrote:
 > Hello,
 >
 > is there a way to get hold of generate$Stream using the aldor
 > compiler? I spent quite some time until figuring out that generate
 > is probably a keyword in aldor (I could not check as the aldor
 > site seems to be down) and this causes strange error messages.

generate is a keyword in Aldor.

 > =================================================
 > #include "axiom"
 >
 > teststream: with {
 >         zerostream:()->Stream Integer;
 > } == add {
 >         zerostream():Stream Integer == {
 >                 import from Integer;
 >                 generate((x:Integer):Integer +-> 0@Integer,0@Integer);
 > }
 > }
 > =================================================

I think you are out of luck here.

The definition in stream.spad is

     generate f    == delay concat(f(), generate f)
     gen:(S -> S,S) -> %
     gen(f,s) == delay(ss:=f s; concat(ss, gen(f,ss)))
     generate(f,s)==concat(s,gen(f,s))

which could mean that you could try to define your own
"mygenerate" instead of "generate". The tricky thing then is "delay".
That is yet another keyword (unused though) in Aldor.

The definition of "delay" in that file is

     delay(fs:()->%) == [NonNullStream, fs pretend %]

So you have to give a definition for "mydelay", as well.

The hardest part is "NonNullStream". It's definition is

     NonNullStream: S := _$NonNullStream$Lisp pretend S

But the following works in Axiom. As you see, lot's of "pretend"s. So 
don't try that at home.

Say

)co aaa.as
zerostream()

---BEGIN aaa.as
#include "axiom"

MyStream(S: Type): with {
   mygenerate: (() -> S) -> %;
   mygenerate: (S -> S,S) -> %;
} == Stream S add {
   Rep == Record(firstElt: S, restOfStream: %);
   macro st x == x pretend Stream S;
   import from Rep;
   s: S == (1$Integer) pretend S; -- we need an element that we never access
   ls: List S == [s]; -- auxiliary
   import from Integer, StreamTaylorSeriesOperations Integer;
   import from Stream Integer;
   REC == Record(firstElt: S, restOfStream: Stream S);
   import from REC;
   NonNullStream: S == ((rst integers 0) pretend REC).firstElt;
   mydelay(fs:()->%): % == per [NonNullStream, fs pretend %];
   mygenerate(f: ()->S): % == {
	  fs(): % == concat(f(), st mygenerate f) pretend %;
	  mydelay fs;
   }
   gen(f: S -> S, s: S): % == {
	  fs(): % == {ss := f s; concat(ss, st gen(f, ss)) pretend %};
	  mydelay fs;
   }
   mygenerate(f: S->S, s: S): % == concat(s, st gen(f, s)) pretend %
}

MyStreamPackage(S: Type): with {
   mygenerate: (() -> S) -> Stream S;
   mygenerate: (S -> S,S) -> Stream S;
} == add {
   mygenerate(f: ()->S): Stream S == {
     (mygenerate(f)$MyStream(S)) pretend Stream(S);
   }
   mygenerate(f: S->S, s: S): Stream S == {
     (mygenerate(f, s)$MyStream(S)) pretend Stream(S);
   }
}


TestStream: with {
   zerostream:()->Stream Integer;
} == add {
   zerostream():Stream Integer == {
     import from Integer, MyStreamPackage(Integer);
     mygenerate(():Integer +-> 0@Integer);
   }
   onestream():Stream Integer == {
     import from Integer, MyStreamPackage(Integer);
     mygenerate(():Integer +-> 1@Integer);
   }
}
---END aaa.as

\start
Date: 09 Aug 2007 11:54:00 -0500
From: Gabriel Dos Reis
To: list
Subject: InteractiveMode

The variable InteractiveMode used in function postError (postpar.boot)
is a typo for $InteractiveMode.

\start
Date: 09 Aug 2007 12:23:00 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: newrule from metalex.lisp

The routine NEWRULE from metalex.lisp contains the following:

  (test Rule1)

That line should read

  (test "RULE1")

\start
Date: Thu, 9 Aug 2007 13:04:06 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: newrule from metalex.lisp

> The routine NEWRULE from metalex.lisp contains the following:
>
> (test Rule1)
>
> That line should read
>
> (test "RULE1")

I don't know where metalex is used anymore. 
The meta language was removed years ago and rewritten into lisp.
The zips/meta.tar file is the last remaining evidence.

I'm not sure I can make a reasonable comment on a change like this.
I have no idea what you're thinking about. 
I have no idea what bug this causes.
I see no broken-before, fixed-after test cases.
I see no documentation.
I see no patch/build/test cycles or evidence of testing.
I see no diff-Naur patch against silver.

I know that when you encounter a bug and make a fix it is painfully
obvious what needs to be done, why you need to do it, how you should
fix it, where to change the source, and how to test the result. The
fix is probably a good fix. But unless you share this information
there is no way to know.

You remember the struggles we had trying to decode Martin's code
without documentation? This change is exactly like that.

So, I'll ask the same question I asked Steve with his i-output fix...

Can you show an example where it breaks before the change 
and is fixed after the change?

\start
Date: Thu, 9 Aug 2007 13:34:23 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: newrule from metalex.lisp

On Thu, 9 Aug 2007, Tim Daly wrote:

| Gaby,
| 
| > The routine NEWRULE from metalex.lisp contains the following:
| >
| > (test Rule1)
| >
| > That line should read
| >
| > (test "RULE1")
| 
| I don't know where metalex is used anymore. 

If metalex is no longer used, then we should just remove it :-)
I'm all for unused Lisp codes that go away.


| The meta language was removed years ago and rewritten into lisp.
| The zips/meta.tar file is the last remaining evidence.
| 
| I'm not sure I can make a reasonable comment on a change like this.

Well, obviously I did not invent the fix from thin air :-)  
Here is what is happening.

I've modifications in a local tree that has all of depsys, interpsys, codes 
completely compiled!  Yes, I remember you said a long time ago that 
depsys needs to run interpreted because of some macros.  I was not convinced
for various reasons.  The current practice of depsys is only because of poor
structure.

The first thing to do to get rid of the 'some macros' stonewall is to
sequester those macros is a separate file, compile them and load them while
compiling functions/files that make use of them.

The second thing I did was to wrap COMPILE-FILE to report back to me whether
there was FAILURE-P or WARNING-P (Common Lisp semantics).  
I made bootsys (and other basis Lisps src/lisp) return non-zero exit when
FAILURE-P is set, so that Make can stop the build.  FAILURE-P means
there might be other diagnostic ecept STYLE-WARNING conditions.
Then I systematically examine the condition that led to the failure.

In this specific case, I was compiling metalex.lisp and bootsys reported back
that the variable Rule1 was undefined.  Then I looked at the file, what it was
trying to do, then eventually trace back to the macro TEST from
bootlex.lisp:

   (defmacro test (x &rest y)
     `(progn
	(setq spaderrorstream t)
	(in-boot)
	(initialize-preparse *terminal-io*)
	(,(intern (strconc "PARSE-" x)) . ,y)))

which is supposed to call the function PARSE-RULE1 from metameta.lisp.
Using type inference, it is "clear" that (strconc "PARSE-" x) works
only if x is of type string, thus the fix.

Now, if you think the whole metameta stuff can go away, I'm all for it --
though I'm not sure it would work (I haven't tried).


| I have no idea what you're thinking about. 
| I have no idea what bug this causes.
| I see no broken-before, fixed-after test cases.

It is not true that there is nothing broken.  The code is obviously wrong as
written since it references a variable that is never defined either statically
nor dynamically.  Beause hat is simply a typo.

| I see no documentation.

Tell that to the those who wrote the uncommented stuff. :-)

| I see no patch/build/test cycles or evidence of testing.
| I see no diff-Naur patch against silver.

I leave this up to you and for another time.

[...]

| You remember the struggles we had trying to decode Martin's code
| without documentation? This change is exactly like that.

I disagree.  I struggled to understand why the compiler is emitting a 
warning.  The struggle is because the *existing code is highly undocumented.*
The history of the typo fix is uninteresting tomorrow, or even 30 years from
now.  Once the typo is fix.  The documentation should explain the purpose of
the codes and how it does the code, not explain how every single typo was
fixed.


Can you explain why the existing code is correct as written?

\start
Date: Thu, 9 Aug 2007 13:46:21 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: newrule from metalex.lisp

Gaby,

Thanks for the explanation. Now the change makes sense.

Tim wrote:
>> I see no diff-Naur patch against silver

Gaby wrote:
> I leave this up to you and for another time.

Why?

\start
Date: 09 Aug 2007 14:47:46 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: re: newrule from metalex.lisp

Gabriel Dos Reis writes:

> On Thu, 9 Aug 2007, Tim Daly wrote:
> 
> | Gaby,
> | 
> | > The routine NEWRULE from metalex.lisp contains the following:
> | >
> | > (test Rule1)
> | >
> | > That line should read
> | >
> | > (test "RULE1")
> | 
> | I don't know where metalex is used anymore. 
> 
> If metalex is no longer used, then we should just remove it :-)
> I'm all for unused Lisp codes that go away.

I removed this code (and metameta.lisp) a while ago from the axisp
branch.  Never posted a patch since I was unsure if it was of interest
to others -- was planning to raise the issue eventually.  Is
metameta.lisp of iterest?  If not, I can post a patch within a day or
two removing both.

\start
Date: Thu, 9 Aug 2007 13:55:10 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: macro STEP

Tim --

I believe Spad defines the macro STEP (for iteration purposes, like COLLECT).
I'm unable to locate it right now.  Do you happen to know where it is defined? 

\start
Date: 09 Aug 2007 15:05:38 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: macro STEP

Hi Gaby,

Gabriel Dos Reis writes:

> Tim --
> 
> I believe Spad defines the macro STEP (for iteration purposes, like COLLECT).
> I'm unable to locate it right now.  Do you happen to know where it is defined? 

It has been a while since I looked at this, but I have a vivid
recollection that STEP is effectively an IR meta-op, never emitted
into actual code -- thus not defined as a macro or similar.

\start
Date: Thu, 9 Aug 2007 14:11:45 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: macro STEP

On Thu, 9 Aug 2007, Stephen Wilson wrote:

| Hi Gaby,
| 
| Gabriel Dos Reis writes:
| 
| > Tim --
| > 
| > I believe Spad defines the macro STEP (for iteration purposes, like COLLECT).
| > I'm unable to locate it right now.  Do you happen to know where it is defined? 
| 
| It has been a while since I looked at this, but I have a vivid
| recollection that STEP is effectively an IR meta-op, never emitted
| into actual code -- thus not defined as a macro or similar.

You're exactly right.  Shortly after I sent my message, I discovered that
it isn't a macro, but a non-executable opcode that is taken care of by the
macro -REPEAT.  And your message came while I was composing the one
instructing to disregard my query.

Sorry for the noise.

\start
Date: Thu, 9 Aug 2007 21:33:22 +0200
From: Juergen Weiss
To: Stephen Wilson, Gabriel Dos Reis
Subject: re: newrule from metalex.lisp

In principle metalex.lisp is used to generate fnewmeta.lisp
from fnewmeta.meta (and metameta.lisp from metameta.meta).
metameta.meta is a parser generator written in itself. The
grammar of the old parser (for the SPAD compiler) is
defined in the file fnewmeta.meta.

Seems that someone did not like this setup and removed
some files. The remaining parts do not make much sense
anymore. So one solution is to eliminate the remnants,
the other to get the files from the archives (tar file)
and add some rules in the Makefiles.

> -----Original Message-----
> From: axiom-developer-bounces+weiss=uni-mainz.de@nongnu.org
>  On Behalf Of Stephen Wilson
> Sent: Thursday, August 09, 2007 8:48 PM
> To: Gabriel Dos Reis
> Cc: list
> Subject: re: newrule from metalex.lisp
>
> Gabriel Dos Reis writes:
>
> > On Thu, 9 Aug 2007, Tim Daly wrote:
> >
> > | Gaby,
> > |
> > | > The routine NEWRULE from metalex.lisp contains the following:
> > | >
> > | > (test Rule1)
> > | >
> > | > That line should read
> > | >
> > | > (test "RULE1")
> > |
> > | I don't know where metalex is used anymore.
> >
> > If metalex is no longer used, then we should just remove it :-)
> > I'm all for unused Lisp codes that go away.
>
> I removed this code (and metameta.lisp) a while ago from the axisp
> branch.  Never posted a patch since I was unsure if it was of interest
> to others -- was planning to raise the issue eventually.  Is
> metameta.lisp of iterest?  If not, I can post a patch within a day or
> two removing both.

\start
Date: Thu, 9 Aug 2007 14:33:31 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: metalex change 

Gaby,

 (test 'rule1)

eventually does a call to strconc, a vmlisp function.
The strconc function is defined in vmlisp.lisp as
  
  (define-function 'strconc #'concat)

The concat function is defined in vmlisp.lisp as a call to

  (system:string-concatenate a b)

If you call:

  (strconc "PARSE-" 'rule1)

you get

  "PARSE-RULE1"

so the original code is correct as written.

\start
Date: Thu, 9 Aug 2007 14:37:33 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: metalex change 

Actually, we're both incorrect. The argument is missing a quote.

\start
Date: Thu, 9 Aug 2007 14:52:32 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: metalex change 

On Thu, 9 Aug 2007, Tim Daly wrote:

| Gaby,
| 
| Actually, we're both incorrect. The argument is missing a quote.

Why is it a quote when strconc is defined as synonymous to concat
(see vmlisp.lisp) and concat itself is defined as


   #-AKCL
   (defun concat (a b &rest l)
      (let ((type (cond ((bit-vector-p a) 'bit-vector) (t 'string))))
	 (cond ((eq type 'string)
		(setq a (string a) b (string b))
		(if l (setq l (mapcar #'string l)))))
	 (if l (apply #'concatenate type a b l)
	   (concatenate type a b))) )
   #+AKCL
   (defun concat (a b &rest l)
     (if (bit-vector-p a)
	 (if l (apply #'concatenate 'bit-vector a b l)
	   (concatenate 'bit-vector a b))
       (if l (apply #'system:string-concatenate a b l)
	 (system:string-concatenate a b))))


??


(I'm using SBCL to type check the codes, but I don't think it matters much.  
Furthermore, I think we should just have one definition).

\start
Date: Thu, 9 Aug 2007 14:54:27 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: metalex change 

On Thu, 9 Aug 2007, Tim Daly wrote:

| Gaby,
| 
|  (test 'rule1)
| 
| eventually does a call to strconc, a vmlisp function.
| The strconc function is defined in vmlisp.lisp as
|   
|   (define-function 'strconc #'concat)
| 
| The concat function is defined in vmlisp.lisp as a call to
| 
|   (system:string-concatenate a b)
| 
| If you call:
| 
|   (strconc "PARSE-" 'rule1)
| 
| you get
| 
|   "PARSE-RULE1"
| 
| so the original code is correct as written.

No, the orignal code did not have a quote -- that is how the SBCL compiler
discover the bugs.  It was plain Rule1 without quote.

Also, if the function expects strings, we should give it a string.

\start
Date: Thu, 9 Aug 2007 14:59:23 -0500 (CDT)
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: re: newrule from metalex.lisp

On Thu, 9 Aug 2007, Weiss, Juergen wrote:

| In principle metalex.lisp is used to generate fnewmeta.lisp
| from fnewmeta.meta (and metameta.lisp from metameta.meta). 
| metameta.meta is a parser generator written in itself. The
| grammar of the old parser (for the SPAD compiler) is
| defined in the file fnewmeta.meta. 
| 
| Seems that someone did not like this setup and removed
| some files. The remaining parts do not make much sense
| anymore. So one solution is to eliminate the remnants,
| the other to get the files from the archives (tar file)
| and add some rules in the Makefiles.


Hi Juergen,  thanks for the background.

You're quite right the current situation is confusing.  The current
interpreter uses the new parser (cparse.boot), while the compiler
uses the old parser whose grammar is generated as you describe above.
Except that the grammar is not actually generated anymore: instead the 
corresponding Lisp is cached.  I believe it would make sense that
both the interpreter and the compiler uses the same parser, to reduce
confusion in syntax, etc.  From that perspective, I would think that the long
term would be to remove the remanants.

Would you object to moving to the new parser (cparse.boot)?

\start
Date: Thu, 9 Aug 2007 16:07:26 -0400
From: Bill Page
To: Juergen Weiss
Subject: re: newrule from metalex.lisp
Cc: Gabriel Dos Reis

On 8/9/07, Weiss, Juergen wrote:
> In principle metalex.lisp is used to generate fnewmeta.lisp
> from fnewmeta.meta (and metameta.lisp from metameta.meta).
> metameta.meta is a parser generator written in itself. The
> grammar of the old parser (for the SPAD compiler) is
> defined in the file fnewmeta.meta.
>
> Seems that someone did not like this setup and removed
> some files. The remaining parts do not make much sense
> anymore. So one solution is to eliminate the remnants,
> the other to get the files from the archives (tar file)
> and add some rules in the Makefiles.
>

In

http://wiki.axiom-developer.org/AxiomDevelopment

"There is a third language used in the system called Meta. (Which is
why meta.tar exists in zips). This code is not part of the bootstrap
but needs to be at some point. Changing the meta parser (see
metameta.lisp, fnewmeta.lisp, and metalex.lisp) would surely cause
havoc. In the distributed system I replaced the Meta code with common
lisp."

-----

You probably know where my sympathy lies. I strongly believe that Tim
is right: "This code is not part of the bootstrap but needs to be at
some point." and I object to the continuing trend to reduce everything
to Lisp.

I think that meta is actually rather well documented (although the
code in Axiom may not be). See:

http://doi.acm.org/10.1145/1093415.1093417

META/LISP: an interactive translator writing system
Source 	ACM SIGSAM Bulletin archive
Issue 16  (October 1970) table of contents
Pages: 10 - 18
Year of Publication: 1970
ISSN:0163-5824
Author 	
R. D. Jenks 	 IBM Thomas J. Watson Research Center, Yorktown Heights, New York

http://doi.acm.org/10.1145/362896.362902

Referenced:

http://doi.acm.org/10.1145/800204.806291
http://www3.interscience.wiley.com/cgi-bin/abstract/113447317/ABSTRACT
http://doi.acm.org/10.1145/987508.987512

also in

Jenks, R.D.: META/PLUS: The Syntax Extension Facility for SCRATCHPAD,
IBM T.J. Watson Research Center, RC 3259, New York, Feb. 23, 1971

\start
Date: 09 Aug 2007 16:14:44 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: re: metalex change

Gabriel Dos Reis writes:
> Also, if the function expects strings, we should give it a string.

Although not documented as such, it is likely that
system:string-concatenate is designed to take string designators as
arguments instead of `just' strings.  This is a fairly common Lisp
idiom, so I do not see a problem.  Perhaps a close look at the gcl
code and a patch against the documentation in si-defs.texi is in
order.

\start
Date: 09 Aug 2007 16:19:41 -0400
From: Stephen Wilson
To: Stephen Wilson
Subject: re: metalex change
Cc: Gabriel Dos Reis

Stephen Wilson writes:

> Gabriel Dos Reis writes:
> > Also, if the function expects strings, we should give it a string.
> 
> Although not documented as such, it is likely that
> system:string-concatenate is designed to take string designators as
> arguments instead of `just' strings.  This is a fairly common Lisp
> idiom, so I do not see a problem.  Perhaps a close look at the gcl
> code and a patch against the documentation in si-defs.texi is in
> order.

Of course, that being said, it is a stylistic choice as to what
designator one uses.  In this case I would probably use a string
myself as opposed to a symbol.

\start
Date: 09 Aug 2007 15:20:26 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: SPECIALCASESYNTAX

  Speaking of meta meta and friends, the SBCL compiler chokes on the
following from newaux.lips


   (defun SPECIALCASESYNTAX () (OR (AND (char= TOK '#\#) (DIGITP CHR))))

   (defun TERMINATOR (CHR)
     (member CHR '(#\  #\( #\) #\. #\; #\, #\Return)) :test #'char=)


The problem is that the routine SPECIALCASESYNTAX references two
undefined variables, namely TOK and CHR.   I don't know how that function
can possibly work.  In fact, that routine does not appear to be called
anywhere...

\start
Date: Thu, 9 Aug 2007 15:22:59 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: re: metalex change

On Thu, 9 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > Also, if the function expects strings, we should give it a string.
| 
| Although not documented as such, it is likely that
| system:string-concatenate is designed to take string designators as
| arguments instead of `just' strings.  This is a fairly common Lisp
| idiom, so I do not see a problem.  Perhaps a close look at the gcl
| code and a patch against the documentation in si-defs.texi is in
| order.

I'm using SBCL to type check the code.  But that should not matter much.

We have two versions, one that uses GCL's stuff, and one that uses the
standard concatenate with type 'string.  We should write codes that compile
with either version.

\start
Date: 09 Aug 2007 15:46:56 -0500
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: re: metalex change

Stephen Wilson writes:

| Stephen Wilson writes:
| 
| > Gabriel Dos Reis writes:
| > > Also, if the function expects strings, we should give it a string.
| > 
| > Although not documented as such, it is likely that
| > system:string-concatenate is designed to take string designators as
| > arguments instead of `just' strings.  This is a fairly common Lisp
| > idiom, so I do not see a problem.  Perhaps a close look at the gcl
| > code and a patch against the documentation in si-defs.texi is in
| > order.
| 
| Of course, that being said, it is a stylistic choice as to what
| designator one uses.  In this case I would probably use a string
| myself as opposed to a symbol.

and that would be give a correct program too :-)

Try this with SBCL:

        (concatenate 'string "foo 'bar) 

\start
Date: Thu, 9 Aug 2007 22:48:29 +0200
From: Juergen Weiss
To: Gabriel Dos Reis
Subject: re: newrule from metalex.lisp

Hi,

There should be only one parse - for sure. The old one does
not support rules for the interpreter. The bootstrap of
the old parser generator is another difficulty. With at least
the possibility to use Aldor as the new compiler there
are quite a few arguments in favor of the new parser. It is
similar in style to the boot translator.

A few years ago I made an argument in favor of the
old parser on this mailing list -- as the one doing the
boot translation, the interpreter parsing and the
parsing for the SPAD compiler. But the code seems to be
quite fragile. In the mean time I think the new
parse could be the better solution.

> -----Original Message-----
> From: Gabriel Dos Reis [mailto:Gabriel Dos Reis]
> Sent: Thursday, August 09, 2007 9:59 PM
> To: Weiss, Juergen
> Cc: Stephen Wilson; list
> Subject: re: newrule from metalex.lisp
>
> Hi Juergen,  thanks for the background.
>
> You're quite right the current situation is confusing.  The current
> interpreter uses the new parser (cparse.boot), while the compiler
> uses the old parser whose grammar is generated as you describe above.
> Except that the grammar is not actually generated anymore:
> instead the
> corresponding Lisp is cached.  I believe it would make sense that
> both the interpreter and the compiler uses the same parser, to reduce
> confusion in syntax, etc.  From that perspective, I would
> think that the long
> term would be to remove the remanants.
>
> Would you object to moving to the new parser (cparse.boot)?

\start
Date: Thu, 9 Aug 2007 15:52:04 -0500 (CDT)
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: re: newrule from metalex.lisp

On Thu, 9 Aug 2007, Weiss, Juergen wrote:

| Hi,
| 
| There should be only one parse - for sure. The old one does
| not support rules for the interpreter. The bootstrap of
| the old parser generator is another difficulty. With at least
| the possibility to use Aldor as the new compiler there
| are quite a few arguments in favor of the new parser. It is
| similar in style to the boot translator.
| 
| A few years ago I made an argument in favor of the
| old parser on this mailing list -- as the one doing the
| boot translation, the interpreter parsing and the
| parsing for the SPAD compiler. But the code seems to be
| quite fragile. In the mean time I think the new
| parse could be the better solution.

As ever, thanks sharing your experience and insight with these issues.

I'll put the move to new parser on my todo list.

\start
Date: 09 Aug 2007 16:55:02 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: re: metalex change

Gabriel Dos Reis writes:

> On Thu, 9 Aug 2007, Stephen Wilson wrote:
> 
> | Gabriel Dos Reis writes:
> | > Also, if the function expects strings, we should give it a string.
> | 
> | Although not documented as such, it is likely that
> | system:string-concatenate is designed to take string designators as
> | arguments instead of `just' strings.  This is a fairly common Lisp
> | idiom, so I do not see a problem.  Perhaps a close look at the gcl
> | code and a patch against the documentation in si-defs.texi is in
> | order.
> 
> I'm using SBCL to type check the code.  But that should not matter much.
> 
> We have two versions, one that uses GCL's stuff, and one that uses the
> standard concatenate with type 'string.  We should write codes that compile
> with either version.

OK.  I think the function is quite broken anyways.  It should either
be removed and calls go directly to cl::concatenate or we should
define a semantics which makes sense.  Having concat return either a
bit-vector or string depending on the type of the first argument is
just bizarre.

Possibly the only sensible semantics would be to have 'concat require
all its arguments to be of the same type T s.t. (subtype T 'sequence)
returns true, and then just call (concatenate T args).

If optimized versions for a specific type are needed I would suggest
writing them independently as `concat-string', `concat-bit-vec', etc.

Any alternatives?

\start
Date: Thu, 9 Aug 2007 16:02:22 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: re: metalex change

On Thu, 9 Aug 2007, Stephen Wilson wrote:

| Possibly the only sensible semantics would be to have 'concat require
| all its arguments to be of the same type T s.t. (subtype T 'sequence)
| returns true, and then just call (concatenate T args).

I'm fine with this.

\start
Date: 09 Aug 2007 17:03:30 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: re: metalex change

Gabriel Dos Reis writes:

> On Thu, 9 Aug 2007, Stephen Wilson wrote:
> 
> | Possibly the only sensible semantics would be to have 'concat require
> | all its arguments to be of the same type T s.t. (subtype T 'sequence)
> | returns true, and then just call (concatenate T args).
> 
> I'm fine with this.

OK.  I will get a patch together tonight and post.

\start
Date: Thu, 9 Aug 2007 23:47:04 +0200 (CEST)
From: Franz Lehner
To: Bill Page
Subject: Re: aldor stream oddities

> "The important thing is to escape the keyword generator by prefix with _."
thanks a lot for your quick replies and solutions.
I am trying to put together some functions to manipulate moment sequences 
and got stuck constructing the zero element.
Am I right that there is no sequence domain (of category VectorSpace 
or Module) in the library yet?

\start
Date: Thu, 9 Aug 2007 17:49:19 -0500
From: Tim Daly
To: Stephen Wilson, Gabriel Dos Reis
Subject: concatenate and bit-vector

The semantics of concat are those of vmlisp.

It might be possible to prove that concat is never called with
bit-vector semantics. The subtle part is to prove that it can't
occur in generated code (e.g. algebra).

\start
Date: Thu, 9 Aug 2007 18:02:46 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: concatenate and bit-vector

On Thu, 9 Aug 2007, Tim Daly wrote:

| Steve, Gaby,
| 
| The semantics of concat are those of vmlisp.
| 
| It might be possible to prove that concat is never called with
| bit-vector semantics. The subtle part is to prove that it can't
| occur in generated code (e.g. algebra).

I'm sorry but that is nonsense to me.  

You clearly have a buggy codes, but you're unwilling to fix, invoking twisted
logic.  

That concat has two version.  One for AKCL, one for non-AKCL.
The only way its call can always yield meaningful results is that the
arguments satisfy the common semantics restrictions, which is that
the arguments be of type string.  That is all you need to know to fix your
code. 

\start
Date: Thu, 9 Aug 2007 19:03:05 -0400
From: Bill Page
To: Franz Lehner
Subject: Re: aldor stream oddities

On 8/9/07, Franz Lehner wrote:
> dear all,
>
> > "The important thing is to escape the keyword generator by prefix with _."
> thanks a lot for your quick replies and solutions.
> I am trying to put together some functions to manipulate moment sequences
> and got stuck constructing the zero element.
> Am I right that there is no sequence domain (of category VectorSpace
> or Module) in the library yet?
>

What is a "sequence domain"? Can you give a brief explanation or a reference?

\start
Date: Thu, 9 Aug 2007 18:04:03 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: newrule from metalex.lisp

On Thu, 9 Aug 2007, Tim Daly wrote:

| Gaby,
| 
| Thanks for the explanation. Now the change makes sense.
| 
| Tim wrote:
| >> I see no diff-Naur patch against silver
| 
| Gaby wrote:
| > I leave this up to you and for another time.
| 
| Why?

Because I suspected that once we have identified the bug and apply
common logic, you will not be willing to accept that there was a bug.  
Sorry.

\start
Date: Thu, 9 Aug 2007 18:06:35 -0500
From: Tim Daly
To: Bill Page
Subject: bootstrap Meta/Boot

Bill writes:

> You probably know where my sympathy lies. I strongly believe that Tim
> is right: "This code is not part of the bootstrap but needs to be at
> some point." and I object to the continuing trend to reduce everything
> to Lisp.

In the IBM/NAG days you needed a running Axiom to build Axiom.

Meta, like Boot, was cleverly written in itself. Thus if you have a
running Meta, you can have a running Meta. And you need to get Meta
running before all else. If you have a running Boot you can make a
running Boot. 

Such a trend leads you back to the point where you need a running
Axiom to build a running Axiom.  It is an interesting, but academic,
problem which is elegantly sidestepped by lisp code.

Fortunately in the brave new world we seem to inhabit, there is no
sticking place for your objection.  You can create your own branch and
thus reconstruct Meta in Meta and Boot in Boot.

\start
Date: 09 Aug 2007 19:11:41 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: concatenate and bit-vector

Gabriel Dos Reis writes:

> On Thu, 9 Aug 2007, Tim Daly wrote:
> 
> | Steve, Gaby,
> | 
> | The semantics of concat are those of vmlisp.
> | 
> | It might be possible to prove that concat is never called with
> | bit-vector semantics. The subtle part is to prove that it can't
> | occur in generated code (e.g. algebra).
> 
> I'm sorry but that is nonsense to me.  
> 
> You clearly have a buggy codes, but you're unwilling to fix, invoking twisted
> logic.  
> 
> That concat has two version.  One for AKCL, one for non-AKCL.
> The only way its call can always yield meaningful results is that the
> arguments satisfy the common semantics restrictions, which is that
> the arguments be of type string.  That is all you need to know to fix your
> code. 

I agree that 'concat is a bit wierd, an I would like it to be a little
more general, but I still dont understand what is broken about it.

One gets the same results for each version of concat, under GCl or
SBCL as appropriate.

  (concat "foo" #\-  'bar) ==> "FOO-BAR"

  (concat #*1010 (make-array 2 :element-type 'bit :initial-contents '(0 1)))
     ==> #*101001

I do not understand what is buggy about the code per say, other than
the semantics just dont jive well IMHO in CL terms w.r.t 'concatenate
in the case the arguments are string designators thus possibly leading
to confusion.

Am I missing something?

\start
Date: Thu, 9 Aug 2007 18:14:21 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: concatenate and bit-vector

On Thu, 9 Aug 2007, Stephen Wilson wrote:

| Am I missing something?

Did you try

   (concatenate 'string "foo" 'bar)

in SBCL, for example?

\start
Date: Thu, 9 Aug 2007 18:23:43 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: getrulefunlists

  Yet one more.  Consider the routine GETFUNLISTS from
src/interp/parsing.lisp:


(defun getrulefunlists  (rootfun rs)
  (let* ((metapfx (or (get rootfun 'metapfx) ""))
         (mainfun (internl metapfx (pname rootfun)))
         (mainfunstr (pname mainfun))
         (flnam (internl mainfunstr "FUN"))
         (pfx-funlist (union (cons mainfun
                                   (if (atom (eval flnam))
				       nil 
				     (eval flnam)))
                             (mapcar #'(lambda (x) (internl metapfx (pname x)))
                                     (assocleft rs))))
         n unpfx-funlist)
    (set flnam pfx-funlist)
    (if (not (lessp (setq n (length metapfx)) 0))
        (setq unpfx-funlist
              (mapcar #'(lambda (x) 
			  (intern (subseq (copy-symbol (pname x)) n)))
		      pfx-funlist)))
    (if unpfx-funlist (list pfx-funlist unpfx-funlist))))


The type checker of the SBCL compiler does not like it, saying:

; file: /home/gdr/build/bi/src/interp/parsing.lisp
; in: DEFUN GETRULEFUNLISTS
;     (INTERN (SUBSEQ (COPY-SYMBOL (VMLISP:PNAME BOOT::X)) BOOT::N))
; 
; note: deleting unreachable code
; 
; caught WARNING:
;   Asserted type STRING conflicts with derived type (VALUES LIST &OPTIONAL).
;   See also:
;     The SBCL Manual, Node "Handling of Types"


Indeed, if you look again at the incriminated form:

	(intern (subseq (copy-symbol (pname x)) n))

it does not make sense to me how it could possibly work -- using Common Lisp
semantics.  Indeed, copy-symbol will return a symbol and a symbol is not 
a sequence.  I suspect what you want to pass to SUBSEQ if actually the
SYMBOL-NAME of the new symbol.

\start
Date: 09 Aug 2007 19:29:28 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: concatenate and bit-vector

Gabriel Dos Reis writes:

> On Thu, 9 Aug 2007, Stephen Wilson wrote:
> 
> | Am I missing something?
> 
> Did you try
> 
>    (concatenate 'string "foo" 'bar)
> 
> in SBCL, for example?

I dont have to. 'bar is not a sequence. 

'concat excepts string designators.  'bar is a string designator.

I still dont understand the problem.

\start
Date: Thu, 9 Aug 2007 18:32:09 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: concatenate and bit-vector

On Thu, 9 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| 
| > On Thu, 9 Aug 2007, Stephen Wilson wrote:
| > 
| > | Am I missing something?
| > 
| > Did you try
| > 
| >    (concatenate 'string "foo" 'bar)
| > 
| > in SBCL, for example?
| 
| I dont have to. 'bar is not a sequence. 

Good.

\start
Date: 09 Aug 2007 18:40:14 -0500
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: re: concatenate and bit-vector

Stephen Wilson writes:

| Gabriel Dos Reis writes:
| 
| > On Thu, 9 Aug 2007, Tim Daly wrote:
| > 
| > | Steve, Gaby,
| > | 
| > | The semantics of concat are those of vmlisp.
| > | 
| > | It might be possible to prove that concat is never called with
| > | bit-vector semantics. The subtle part is to prove that it can't
| > | occur in generated code (e.g. algebra).
| > 
| > I'm sorry but that is nonsense to me.  
| > 
| > You clearly have a buggy codes, but you're unwilling to fix, invoking twisted
| > logic.  
| > 
| > That concat has two version.  One for AKCL, one for non-AKCL.
| > The only way its call can always yield meaningful results is that the
| > arguments satisfy the common semantics restrictions, which is that
| > the arguments be of type string.  That is all you need to know to fix your
| > code. 
| 
| I agree that 'concat is a bit wierd, an I would like it to be a little
| more general, but I still dont understand what is broken about it.
| 
| One gets the same results for each version of concat, under GCl or
| SBCL as appropriate.
| 
|   (concat "foo" #\-  'bar) ==> "FOO-BAR"


Now, I understand what is wrong with my version and your version.
The version in trunk calls STRING on all arguments before calling
concatenate.  

The version I'm working with does not call STRING on the arguments.
That is where the difference come from.

So the original bug in 

   (test Rule1)

can be fixed either:

   1.  (test 'Rule1)
   2.  (test "RULE1")

It is Tim's call.  

\start
Date: 09 Aug 2007 19:34:58 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: concatenate and bit-vector

Gabriel Dos Reis writes:

> On Thu, 9 Aug 2007, Stephen Wilson wrote:
> 
> | Gabriel Dos Reis writes:
> | 
> | > On Thu, 9 Aug 2007, Stephen Wilson wrote:
> | > 
> | > | Am I missing something?
> | > 
> | > Did you try
> | > 
> | >    (concatenate 'string "foo" 'bar)
> | > 
> | > in SBCL, for example?
> | 
> | I dont have to. 'bar is not a sequence. 
> 
> Good.

I understand that concat is a bit of a misnomer in CL terms since

  (concatenate 'string "FOO-" 'bar)

fails.  Of course:

  (concat "FOO-" 'bar)

works, under both #+AKCL and #-AKCL varients.  They do not seem
inconsistant to me, nor buggy. Could you please explain what the
problem is?

\start
Date: Thu, 9 Aug 2007 18:38:12 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: concatenate and bit-vector

On Thu, 9 Aug 2007, Stephen Wilson wrote:

| I understand that concat is a bit of a misnomer in CL terms since
| 
|   (concatenate 'string "FOO-" 'bar)
| 
| fails.  Of course:
| 
|   (concat "FOO-" 'bar)
| 
| works, under both #+AKCL and #-AKCL varients.  They do not seem
| inconsistant to me, nor buggy. Could you please explain what the
| problem is?

I just sent a message -- before receiving this one.

The orignal bug canbe fixed either way:

    (test 'Rule1)
  
or

    (test "RULE1")


But don't ask me to give a test case that makes the system crash.  The
ogirinal code just could not make any sense.

\start
Date: Thu, 9 Aug 2007 18:54:15 -0500
From: Tim Daly
To: Stephen Wilson
Subject: concatenate and bit-vector

Steve,

In order to move from MacLisp to VMLisp and then to pre-common lisp
and then to common lisp (and now to ansi) one of two possible 
approaches can be taken. The first approach is to emulate the
semantics of the original system in the new system. The second 
approach is to prove that the new system does not require all of
the old semantics.

Because it is less error-prone to take the first approach the decision
was to emulate the prior system semantics where possible. In this
particular case the concat and strconc functions have vmlisp and/or
maclisp semantics.

An example occurs in metalex.lisp where it reads:
; Coding note: yes, I know, use string-trim -- but it is broken
; in Symbolics Common Lisp for short strings.

or in parsing.lisp
"A string contining the remaining chars from readline; needed because
Symbolics read-line returns embedded newlines in a c-m-Y"

or many other places such as DEFIOSTREAM, which is non-common lisp.

I still have the MacLisp and VMLisp documentation but most people do
not.  The fact that I did not document the semantics of strconc, for
instance, is a flaw I hope we can all overcome in the present port.

\start
Date: 09 Aug 2007 19:53:40 -0400
From: Stephen Wilson
To: Tim Daly
Subject: Re: concatenate and bit-vector
Cc: Gabriel Dos Reis

Tim Daly writes:

> Steve, Gaby,
> 
> The semantics of concat are those of vmlisp.
> 
> It might be possible to prove that concat is never called with
> bit-vector semantics. The subtle part is to prove that it can't
> occur in generated code (e.g. algebra).

A generalization of 'concat might be useful, but that quality is
important only when it is actually used.  I'll postpone a rewrite of
the function until/if it becomes necessary.

\start
Date: Thu, 9 Aug 2007 18:56:29 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: concatenate and bit-vector

On Thu, 9 Aug 2007, Stephen Wilson wrote:

| Tim Daly writes:
| 
| > Steve, Gaby,
| > 
| > The semantics of concat are those of vmlisp.
| > 
| > It might be possible to prove that concat is never called with
| > bit-vector semantics. The subtle part is to prove that it can't
| > occur in generated code (e.g. algebra).
| 
| A generalization of 'concat might be useful, but that quality is
| important only when it is actually used.  I'll postpone a rewrite of
| the function until/if it becomes necessary.

That is also fine with me.  The only thing that matters to me is that
the bug I reported is fixed.

\start
Date: Thu, 9 Aug 2007 19:10:39 -0500
From: Tim Daly
To: list
Subject: Lisp in Small Pieces

Lisp in Small Pieces, a fantastically well done literate document,
managed to beat out Harrry Potter on Amazon. And it is selling for $4.
<http://planet.lisp.org>

\start
Date: 09 Aug 2007 20:13:46 -0400
From: Stephen Wilson
To: Tim Daly
Subject: Re: concatenate and bit-vector

Tim,

Documentation would certainly help the current strategy, however, I
believe that ANSI cl is really the only Lisp variant of importance to
Axiom nowadays.

Despite the fact that it is certainly more error-prone (and thus
difficult) to rewrite everything using CL idioms / semantics I am
still inclined to think that we should attempt that direction.  

This opinion is based on my perception that ANSI cl has much more
mind-share than preceding dialects.  I for one never programmed in
MacLisp or VMLisp, for example.

However, there are undoubtedly many functions/macros which arose out
of these ports which are useful.  I have not tried to categorize them
in any way.  But, I would rather document what is useful and consider
them as utilities more than as `porting devices', possibly changing
their names to sit better with CL conventions.

Of course, all this has as much to do with `style' as with anything
else.  But the mind-share point and simply making the code more
accessible to CL programmers I find fairly motivating.

Any objections to this kind of reorganization as we work?

\start
Date: 09 Aug 2007 19:22:05 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: Lisp in Small Pieces

Tim Daly writes:

| Lisp in Small Pieces, a fantastically well done literate document,
| managed to beat out Harrry Potter on Amazon. And it is selling for $4.

Well, that certainly is an order of magniture smaller than how much I
payed ten years ago -- French version.

\start
Date: Thu, 9 Aug 2007 20:40:01 -0500 (CDT)
From: Gabriel Dos Reis
To: list
Subject: numberOfEmptySlots

Consider the following function from src/interp/clam.boot:

    numberOfEmptySlots cache==
      count:= (CAAR cache ='$failed => 1; 0)
      for x in tails rest cache while NE(x,cache) repeat
	if CAAR x='$failed then count:= count+1
      count


The SBCL type checker does not like it because:

  * it is able to infer that cache is a list,
  * '=' (coming from NE, which mean not =) can be applied only
    to numbers.

Consequently, we have conflicting assumptions for the same value.  So, we 
have a bug.  Now, looking back at the code, the expression

     NE(x,cache)

cannot be right.  Was it indended to be

    x /= cache

instead?

Note: a /= b is almost same like (not (equal a b)).

What is the semantics of function numberOfEmptySlots?  What is
the structure of its parameter?

\start
Date: 09 Aug 2007 21:06:07 -0500
From: Gabriel Dos Reis
To: list
Subject: Re: numberOfEmptySlots

Gabriel Dos Reis writes:

| Consider the following function from src/interp/clam.boot:
| 
|     numberOfEmptySlots cache==
|       count:= (CAAR cache ='$failed => 1; 0)
|       for x in tails rest cache while NE(x,cache) repeat
| 	if CAAR x='$failed then count:= count+1
|       count
| 
| 
| The SBCL type checker does not like it because:
| 
|   * it is able to infer that cache is a list,
|   * '=' (coming from NE, which mean not =) can be applied only
|     to numbers.
| 
| Consequently, we have conflicting assumptions for the same value.  So, we 
| have a bug.  Now, looking back at the code, the expression
| 
|      NE(x,cache)
| 
| cannot be right.  Was it indended to be
| 
|     x /= cache
| 
| instead?

Looking more into it, I suspect it was supposed to be

      NEQ(x,cache)

where NEW is the macro (from vmlisp.lisp)


   (defmacro neq (a b) `(not (eq ,a ,b)))

\start
Date: Thu, 9 Aug 2007 22:19:12 -0400
From: Bill Page
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

On 8/9/07, Tim Daly wrote:
>
> In the IBM/NAG days you needed a running Axiom to build Axiom.
>

I believe that is one of the things that allowed Axiom to become so
advanced so quickly (relatively speaking). Axiom's library code is
highly circularly-dependent as a result. This structure makes Spad a
very expressive language indeed. (Probably even more expressive than
Python by most common measures.)

That you need a running Axiom to build Axiom is still true in the all
branches of the Axiom project. You need a consistent copy of the
databases before you can even compile the associated Spad code. But
the databases must be created by compiling the Spad code in an already
running Axiom. You also needed a running Axiom to generate the
bootstrap Lisp  necessary to break the dependency cycles. Apparently
these problems can be solved but only with a radically different build
approach than is used now in Axiom, as demonstrated by the Axiom fork
project.

> Meta, like Boot, was cleverly written in itself. Thus if you have a
> running Meta, you can have a running Meta. And you need to get Meta
> running before all else. If you have a running Boot you can make a
> running Boot.
>

That is nothing strange or clever. If you have a running gcc then you
can make a running gcc. The is true of many other languages, e.g.
Haskell. We have discussed this ad infinitum in this email list.

> Such a trend leads you back to the point where you need a running
> Axiom to build a running Axiom.  It is an interesting, but academic,
> problem which is elegantly sidestepped by lisp code.
>

What do you think is being side-stepped by lisp code? It could just as
easily by solved by writing everything in C (gcc bootstrapping not
withstanding). If you write everything at the same linguistic level
(i.e. in the same language) then of course this problem does not
arise. But you also severely limit your design options.  The
consequences seem obvious in systems like Maxima, Maple and
Mathematica. This difference in design methodology is one of the
things that sets Axiom apart.

> Fortunately in the brave new world we seem to inhabit, there is no
> sticking place for your objection.  You can create your own branch and
> thus reconstruct Meta in Meta and Boot in Boot.
>

Indeed I could had I the time and skill. Luckly there are some other
motivated people more qualified than I, which leaves my remaining time
available for answering emails such as these. ;-)

\start
Date: Thu, 9 Aug 2007 21:30:42 -0500
From: Tim Daly
To: Stephen Wilson
Subject: concatenate and bit-vector

I plan to rewrite functions into ANSI as I encounter them so,
no, I have no objections to a reorganization.

\start
Date: Thu, 9 Aug 2007 21:45:09 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: numberOfEmptySlots

The NE occurs in boot code. 
Perhaps the author meant to use the infix form NE?

\start
Date: Thu, 9 Aug 2007 22:58:20 -0400
From: Bill Page
To: list
Subject: Simon Peyton-Jones video on the "threshold of immortality" (and Haskell)

Talk posted by Bruce Stewart:

http://beautifulcode.oreillynet.com/2007/08/oscon_video_of_simon_peyton_jo.php

Slides:

http://conferences.oreillynet.com/presentations/os2007/os_peytonjones.pdf

I think this energetic talk is important at a number of levels,
independently of the specific subject of Haskell programming. Simon
makes a number of important side comments about the "slow death" and
other characteristics of successful "research languages" which seem to
apply in a positive sense to Boot, Spad and Aldor (See: slide 5)
versus the "threshold of immortality" for languages like Fortran and
Python.

I think that if Axiom is going to survive another 30 years, then we
very badly need to get closer to this threshold.

\start
Date: Thu, 9 Aug 2007 22:09:04 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: numberOfEmptySlots

On Thu, 9 Aug 2007, Tim Daly wrote:

| The NE occurs in boot code. 

Yes.

| Perhaps the author meant to use the infix form NE?

which would be equivalent to ^=, e.g. not equal.  
Why would that be correct? 

Hmm.  Looking at the code, it is comparing lists and x
is taken from cache, then using ^= would lead to infinite
loop.   No?

\start
Date: 09 Aug 2007 22:37:00 -0500
From: Gabriel Dos Reis
To: Bill Page
Subject: re: bootstrap Meta/Boot

Bill Page writes:

| On 8/9/07, Tim Daly wrote:
| >
| > In the IBM/NAG days you needed a running Axiom to build Axiom.
| >
| 
| I believe that is one of the things that allowed Axiom to become so
| advanced so quickly (relatively speaking). Axiom's library code is
| highly circularly-dependent as a result. This structure makes Spad a
| very expressive language indeed. (Probably even more expressive than
| Python by most common measures.)

It is odd to state, but Axiomatizers should not underestimate the
power of abstraction. 

Not because the whole system is mechanically translated to assembly
code means that the system should actually be written in assembly
code.  Think Unix, think C.  Think Spad, think high level.

Fortunately, Boot is already written in Boot and we have a 2-3 stage
Boot-strap. 

\start
Date: 09 Aug 2007 22:42:18 -0500
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: Simon Peyton-Jones video on the "threshold of immortality" (and Haskell)

Bill Page writes:

| Talk posted by Bruce Stewart:
| 
| http://beautifulcode.oreillynet.com/2007/08/oscon_video_of_simon_peyton_jo.php
| 
| Slides:
| 
| http://conferences.oreillynet.com/presentations/os2007/os_peytonjones.pdf
| 
| I think this energetic talk is important at a number of levels,
| independently of the specific subject of Haskell programming. Simon
| makes a number of important side comments about the "slow death" and
| other characteristics of successful "research languages" which seem to
| apply in a positive sense to Boot, Spad and Aldor (See: slide 5)
| versus the "threshold of immortality" for languages like Fortran and
| Python.


That cuts his presentation at HOPL III last June in San Diego.

As ever, it is alsways an immense pleasure to attent or see a talk by 
SPJ.

I wish we had more Simons working on Axiom...

\start
Date: Thu, 09 Aug 2007 21:03:19 -0700
From: Ed Borasky
To: list
Subject: re: bootstrap Meta/Boot

Gabriel Dos Reis wrote:
> Bill Page writes:
> 
> | On 8/9/07, Tim Daly wrote:
> | >
> | > In the IBM/NAG days you needed a running Axiom to build Axiom.
> | >
> | 
> | I believe that is one of the things that allowed Axiom to become so
> | advanced so quickly (relatively speaking). Axiom's library code is
> | highly circularly-dependent as a result. This structure makes Spad a
> | very expressive language indeed. (Probably even more expressive than
> | Python by most common measures.)
> 
> It is odd to state, but Axiomatizers should not underestimate the
> power of abstraction. 
> 
> Not because the whole system is mechanically translated to assembly
> code means that the system should actually be written in assembly
> code.  Think Unix, think C.  Think Spad, think high level.
> 
> Fortunately, Boot is already written in Boot and we have a 2-3 stage
> Boot-strap. 
> 
> -- Gaby

As a user who can't quite find the time to get involved with Axiom on a
deeper level, I must say I find the plethora of languages in the Axiom
development scheme quite daunting. Let's see: there's Axiom, Boot, SPAD,
Aldor *and* Common Lisp, not counting the underlying C that most of the
Common Lisps are built in. If *I* were building Axiom from "scratch",
I'd start with Common Lisp, because Common Lisp compilers are pretty
good. Then I would implement the core of Axiom in Common Lisp -- just
enough so it can bootstrap itself.

I think two levels of abstraction is probably the maximum a developer
should have to deal with, and one level would be even better. Of course,
any sufficiently powerful language is going to need a "virtual machine /
run time library" to handle OS interfaces, handling primitive data such
as strings, multiprecision numbers, floating point arithmetic, dense
arrays of floating point values, graphics, etc. while providing
reasonable efficiency and portability. But does it really need so many
sub-languages?

\start
Date: 09 Aug 2007 23:25:52 -0500
From: Gabriel Dos Reis
To: Ed Borasky
Subject: re: bootstrap Meta/Boot

Ed Borasky writes:


[...]

| As a user who can't quite find the time to get involved with Axiom on a
| deeper level, I must say I find the plethora of languages in the Axiom
| development scheme quite daunting. Let's see: there's Axiom, Boot, SPAD,
| Aldor *and* Common Lisp, not counting the underlying C that most of the
| Common Lisps are built in. If *I* were building Axiom from "scratch",
| I'd start with Common Lisp, because Common Lisp compilers are pretty
| good. 

In fact that is open to debate, by reality check.  The only "good"
Common Lisp compiler I know freely available is SBCL, and we don't
support it right now.  And Common Lisp actually gives you very little
support to write useful programs.

In fact, once I got deep into Axiom internals, I found (Common) Lisp
just too low level, incomplete and unhelpful by times.  As probably
did the original designers and developers of Axiom; and they developed
languages to help them accomplish their tasks.

Check out Domain Specific Languages (DSLs).  Or if you're washing
SPJ's talk, you've probably have heard it by now.  Note also that 
Boot+Spad are close to Haskell and ahead of their times.  We want
that.  In particular, we don't want to indefinitely stay at the 
low level of Lisp.

Standard ML compilers were once written in Lisp.  They are no more.

\start
Date: Thu, 09 Aug 2007 21:41:27 -0700
From: Ed Borasky
To: list
Subject: re: bootstrap Meta/Boot

Gabriel Dos Reis wrote:

> In fact that is open to debate, by reality check.  The only "good"
> Common Lisp compiler I know freely available is SBCL, and we don't
> support it right now.  And Common Lisp actually gives you very little
> support to write useful programs.

Well ... SBCL is a re-write of CMUCL, which I thought was freely
available, except on Windows. The libraries for Common Lisp are immense,
though.

> In fact, once I got deep into Axiom internals, I found (Common) Lisp
> just too low level, incomplete and unhelpful by times.  As probably
> did the original designers and developers of Axiom; and they developed
> languages to help them accomplish their tasks.

Well, considering the long history of Axiom and its predecessors, that's
not surprising. But once you *have* Axiom capable of compiling itself,
do you really need the underlying scaffolding, or can you take it down
and just use the building?

> Check out Domain Specific Languages (DSLs).  Or if you're washing
> SPJ's talk, you've probably have heard it by now.  Note also that 
> Boot+Spad are close to Haskell and ahead of their times.  We want
> that.  In particular, we don't want to indefinitely stay at the 
> low level of Lisp.

I just buzzed through the SPJ slides. I've been a big fan of functional
programming languages, denotational semantics, etc. since Lisp 1.5. I
haven't bothered to learn Haskell or any of the ML family yet, partly
because I don't get paid to write in functional languages, and partly
because of all the functional languages around today, the one that I
think has the strongest legs is Erlang. *That's* the one I'm learning at
the moment.

As far as DSLs are concerned, since I also hang out with the Ruby crowd,
I'm familiar with DSLs. I don't necessarily think they're a good thing
-- I much prefer, as you seem to, higher-level abstractions in
programming languages. You may need a hierarchy of languages to get
there, but do you need it forever?

One final note about the Simon Peyton Jones slides -- I absolutely
positively *detest* the vernacular "drinking the Kool-Aid". It refers to
a sad incident in which an insane and vicious man duped hundreds of
people into drinking poison. That's *not* the kind of image I want to be
associated with the fruits of *my* labors -- ever!  Haskell Curry
deserves better than that.
> 
> Standard ML compilers were once written in Lisp.  They are no more.

Are they written in Standard ML? If so, they've successfully taken down
the scaffolding.

\start
Date: Thu, 9 Aug 2007 23:48:27 -0500
From: Tim Daly
To: Ed Borasky
Subject: bootstrap Meta/Boot

> But does it really need so many sub-languages?

Well, that's a religious question.

Some on the wailing list feel that Meta and Boot should be recovered,
made strongly typed, and closer to the algebra language.  On the plus
side it will be claimed that these are "higher level" (or could be
made into higher level since they are really just syntactic sugar).
On the minus side Meta and Boot are languages with 3 people who read
them and no-one who writes them.

Yet others would like a single language like Aldor that implements
everything. On the plus side this would mean that there is only one
language to learn, which is reasonable. On the minus side this is a
huge task, involving reimplementing the interpreter, the compiler, the
databases, the algebra, and other machinery.

Then there is the common lisp internals, spad externals, crowd. On the
minus side the claim is made that lisp is an "assembly language".  On
the plus side, well, its lisp. You can't get any higher level language.  
Either you get it or you don't.

I firmly believe that the internals should be in common lisp. It
already is common lisp modulo some "syntactic sugar" (e.g. current
boot). Over the years I've been slowly removing this sugar and using
only common lisp.

It hardly matters. The "new world" allows everyone to do whatever
suits their mood by creating their own branch. This will eventually
undermine the whole effort rendering the language debate mute.

\start
Date: Thu, 9 Aug 2007 23:53:42 -0500
From: Tim Daly
To: Ed Borasky
Subject: bootstrap Meta/Boot

> the one that I think has the strongest legs is Erlang

Funny you should mention that as I'm half way thru the new Erlang book.
This model, if not the language itself, is a perfect vehicle for an
implementation of provisos (much discussed on this list). Using closures,
SBCL threads, and some transparent networking I believe this could all
be implemented in common lisp. Laying this model under the algebra gives
us the ability to write parallel algebra using provisos transparently.

\start
Date: Thu, 09 Aug 2007 22:18:44 -0700
From: Ed Borasky
To: list
Subject: Re: bootstrap Meta/Boot

Tim Daly wrote:
>> the one that I think has the strongest legs is Erlang
> 
> Funny you should mention that as I'm half way thru the new Erlang book.
> This model, if not the language itself, is a perfect vehicle for an
> implementation of provisos (much discussed on this list). Using closures,
> SBCL threads, and some transparent networking I believe this could all
> be implemented in common lisp. Laying this model under the algebra gives
> us the ability to write parallel algebra using provisos transparently.
> 
> Tim

Portland Oregon hosted last year's functional languages conference, and
I went to two of the language-specific workshops on the weekend before
the conference itself. It was an agonizing decision -- all of the major
functional languages were represented, and the only one I really
consider myself fluent in is a subset of Common Lisp. In the end,
though, I chose Erlang and Scheme.

For what it's worth, I think the Schemers were right in the great
Lisp/Scheme schism, and having spent nearly 3/4 of my career writing
assembly language and FORTRAN for a living, I have a great appreciation
for the power of low-level languages. They're addicting -- perhaps the
most addicting of all is Forth.

Also, the Scheme workshop featured a fascinating paper by the Gambit-C
Scheme team on Termite, where they've implemented the primitives of
Erlang concurrency in Scheme with competitive performance on a number of
tests with Erlang itself. Presumably it could be implemented in SBCL if
it can be implemented in Scheme. Google for Scheme Gambit Termite and
you'll find it.

\start
Date: Thu, 09 Aug 2007 22:29:21 -0700
From: Ed Borasky
To: list
Subject: Re: bootstrap Meta/Boot

Tim Daly wrote:
>> But does it really need so many sub-languages?
> 
> Well, that's a religious question.
> 
> Some on the wailing list feel that Meta and Boot should be recovered,
> made strongly typed, and closer to the algebra language.  On the plus
> side it will be claimed that these are "higher level" (or could be
> made into higher level since they are really just syntactic sugar).
> On the minus side Meta and Boot are languages with 3 people who read
> them and no-one who writes them.

Oh ... OK ... Aldor, SPAD, Boot *and* Meta ... yet another language. :)

> 
> Yet others would like a single language like Aldor that implements
> everything. On the plus side this would mean that there is only one
> language to learn, which is reasonable. On the minus side this is a
> huge task, involving reimplementing the interpreter, the compiler, the
> databases, the algebra, and other machinery.

And of course there is the "Aldor is a great language but it still has
some non-freedoms attached" argument. I would think getting a
free-as-in-freedom Aldor would be an easier job than a
free-as-in-freedom Java, but, hey, Java happened!

> Then there is the common lisp internals, spad externals, crowd. On the
> minus side the claim is made that lisp is an "assembly language".  On
> the plus side, well, its lisp. You can't get any higher level language.  
> Either you get it or you don't.
> 
> I firmly believe that the internals should be in common lisp. It
> already is common lisp modulo some "syntactic sugar" (e.g. current
> boot). Over the years I've been slowly removing this sugar and using
> only common lisp.
> 
> It hardly matters. The "new world" allows everyone to do whatever
> suits their mood by creating their own branch. This will eventually
> undermine the whole effort rendering the language debate mute.

It may allow arbitrary branches/forks, but the odds of any of them
creating a successful project are small. You pretty much have to be a
mathematician to *use* Axiom, unlike Derive, which a bright high-school
student can use out of the box. Maxima is a little harder to use, but
the wxMaxima GUI is pretty easy and "Derive-like".

Speaking of Derive, perhaps it's worthy of note that the original
versions of Derive were written using an underlying implementation that
was "Lisp-like" but had some real fundamental semantic differences from
Lisp. I've forgotten the details, but eventually the developers were
forced to rewrite it in Lisp, and indeed, to build their own Lisp on the
8086/DOS/DOS Extenders platform as well.

\start
Date: Fri, 10 Aug 2007 00:36:55 -0500
From: Tim Daly
To: Ed Borasky
Subject: bootstrap Meta/Boot

(ah, forth. i do so love forth)

Scheme is quite nice. My son implemented and sells a PHP compiler in
scheme. Scheme has two flaws from my point of view. A minor flaw is that
I end up implementing half of common lisp in scheme, and badly at that.

A major flaw is that scheme broke the correspondence of 
  nil == false == empty list
which is the bridge between the procedural and data representations.
THE fundamental insight of lisp is that 
  programs == data.

No other language gets this right.  Unfortunately there is no way to
fake this connection in scheme. So while I like the idea I think they
blew THE fundamental detail.

\start
Date: Fri, 10 Aug 2007 00:40:58 -0500
From: Tim Daly
To: Ed Borasky
Subject: bootstrap Meta/Boot

>> It hardly matters. The "new world" allows everyone to do whatever
>> suits their mood by creating their own branch. This will eventually
>> undermine the whole effort rendering the language debate mute.

> It may allow arbitrary branches/forks, but the odds of any of them
> creating a successful project are small.

Precisely. Vanishingly small.

\start
Date: 10 Aug 2007 07:42:45 +0200
From: Martin Rubey
To: Franz Lehner
Subject: Re: aldor stream oddities

Franz Lehner writes:

> dear all,
> 
> > "The important thing is to escape the keyword generator by prefix with _."
> thanks a lot for your quick replies and solutions.
> I am trying to put together some functions to manipulate moment sequences and
> got stuck constructing the zero element.
> Am I right that there is no sequence domain (of category VectorSpace or Module)
> in the library yet?

Do you mean "potentially" infinite sequences of some ground ring, with
componentwise addition and scalar multiplication?

\start
Date: Fri, 10 Aug 2007 00:45:34 -0500
From: Tim Daly
To: Ed Borasky
Subject: bootstrap Meta/Boot

> Derive ....

Derive is a fantastic program and often outperformed everything else.
It is historically interesting, in the "Newton's Notebooks" sense.

I have spent the last few months trying to convince TI to either
release the original derive lisp code (which they no longer use)
or to write a "dead safe" clause that would release the code if
TI lost interest. It went up the management chain at TI.

As of last week the effort officially failed.

\start
Date: Thu, 9 Aug 2007 23:19:28 -0700 (PDT)
From: Cliff Yapp
To: Tim Daly, Stephen Wilson
Subject: Re: concatenate and bit-vector

--- Tim Daly wrote:

> Steve,
> 
> In order to move from MacLisp to VMLisp and then to pre-common lisp
> and then to common lisp (and now to ansi) one of two possible 
> approaches can be taken. The first approach is to emulate the
> semantics of the original system in the new system. The second 
> approach is to prove that the new system does not require all of
> the old semantics.

Or, third, use the literate re-write and re-design of the system to
ensure that everything fits in common lisp.

> Because it is less error-prone to take the first approach the
> decision was to emulate the prior system semantics where possible.

Less error prone initially, but more difficult to understand and
maintain.

Either way, we need to have sufficient understanding of the system that
we can make intelligent statements about what is and is not required. 
The effort needed for that is sufficiently large that refactoring to
work on common lisp without emulating old behaviors that can be cleanly
expressed in the new ANSI conventions seems (to me) like a logical step
to take.

> In this particular case the concat and strconc functions have vmlisp
> and/or maclisp semantics.
> 
> An example occurs in metalex.lisp where it reads:
> ; Coding note: yes, I know, use string-trim -- but it is broken
> ; in Symbolics Common Lisp for short strings.
> 
> or in parsing.lisp
> "A string contining the remaining chars from readline; needed because
> Symbolics read-line returns embedded newlines in a c-m-Y" or many
> other places such as DEFIOSTREAM, which is non-common lisp.

Eventually, I hope we will reach a point where we won't have the legacy
of all the various non-ANSI lisps cluttering up the code - it doesn't
add anything I can see and increases the overhead for understanding.
 
> I still have the MacLisp and VMLisp documentation but most people do
> not.  The fact that I did not document the semantics of strconc, for
> instance, is a flaw I hope we can all overcome in the present port.

MacLisp and VMLisp are no longer active targets - shouldn't we be
looking first at what "higher level" components of Axiom are supposed
to be doing and then re-think how to do those jobs in light of modern
Lisp environments?

\start
Date: Fri, 10 Aug 2007 00:02:03 -0700 (PDT)
From: Cliff Yapp
To: Bill Page, Tim Daly
Subject: re: bootstrap Meta/Boot

--- Bill Page wrote:

> Apparently these problems can be solved but only with a radically
> different build approach than is used now in Axiom, as demonstrated
> by the Axiom fork project.

Eventually, my understanding is we will head in a similar direction.

> > Such a trend leads you back to the point where you need a running
> > Axiom to build a running Axiom.  It is an interesting, but
> > academic, problem which is elegantly sidestepped by lisp code.
> >
> 
> What do you think is being side-stepped by lisp code? It could just
> as easily by solved by writing everything in C (gcc bootstrapping not
> withstanding).

Quite true.  However, Lisp (at least in the eyes of some) offers a lot
in a single language.

> If you write everything at the same linguistic level
> (i.e. in the same language) then of course this problem does not
> arise. But you also severely limit your design options.

Actually, all that is needed is to keep a subset of the language you
are targeting defined in Lisp (or whatever) and then keep the rest of
that language buildable from that subset.  So the minimum functionality
that must remain defined at the "base" linguistic level is the
functionality needed to build enough of the new language that the
result can understand the remainder of its own definition.  What
constitutes this minimum subset is actually an interesting problem.  If
I understand correctly, one of the really elegant things about Forth is
that this minimum subset is well understood and quite small, and thus
easily implemented.  What constitutes the minimal subset for Common
Lisp in terms of some other language is not as well defined, but is an
interesting problem that other people have inquired about in the past. 
Possibly, enough of a bootstrap Lisp compiler written in Forth would
constitute a minimal path to a working Common Lisp.*  Then, we have the
same question for SPAD - is there enough benefit to it being written in
itself to merit consideration of the bootstrap problem, or is Lisp
sufficiently capable that it can express SPAD "well enough".

> The consequences seem obvious in systems like Maxima, Maple and
> Mathematica. This difference in design methodology is one of the
> things that sets Axiom apart.

I would have thought the major difference there would be Axiom's strong
focus on being correct as a first order priority.  How do you see
languages written in themselves as setting Axiom apart?

Cheers,
CY

* I'm actually trying to get ahold of an old thesis on implementing a
small Lisp in Forth - I know most folks on the Axiom project won't be
interested, but Bare Metal -> Forth -> ANSI CL is an interesting
possibility to me as "future proofing" against the bootstrap problem. 
Of course, there's also the CADR Lisp Machine information at MIT, which
is also very interesting :-).

\start
Date: Thu, 9 Aug 2007 23:43:07 -0700 (PDT)
From: Cliff Yapp
To: Ed Borasky
Subject: re: bootstrap Meta/Boot

--- Ed Borasky wrote:

> Well, considering the long history of Axiom and its predecessors,
> that's not surprising. But once you *have* Axiom capable of compiling
> itself, do you really need the underlying scaffolding, or can you
> take it down and just use the building?

You take it down only if you are sure you will never again need to
re-build the building.

I am quite sure the original team probably reached the same conclusion,
but the fact remains that the original system had to be re-bootstrapped
by Tim for public release.  So we already have one example where the
loss of the scaffolding was a major inconvenience.
 
> -- I much prefer, as you seem to, higher-level abstractions in
> programming languages. You may need a hierarchy of languages to get
> there, but do you need it forever?

The bootstrap problem occurs when languages become divorced from their
original implementations in another language - i.e. you need a working
binary and have no source to compile to create that binary that doesn't
require the same working binary.  If you can guarantee that you will
always have a running cross-compiler this is workable, but it seems a
dangerous assumption to make.

Interesting you should mention Forth, by the way - in the discussion of
what constitutes the minimum path for a "hard bootstrap" on
comp.lang.lisp Forth was suggested as a good way to get the most
functionality for the least amount of low level machine/assembly
coding.  I'm currently trying to track down some older work that was
done on implementing Lisp in Forth.

\start
Date: Fri, 10 Aug 2007 00:04:09 -0700 (PDT)
From: Cliff Yapp
To: Tim Daly
Subject: Re: Lisp in Small Pieces

Not at $4 any more. I didn't notice it in time.  Arrrgh.

--- Tim Daly wrote:

> Lisp in Small Pieces, a fantastically well done literate document,
> managed to beat out Harrry Potter on Amazon. And it is selling for
> $4.
> <http://planet.lisp.org>

\start
Date: Fri, 10 Aug 2007 10:20:32 +0200 (CEST)
From: Franz Lehner
To: Bill Page
Subject: Re: aldor stream oddities

On Fri, 10 Aug 2007, Bill Page wrote:
> What is a "sequence domain"? Can you give a brief explanation or a reference?
see below
On Fri, 10 Aug 2007, Martin Rubey wrote:
> Do you mean "potentially" infinite sequences of some ground ring, with
> componentwise addition and scalar multiplication?
Exactly. It's straightforward, still I don't want to reduplicate code.
Actually UnivariateTaylorSeries could do it, but contains too much.

Here is another question.
I would like to use the recursive formula
http://en.wikipedia.org/wiki/Cumulant#Cumulants_and_moments
to convert streams of moments into cumulants and vice versa.
This is a somewhat more involved than the Fibonacci example in the Axiom 
book and I don't see how map etc from StreamFunctions? could handle this 
directly. Before digging into the guess code or aldor-combinat where I 
suspect similar things are done, I thought I'd ask for "clever" solutions 
here.

\start
Date: Fri, 10 Aug 2007 12:01:12 +0200
From: Ralf Hemmecke
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

> Fortunately in the brave new world we seem to inhabit, there is no
> sticking place for your objection.  You can create your own branch and
> thus reconstruct Meta in Meta and Boot in Boot.

And whoever wants to rewrite everything is LISP should create a new 
branch and write Axiom in Common LISP so that on the list

http://wiki.axiom-developer.org/AxiomProgramming

*only* LISP remains No BOOT, no SHOE, no SPAD.

I wonder, how many people would use such a system. And how many people 
would be able to maintain it.

Tim, if you are so much concered with bootstrapping, what is wrong in 
having a very small lisp machinary to get to some state where one could 
climb the abstraction ladder and define the rest in some (hopefully) 
more human readable language?

BTW, why do you think it is so essential that the underlying language of 
Axiom must be LISP? If I now start a branch and convert Axiom to 
Haskell, or Assembler would you object? Would you be interested?

\start
Date: Fri, 10 Aug 2007 12:01:52 +0200
From: Ralf Hemmecke
To: Franz Lehner
Subject: Re: aldor stream oddities

On 08/10/2007 10:20 AM, Franz Lehner wrote:
> On Fri, 10 Aug 2007, Bill Page wrote:
>> What is a "sequence domain"? Can you give a brief explanation or a 
>> reference?
> see below
> On Fri, 10 Aug 2007, Martin Rubey wrote:
>> Do you mean "potentially" infinite sequences of some ground ring, with
>> componentwise addition and scalar multiplication?
> Exactly. It's straightforward, still I don't want to reduplicate code.
> Actually UnivariateTaylorSeries could do it, but contains too much.

Suppose you have a ring R. You can (mathematically) produce S=R^{(N)}, 
the ring of sequences (N being the natural numbers).

Now, in Axiom we should have a problem with saying that S is an additive 
group. Not in the mathematical sense, of course, but in Axiom we want to 
be able to compute.

Do you want the following to happen?

(1) -> f(): Integer == 1
    Function declaration f : () -> Integer has been added to workspace.
            Type: Void
(2) -> s: Stream(Integer) := generate f
    (2)  [1,1,1,1,1,1,1,1,1,1,...]
            Type: Stream Integer
(3) -> t: UnivariateTaylorSeries(Integer,x,0) := series s
                  2    3    4    5    6    7    8    9    10      11
    (3)  1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x   + O(x  )
            Type: UnivariateTaylorSeries(Integer,x,0)
(4) -> zero?(t-t)
    (4)  false
            Type: Boolean

I don't.

And for that reason, one should be really careful in defining the 
library. Aldor's LibAlgebra, takes a bit more care.

%5 >> DenseUnivariateTaylorSeries(Integer) has Ring
F @ Boolean

The category Ring is reserved for structures with complete equality testing.

Ralf

--------------------------------------------------------------------
If follows a paragraph from the Algebra User Guide and Reference Manual, 
version 1.1.0 - April 19, 2005 by Manuel Bronstein and Mark Moreno Maza

Chapter 2.

The libaldor categories AdditiveType, ArithmeticType and
LinearCombinationType already export the basic arithmetic operations
provided respectively by abelian groups, rings and modules. In fact
AbelianGroup, Ring and Module do inherit their exports from them.
There is however a fundamental difference: while the libaldor
categories export the usual operations =, +, -, ..., they make no
assumption about their algebraic properties whatsoever. On the other
hand, the corresponding algebraic categories in Algebra do assume that
= is a complete equality test, and that the arithmetic operations
satisfy the algebraic axioms of their mathematical structure. So for
example, while Integer is extended by Algebra to be a Ring (among
other things), SingleFloat remains an ArithmeticType but is not a
Ring. There is a similar relationship between LinearArithmeticType and
Algebra, both provided by Algebra. Mathematical types such as
DenseMatrix(R) or DenseUnivariatePolynomial(R) allow their argument R
to be an ArithmeticType rather than a Ring, but those among their
functions that require a complete equality on R are not exported when
R is not a Ring. Similarly, while DenseUnivariatePolynomial(R) is
always an ArithmeticType, it is a Ring only when R itself is a Ring.

\start
Date: Fri, 10 Aug 2007 05:33:09 -0700 (PDT)
From: Cliff Yapp
To: Ralf Hemmecke, Tim Daly
Subject: Re: bootstrap Meta/Boot

--- Ralf Hemmecke wrote:

> > Fortunately in the brave new world we seem to inhabit, there is no
> > sticking place for your objection.  You can create your own branch
> > and thus reconstruct Meta in Meta and Boot in Boot.
> 
> And whoever wants to rewrite everything is LISP should create a new 
> branch and write Axiom in Common LISP so that on the list
> 
> http://wiki.axiom-developer.org/AxiomProgramming
> 
> *only* LISP remains No BOOT, no SHOE, no SPAD.

My take on this issue is that FOR MATHEMATICAL PROGRAMMING a language
which tailors itself to that task is warranted, either SPAD or
something similar.  This will eventually be the large majority of work
in Axiom, and so the benefits of a language specifically tailored
specifically to help with writing mathematics (which is quite complex,
even by programming standards) is justified.

I outlined earlier my take on this issue, which is why I don't ignore
the bootstrapping issue as pointless.  

> I wonder, how many people would use such a system. And how many
> people would be able to maintain it.
> 
> Tim, if you are so much concered with bootstrapping, what is wrong in
> having a very small lisp machinary to get to some state where one
> could climb the abstraction ladder and define the rest in some
> (hopefully)  more human readable language?

Just IMHO, Lisp code intended for human consumption is actually fairly
readable.  Boot's output is not a good way to judge.

\start
Date: 10 Aug 2007 08:25:46 -0500
From: Gabriel Dos Reis
To: Ed Borasky
Subject: re: bootstrap Meta/Boot

Ed Borasky writes:

| Gabriel Dos Reis wrote:
| 
| > In fact that is open to debate, by reality check.  The only "good"
| > Common Lisp compiler I know freely available is SBCL, and we don't
| > support it right now.  And Common Lisp actually gives you very little
| > support to write useful programs.
| 
| Well ... SBCL is a re-write of CMUCL, which I thought was freely
| available, except on Windows.

Well, in fact, you can check it out: SBCL is also available on Windows.

[...]

| Well, considering the long history of Axiom and its predecessors, that's
| not surprising. But once you *have* Axiom capable of compiling itself,
| do you really need the underlying scaffolding, or can you take it down
| and just use the building?

But we don't have Axiom compiling itself right now, and to ensure we
get rid of the lower level, we first need to cover enough platforms
which we don't either.  Nowadays, Haskell compiles itself and you need
a working Haskell to compile Haskell.  If you really need to port to a
new platform where no Haskell exists then you can download the
translated C source files and used them as bootstrapping Haskell.
That is quite a common thing to do.

| > Check out Domain Specific Languages (DSLs).  Or if you're washing
| > SPJ's talk, you've probably have heard it by now.  Note also that 
| > Boot+Spad are close to Haskell and ahead of their times.  We want
| > that.  In particular, we don't want to indefinitely stay at the 
| > low level of Lisp.
| 
| I just buzzed through the SPJ slides. I've been a big fan of functional
| programming languages, denotational semantics, etc. since Lisp 1.5. I
| haven't bothered to learn Haskell or any of the ML family yet, partly
| because I don't get paid to write in functional languages, and partly

I didn't get paid either.

| because of all the functional languages around today, the one that I
| think has the strongest legs is Erlang. *That's* the one I'm learning at
| the moment.
| 
| As far as DSLs are concerned, since I also hang out with the Ruby crowd,
| I'm familiar with DSLs. I don't necessarily think they're a good thing

Well, the point is that, each time you write an application, you write
in a DSL: usually a subset of the base language augmented with
libraries.  Now, one can go further adding syntactic sugar and
appropriate optimizatins, etc.

| -- I much prefer, as you seem to, higher-level abstractions in
| programming languages. You may need a hierarchy of languages to get
| there, but do you need it forever?

When you don't get to bootstrap yourself, yes.

[...]

| > Standard ML compilers were once written in Lisp.  They are no more.
| 
| Are they written in Standard ML?

Most of them are now written in SML complitemented with a bit of C.

\start
Date: 10 Aug 2007 08:28:07 -0500
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: re: bootstrap Meta/Boot

Cliff Yapp writes:

[...]

| Quite true.  However, Lisp (at least in the eyes of some) offers a lot
| in a single language.

As does any modern assembly language.


[...]

| * I'm actually trying to get ahold of an old thesis on implementing a
| small Lisp in Forth


If you're going to consider Forth, at least use PostScript :-)

\start
Date: 10 Aug 2007 08:37:08 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

Tim Daly writes:

| > But does it really need so many sub-languages?
| 
| Well, that's a religious question.
| 
| Some on the wailing list feel that Meta and Boot should be recovered,
| made strongly typed, and closer to the algebra language.  On the plus
| side it will be claimed that these are "higher level" (or could be
| made into higher level since they are really just syntactic sugar).
| On the minus side Meta and Boot are languages with 3 people who read
| them and no-one who writes them.

That counts, obviously is inacurate; is the inaccuracy necessary to
make your point?

[...]

| I firmly believe that the internals should be in common lisp. It
| already is common lisp modulo some "syntactic sugar" (e.g. current
| boot). Over the years I've been slowly removing this sugar and using
| only common lisp.

We just has discussions and evidence posted on the list that we are
not using Common Lisp.

\start
Date: 10 Aug 2007 08:39:24 -0500
From: Gabriel Dos Reis
To: Ed Borasky
Subject: re: bootstrap Meta/Boot

Ed Borasky writes:

| Tim Daly wrote:
| >> But does it really need so many sub-languages?
| > 
| > Well, that's a religious question.
| > 
| > Some on the wailing list feel that Meta and Boot should be recovered,
| > made strongly typed, and closer to the algebra language.  On the plus
| > side it will be claimed that these are "higher level" (or could be
| > made into higher level since they are really just syntactic sugar).
| > On the minus side Meta and Boot are languages with 3 people who read
| > them and no-one who writes them.
| 
| Oh ... OK ... Aldor, SPAD, Boot *and* Meta ... yet another language. :)

Notice that the "expert" in Meta following the discussion had
expressed his opinion.  He suggested to move to a single parser, which
would make reviving Meta a non issue.

Now, it you know Spad, them I claim you know Boot.

\start
Date: 10 Aug 2007 08:41:43 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

Tim Daly writes:

| No other language gets this right.

That is a matter of opinion, and open to debate.

\start
Date: Fri, 10 Aug 2007 06:44:02 -0700
From: Ed Borasky
To: list
Subject: re: bootstrap Meta/Boot

C Y wrote:
>> -- I much prefer, as you seem to, higher-level abstractions in
>> programming languages. You may need a hierarchy of languages to get
>> there, but do you need it forever?
> 
> The bootstrap problem occurs when languages become divorced from their
> original implementations in another language - i.e. you need a working
> binary and have no source to compile to create that binary that doesn't
> require the same working binary.  If you can guarantee that you will
> always have a running cross-compiler this is workable, but it seems a
> dangerous assumption to make.

Apparently that was one of the major inspirations for the CMUCL - SBCL
transition. It was, the last time I looked, still *possible* to build
CMUCL from the ground up, but extremely difficult without an existing
CMUCL compiler.

> Interesting you should mention Forth, by the way - in the discussion of
> what constitutes the minimum path for a "hard bootstrap" on
> comp.lang.lisp Forth was suggested as a good way to get the most
> functionality for the least amount of low level machine/assembly
> coding.  I'm currently trying to track down some older work that was
> done on implementing Lisp in Forth.

I may have that buried somewhere -- at one point I acquired just about
everything I could on Forth, and I never threw it away. What was the
title/author/date? A couple of other paths:

1. I think the HP 28 / 48 / 49 series of calculators' RPL (Reverse
Polish Lisp) might be something to look at. I almost always programmed
it in the RPN form rather than the algebraic form, although it supports
both. In any case, it's a very elegant language.

2. More modern is the gForth/vmgen projects of Anton Ertl et. al. gForth
is a GNU implementation of most of ANS Forth in C. IIRC it uses some
extensions to the pure C language from gcc to provide a high-performance
option but will compile with any C. vmgen is more interesting, though.
Using a combination of gcc and gForth, it can be used to generate
efficient virtual machines/interpreters for a number of languages. Ertl
and David Gregg have published a number of papers on the subject, which
you can find at Ertl's web site.

That's one of the reasons I prefer Scheme to Lisp these days ... there
are more low-level hacks and tweaks and virtual machines and other
efficiency-oriented gizmos for Scheme than there are for Lisp.

\start
Date: Fri, 10 Aug 2007 06:57:08 -0700
From: Ed Borasky
To: list
Subject: re: bootstrap Meta/Boot

Gabriel Dos Reis wrote:

> Now, it you know Spad, them I claim you know Boot.

Uh huh ... and if I know Lisp 1.5, I know Common Lisp and Scheme, right?
If I know Algol 60, I know CPL, BCPL, B and C? In some sense, yes, I do.
I'm simply saying that it's a tremendous burden to need to deal with
more than one or two different semantics/syntax pairs in the development
process. Hence, you have specialists, and languages that die either a
quick death or a slow death, unlike Lisp and Scheme (and Forth and APL),
which should probably be described as "living a slow life." :)

Speaking (again) of Derive, I trolled by the Texas Instruments web site
last night and they have discontinued sale of it. I'm not sure how the
inventors of it feel about that. There is something coming soon (in time
for the school year, I would hope) from TI as a successor, but there
were no details on it.

I for one am sad to see Derive go that route. I had one of the very
early HP-28S calculators, and when it finally died, I replaced it with
an HP-100 Palmtop PC with Derive 3 for DOS running in it. I've been a
Derive fan ever since.

So ... what gives a language staying power, and how should Axiom evolve
to get staying power?

\start
Date: 10 Aug 2007 09:10:59 -0500
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: bootstrap Meta/Boot

Cliff Yapp writes:

[...]

| > I wonder, how many people would use such a system. And how many
| > people would be able to maintain it.
| > 
| > Tim, if you are so much concered with bootstrapping, what is wrong in
| > having a very small lisp machinary to get to some state where one
| > could climb the abstraction ladder and define the rest in some
| > (hopefully)  more human readable language?
| 
| Just IMHO, Lisp code intended for human consumption is actually fairly
| readable.  Boot's output is not a good way to judge.

However, active proponents of Lisp rewrite have been very busy replacing
readable Boot codes with unreadable Lisp captured from bootsys.  
As a case in point, people can admire bookvol5.

Independently of that, the rewrite into Lisp is a setback to stoneages.

\start
Date: 10 Aug 2007 09:18:04 -0500
From: Gabriel Dos Reis
To: Ed Borasky
Subject: re: bootstrap Meta/Boot

Ed Borasky writes:

| Gabriel Dos Reis wrote:
| 
| > Now, it you know Spad, them I claim you know Boot.
| 
| Uh huh ... and if I know Lisp 1.5, I know Common Lisp and Scheme, right?

I don't know.  What do you think?

[...]

| I'm not sure how the inventors of it feel about that.

Ask them.

\start
Date: Fri, 10 Aug 2007 07:13:22 -0700
From: Ed Borasky
To: list
Subject: Re: bootstrap Meta/Boot

Tim Daly wrote:
>> Derive ....
> 
> Derive is a fantastic program and often outperformed everything else.
> It is historically interesting, in the "Newton's Notebooks" sense.
> 
> I have spent the last few months trying to convince TI to either
> release the original derive lisp code (which they no longer use)
> or to write a "dead safe" clause that would release the code if
> TI lost interest. It went up the management chain at TI.
> 
> As of last week the effort officially failed.
> 
> Tim
Presumably because they included parts of it in their "new, improved" TI
NSpire product line/vaporware.

Speaking (again) of TI, I've encountered bugs in the derivative finder
on the TI-89 and Voyage 200 calculators. The software for those is
frozen too, because of NSpire. I love my HP-49. :)

\start
Date: 10 Aug 2007 09:21:01 -0500
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Successful build-improvements compilation

Ralf Hemmecke writes:

| make install
| 
| I get the following:
| 
| woodpecker:~/scratch/AXIOM>ls -l
| total 12
| -rwxr-xr-x 1 hemmecke hemmecke 4953 2007-08-08 14:52 bin
| drwx------ 3 hemmecke hemmecke 4096 2007-08-08 14:51 lib
| 
| Yes, "bin" is the axiom shell script not a directory.
| That should be a bug, right?

I've installed the patch below at revision 703.
Please, let me know.  Thanks for your patience.

-- Gaby

*** ChangeLog.build-improvements	(revision 19837)
--- ChangeLog.build-improvements	(local)
***************
*** 1,3 ****
--- 1,9 ----
+ 2007-08-10  Gabriel Dos Reis  Gabriel Dos Reis
+ 
+ 	* Makefile.pamphlet (install): Ensure $(bindir) exists before
+ 	installing axiom script.
+ 	* Makefile.in: Regenerate.
+ 
  2007-08-07  Gabriel Dos Reis  Gabriel Dos Reis
  
  	* configure.ac.pamphlet (axiom_gcl_emacs): New.  Work around
*** Makefile.in	(revision 19837)
--- Makefile.in	(local)
*************** install:
*** 78,83 ****
--- 78,84 ----
  	@mkdir -p $(DESTDIR)$(libdir)/axiom
  	@cp -pr $(builddir)/target $(DESTDIR)$(libdir)/axiom
  	@ rm -f $(bindir)/axiom
+ 	@ $(mkinstalldirs) $(bindir)
  	@ $(INSTALL_PROGRAM) src/scripts/axiom $(bindir)
  	@echo Axiom installation finished.
  
*** Makefile.pamphlet	(revision 19837)
--- Makefile.pamphlet	(local)
*************** install:
*** 654,659 ****
--- 654,660 ----
  	@mkdir -p $(DESTDIR)$(libdir)/axiom
  	@cp -pr $(builddir)/target $(DESTDIR)$(libdir)/axiom
  	@ rm -f $(bindir)/axiom
+ 	@ $(mkinstalldirs) $(bindir)
  	@ $(INSTALL_PROGRAM) src/scripts/axiom $(bindir)
  	@echo Axiom installation finished.
  @

\start
Date: Fri, 10 Aug 2007 10:36:56 -0400
From: Bill Page
To: Cliff Yapp
Subject: Re: Lisp in Small Pieces

On 8/10/07, C Y wrote:
> Not at $4 any more. I didn't notice it in time.  Arrrgh.
>

:-) I think I got the last one. When I went to amazon.ca it said: 1
new copy for $3.99 and about 10 used copies for about $70. I was
afraid the my order would be cancelled by the time I got to check-out
but in the end I got a confirmation email that said I would be
receiving my book for $3.99 + about $6 for shipping, not bad for 900+
page book I thought. Now we will see if it actually shows up in a few
days.

\start
Date: Fri, 10 Aug 2007 17:01:09 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: Successful build-improvements compilation

Since you've only changed something to the "install" target, I simply 
said (-r703)

I removed /home/hemmecke/scratch/AXIOM completely.

woodpecker:~/OTHER/Axiom/out-of-source-build-improvements> 
~/SVK/axiom/branches/build-improvements/configure 
--prefix=/home/hemmecke/scratch/AXIOM
make install

It still doesn't give me hypertex. There is no such file in that directory.

But I find it here....

woodpecker:~/OTHER/Axiom/out-of-source-build-improvements>find . -name 
hypertex
./target/i686-pc-linux/lib/hypertex
./target/i686-pc-linux/share/hypertex

Maybe I should start from scratch? Or is the installation routine still 
wrong?

Ralf

woodpecker:~/scratch/AXIOM>bin/axiom
/bin/sh: 
/home/hemmecke/scratch/AXIOM/lib/axiom/target/i686-pc-linux/bin/hypertex: 
No such file or directory
/bin/sh: line 0: exec: 
/home/hemmecke/scratch/AXIOM/lib/axiom/target/i686-pc-linux/bin/hypertex: 
cannot execute: No such file or directory
GCL (GNU Common Lisp)  2.6.8 CLtL1    Aug  8 2007 11:35:36

On 08/10/2007 04:21 PM, Gabriel Dos Reis wrote:
> Ralf Hemmecke writes:
> 
> | make install
> | 
> | I get the following:
> | 
> | woodpecker:~/scratch/AXIOM>ls -l
> | total 12
> | -rwxr-xr-x 1 hemmecke hemmecke 4953 2007-08-08 14:52 bin
> | drwx------ 3 hemmecke hemmecke 4096 2007-08-08 14:51 lib
> | 
> | Yes, "bin" is the axiom shell script not a directory.
> | That should be a bug, right?
> 
> I've installed the patch below at revision 703.
> Please, let me know.  Thanks for your patience.

\start
Date: Fri, 10 Aug 2007 11:03:55 -0400
From: Bill Page
To: Cliff Yapp
Subject: re: bootstrap Meta/Boot

On 8/10/07, C Y wrote:
> --- Ed Borasky wrote:
>
> > Well, considering the long history of Axiom and its predecessors,
> > that's not surprising. But once you *have* Axiom capable of compiling
> > itself, do you really need the underlying scaffolding, or can you
> > take it down and just use the building?
>
> You take it down only if you are sure you will never again need to
> re-build the building.
>
> I am quite sure the original team probably reached the same conclusion,
> but the fact remains that the original system had to be re-bootstrapped
> by Tim for public release.  So we already have one example where the
> loss of the scaffolding was a major inconvenience.
>

Well, actually I think that was just a misunderstanding on Tim's part.
Other emails on this list from Mike Dewar of NAG have made it clear
that NAG would have had no objections to releasing an open source
version of Axiom that required a running Axiom to compile.

\start
Date: Fri, 10 Aug 2007 10:11:13 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Successful build-improvements compilation

On Fri, 10 Aug 2007, Ralf Hemmecke wrote:

| Maybe I should start from scratch?


Yes, please try that one.  
I don't see that failure here.

The reason I was not seeing the previous failure was that my $(bindir) was
always /usr/local/bin, which always existed.
However, the hypertex binaries are sequestered inside Axiom's install
path so, I don't understand why you're seeing that failure and not me.

\start
Date: Fri, 10 Aug 2007 10:14:20 -0500 (CDT)
From: Gabriel Dos Reis
To: list
Subject: Re: [fricas-devel] Re: Sage Build, a few more hiccups
Cc: Pete Chvany

On Fri, 10 Aug 2007, William Stein wrote:

[...]

| >
| > ++++++++++++++++++++++++++
| >
| > Errors with Axiom:
| >
| [...]
| 
| I won't say anything further about this because:
|   (1) My understanding is that Axiom has never been ported to OSX;
| they only support
| Linux and Windows.  So it's shouldn't work on OS X.
|   (2) FriCAS (a fork of Axiom) is very likely going to replace Axiom
| in SAGE.  And
| my impression of the amazing skills of they guy who started the FriCAS project
| with all things related to build processes suggests FriCAS will support OS X
| in the near future.

It has been reported many times, that Axiom can be built on OSX.  So, if there
is any outstanding issue with respect to Axiom build on OSX, it would be
good to report to Axiom people.  I'm CC:int axiom-developer.

\start
Date: Fri, 10 Aug 2007 10:17:29 -0500
From: Tim Daly
To: Ralf Hemmecke
Subject: bootstrap Meta/Boot

Tim wrote:
>> Fortunately in the brave new world we seem to inhabit, there is no
>> sticking place for your objection. You can create your own branch and
>> thus recontruct Meta in Meta and Boot in Boot.

Ralf wrote:
> And whoever wants to rewrite everything in LISP should create a new
> branch and write Axiom in Common Lisp so that on the list
>
> http://wiki.axiom-developer.org/AxiomProgramming
>
> *only* LISP remains No BOOT, no SHOE, no SPAD.

In fact, I created a whole project with that almost that subgoal.
The project is on sourceforge and savannah. The work has traditionally
involved rewriting only in Common Lisp and Spad. I've been at it for
years now.

\start
Date: 10 Aug 2007 10:31:51 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Variables in traceComp

Tim --

Consider the function traceComp from spad.lisp 

(defun |traceComp| ()
  (SETQ |$compCount| 0)
  (EMBED '|comp|
     '(LAMBDA (X Y Z)
	 (PROG (U)
	       (SETQ |$compCount| (1+ |$compCount|))
	       (SETQ |yesOrNo| (if (SETQ U (|comp| X Y Z))
				   (if (EQUAL (SECOND U) Y) '|yes| (SECOND U))
				 ('T '|no|)))
	       (|sayBrightly| (CONS (MAKE-FULL-CVEC |$compCount| " ")
				    (LIST X " --> " Y '|%b| |yesOrNo| '|%d|)))
	       (SETQ |$compCount| (1- |$compCount|))
	       (RETURN U)  )))
  (|comp| $x $m $f)
  (UNEMBED '|comp|))


I cannot find a relevant definition of the variables $x, $m, and $f.
Neither can the SBCL compiler.  Is it likely that when you translated
the original Boot code to Lisp you mistyped $x for |$x|, etc?

\start
Date: Fri, 10 Aug 2007 11:36:22 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: Successful build-improvements compilation

On 8/10/07, Gabriel Dos Reis wrote:
> On Fri, 10 Aug 2007, Ralf Hemmecke wrote:
>
> | Maybe I should start from scratch?
>
>
> Yes, please try that one.
> I don't see that failure here.
>
> The reason I was not seeing the previous failure was that my $(bindir) was
> always /usr/local/bin, which always existed.
> However, the hypertex binaries are sequestered inside Axiom's install
> path so, I don't understand why you're seeing that failure and not me.
>

Gaby,

I am seeing the same failure when I build Axiom from
build-improvements for use under Sage. Sage requires that the install
paths be local to Sage. The system where I am trying this runs Debian.

This also happens on the axiom.risc mirror server which we are
re-building from scratch due to a hard disk failure. This server is
also running Debian.

If the solution requires more input, I can send you some build logs
(much) later today.

\start
Date: 10 Aug 2007 10:39:37 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: |New,ENTRY,2|

Tim --

  Consider the routine 

(defun |New,ENTRY,2| (RULE FN INPUTSTREAM) (declare (special INPUTSTREAM))
  (let (zz)
      (INITIALIZE)
      (SETQ $previousTime (TEMPUS-FUGIT))
      (setq ZZ (CONVERSATION '|PARSE-NewExpr| '|process|))
      (REMFLAG |boot-NewKEY| 'KEY)
      INPUTSTREAM))

from spad.lisp.

When you translated the original code form BOOT to Lisp, you misted
$previousTime for |$previousTime|.

\start
Date: Fri, 10 Aug 2007 10:41:45 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: Successful build-improvements compilation

On Fri, 10 Aug 2007, Bill Page wrote:

| On 8/10/07, Gabriel Dos Reis wrote:
| > On Fri, 10 Aug 2007, Ralf Hemmecke wrote:
| >
| > | Maybe I should start from scratch?
| >
| >
| > Yes, please try that one.
| > I don't see that failure here.
| >
| > The reason I was not seeing the previous failure was that my $(bindir) was
| > always /usr/local/bin, which always existed.
| > However, the hypertex binaries are sequestered inside Axiom's install
| > path so, I don't understand why you're seeing that failure and not me.
| >
| 
| Gaby,
| 
| I am seeing the same failure when I build Axiom from
| build-improvements for use under Sage. Sage requires that the install
| paths be local to Sage. The system where I am trying this runs Debian.
| 
| This also happens on the axiom.risc mirror server which we are
| re-building from scratch due to a hard disk failure. This server is
| also running Debian.

OK, so there must be something special with my settings and that is
not supposed to happen.

Investigating...

\start
Date: Fri, 10 Aug 2007 08:44:39 -0700 (PDT)
From: Cliff Yapp
To: Ed Borasky
Subject: re: bootstrap Meta/Boot

--- Ed Borasky wrote:

> I may have that buried somewhere -- at one point I acquired just
> about everything I could on Forth, and I never threw it away. What
> was the title/author/date? A couple of other paths:

The papers, which I can't find:
http://portal.acm.org/citation.cfm?id=59413.59435
http://portal.acm.org/citation.cfm?id=59413.59429

A thesis, which I might be able to request from Florida Tech

TLISP: A Small Lisp Interpreter Implemented in Forth
 Suryadevara, Prasad  Thomas Hand 
http://www.cs.fit.edu/~wds/research/theses/

> 1. I think the HP 28 / 48 / 49 series of calculators' RPL (Reverse
> Polish Lisp) might be something to look at. I almost always
> programmed it in the RPN form rather than the algebraic form,
> although it supports both. In any case, it's a very elegant language.

Indeed.  Is there a language definition somewhere for those
calculators?

> 2. More modern is the gForth/vmgen projects of Anton Ertl et. al.
> gForth is a GNU implementation of most of ANS Forth in C. IIRC it
> uses some extensions to the pure C language from gcc to provide a
> high-performance option but will compile with any C. vmgen is more
> interesting, though. Using a combination of gcc and gForth, it can
> be used to generate efficient virtual machines/interpreters for a
> number of languages. Ertl and David Gregg have published a number of
> papers on the subject, which you can find at Ertl's web site.

Neat!  The appeal of Forth for me was the "bootstrap with only bare
metal" scenario but that's primarily an historical problem these days.

> That's one of the reasons I prefer Scheme to Lisp these days ...
> there are more low-level hacks and tweaks and virtual machines and
> other efficiency-oriented gizmos for Scheme than there are for Lisp.

Probably due to the uses to which each is put - scheme, being smaller,
makes more sense for embedded applications and performance tweaks are
more critical there - applications are still hardware limited.

\start
Date: Fri, 10 Aug 2007 08:51:41 -0700 (PDT)
From: Cliff Yapp
To: Gabriel Dos Reis
Subject: Re: bootstrap Meta/Boot

--- Gabriel Dos Reis wrote:

> However, active proponents of Lisp rewrite have been very busy
> replacing readable Boot codes with unreadable Lisp captured from
> bootsys.   As a case in point, people can admire bookvol5.

FWIW, in my case that's not what I mean when I refer to a lisp rewrite.

> Independently of that, the rewrite into Lisp is a setback to
> stoneages.

A matter of opinion, unless you have some methodology to offer which
allows the question to be decided according to objective measurements. 
However, it seems people are pursuing their various directions anyway
so it doesn't appear to be worth wasting time on any more debate.  If
anyone were going to convince anyone else I would have expected it to
happen by now.  The only way from this point is to have people try
things and make decisions based on experience.

\start
Date: Fri, 10 Aug 2007 10:58:21 -0500 (CDT)
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: Re: bootstrap Meta/Boot

On Fri, 10 Aug 2007, C Y wrote:

| --- Gabriel Dos Reis wrote:
| 
| > However, active proponents of Lisp rewrite have been very busy
| > replacing readable Boot codes with unreadable Lisp captured from
| > bootsys.   As a case in point, people can admire bookvol5.
| 
| FWIW, in my case that's not what I mean when I refer to a lisp rewrite.

I'm looking forward to your concrete realization.

\start
Date: 10 Aug 2007 11:05:33 -0500
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: Successful build-improvements compilation

Bill Page writes:

| On 8/10/07, Gabriel Dos Reis wrote:
| > On Fri, 10 Aug 2007, Ralf Hemmecke wrote:
| >
| > | Maybe I should start from scratch?
| >
| >
| > Yes, please try that one.
| > I don't see that failure here.
| >
| > The reason I was not seeing the previous failure was that my $(bindir) was
| > always /usr/local/bin, which always existed.
| > However, the hypertex binaries are sequestered inside Axiom's install
| > path so, I don't understand why you're seeing that failure and not me.
| >
| 
| Gaby,
| 
| I am seeing the same failure when I build Axiom from
| build-improvements for use under Sage. Sage requires that the install
| paths be local to Sage. The system where I am trying this runs Debian.

Ralf, Bill --

  Issue tracked down and fixed.  Patch installed at revision 704.

Many thanks,

-- Gaby

*** src/sman/ChangeLog.build-improvements	(revision 19838)
--- src/sman/ChangeLog.build-improvements	(local)
***************
*** 1,3 ****
--- 1,8 ----
+ 2007-08-10  Gabriel Dos Reis  Gabriel Dos Reis
+ 
+ 	* sman.c.pamphlet (HypertexProgram): hypertex is installed in lib/
+ 	directory. 
+ 
  2007-07-29  Gabriel Dos Reis  Gabriel Dos Reis
  
  	* Makefile.pamphlet: Propagate libtoolization changes.
*** src/sman/sman.c.pamphlet	(revision 19838)
--- src/sman/sman.c.pamphlet	(local)
*************** int server_num;			/* AXIOM server number
*** 113,119 ****
  
  char	*GraphicsProgram        = "$AXIOM/lib/viewman";
  char    *NagManagerProgram      = "$AXIOM/lib/nagman";
! char	*HypertexProgram        = "$AXIOM/bin/hypertex -s";
  <<clefprogram>>
  char	*SessionManagerProgram  = "$AXIOM/lib/session";
  char	*SpadClientProgram      = "$AXIOM/lib/spadclient";
--- 113,119 ----
  
  char	*GraphicsProgram        = "$AXIOM/lib/viewman";
  char    *NagManagerProgram      = "$AXIOM/lib/nagman";
! char	*HypertexProgram        = "$AXIOM/lib/hypertex -s";
  <<clefprogram>>
  char	*SessionManagerProgram  = "$AXIOM/lib/session";
  char	*SpadClientProgram      = "$AXIOM/lib/spadclient";

\start
Date: Fri, 10 Aug 2007 11:13:54 -0500
From: Tim Daly
To: Ralf Hemmecke
Subject: bootstrap Meta/Boot

> BTW, why do you think it is so essential that the underlying language of
> Axiom must be LISP? 

I don't. In fact, we've had discussions about using Aldor all the way
down.  I don't have the time to rewrite everything in Aldor.  But it
already is in Lisp. Boot is just syntactic sugar for Lisp which limits
what you can write and obscures the syntax.

Writing Boot to generate Lisp is like writing Fortran to generate Aldor.
If you are a Fortran programmer you won't see why that's a problem.
If you are an Aldor programmer you can't imagine why that isn't a problem.

But you can't make Fortran programmers into Aldor programmers.
They have to want to learn.




> If I now start a branch and convert Axiom to Haskell,
> or Assembler would you object?

Nope. It's your time. If you want to rewrite 23 years worth of work
into another language, go for it.




> Would you be interested?

Nope.

The "human readable" language is English. 
That's the whole point of literate programming.

I'm focused on getting the interpreter, compiler, and other internal
machinery into a clean, uniform, literate form in one already existing
language. My focus is on organizing and explaining what is already there.

\start
Date: 10 Aug 2007 11:25:03 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

Tim Daly writes:

[...]

| Writing Boot to generate Lisp is like writing Fortran to generate Aldor.
| If you are a Fortran programmer you won't see why that's a problem.
| If you are an Aldor programmer you can't imagine why that isn't a problem.
| 
| But you can't make Fortran programmers into Aldor programmers.

 Proof by analogy is fraud.

\start
Date: 10 Aug 2007 11:26:05 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

Tim Daly writes:

[...]

| The "human readable" language is English. 

Well, that is probably when one discounts other natural languages around.

\start
Date: Fri, 10 Aug 2007 11:24:56 -0500
From: Tim Daly
To: Bill Page
Subject: bootstrap Meta/Boot

Bill writes:
> Well, actually I think that was just a misunderstanding on Tim's part.
> Other emails on this list from Mike Dewar of NAG have made it clear
> that NAG would have had no objections to releasing an open source
> version of Axiom that required a running Axiom to compile.

Please reference those emails.

\start
Date: 10 Aug 2007 11:28:27 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: $traceflag

  I believe the use of  $TRACEFLAG in the routine S-PROCESS (spad.lisp)
is a typo for |$TraceFlag|.

\start
Date: Fri, 10 Aug 2007 11:33:47 -0500
From: Tim Daly
To: Bill Page
Subject: bootstrap Meta/Boot

Tim writes:
>> Writing Boot to generate Lisp is like writing Fortran to generate Aldor.
>> If you are a Fortran programmer you won't see why that is a problem.
>> If you are an Aldor programmer you can't imagine why that isn't a problem.

Gaby writes:
> Proof by analogy is fraud.

Yes, it is.
Reasoning by analogy is not.

\start
Date: 10 Aug 2007 11:43:11 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

Tim Daly writes:

| Tim writes:
| >> Writing Boot to generate Lisp is like writing Fortran to generate Aldor.
| >> If you are a Fortran programmer you won't see why that is a problem.
| >> If you are an Aldor programmer you can't imagine why that isn't a problem.
| 
| Gaby writes:
| > Proof by analogy is fraud.
| 
| Yes, it is.
| Reasoning by analogy is not.

Define "reasoning".

\start
Date: Fri, 10 Aug 2007 18:38:55 +0200
From: Juergen Weiss
To: Gabriel Dos Reis,
Subject: RE: |New,ENTRY,2|

Hi,

Tim is probably innocent of this one and the last one. This code as not
been changed in at least the last 16 years. And even if he is not --
it's
so long ago that it certainly became time-barred.

Regards

Juergen

P.S.: Most of this broken code is probably not used - but you already
know
that ;-).

Juergen Weiss	  | Universitaet Mainz, Zentrum fuer Datenverarbeitung,
Juergen Weiss| 55099 Mainz, Tel: +49(6131)39-26361, FAX:
+49(6131)39-26407


> -----Original Message-----
> From: axiom-developer-bounces+weiss=uni-mainz.de@nongnu.org
>  On Behalf Of Gabriel Dos Reis
> Sent: Friday, August 10, 2007 5:40 PM
> To: Tim Daly
> Cc: list
> Subject: |New,ENTRY,2|
>
>
> Tim --
>
>   Consider the routine
>
> (defun |New,ENTRY,2| (RULE FN INPUTSTREAM) (declare (special
> INPUTSTREAM))
>   (let (zz)
>       (INITIALIZE)
>       (SETQ $previousTime (TEMPUS-FUGIT))
>       (setq ZZ (CONVERSATION '|PARSE-NewExpr| '|process|))
>       (REMFLAG |boot-NewKEY| 'KEY)
>       INPUTSTREAM))
>
> from spad.lisp.
>
> When you translated the original code form BOOT to Lisp, you misted
> $previousTime for |$previousTime|.

\start
Date: 10 Aug 2007 11:39:11 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: NewSYSTOK

  There is this line in spad.lisp

      (SETQ SINGLINEMODE T)   ; SEE NewSYSTOK

Where is NewSYSTOK?

\start
Date: Fri, 10 Aug 2007 11:42:49 -0500 (CDT)
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: RE: |New,ENTRY,2|

On Fri, 10 Aug 2007, Weiss, Juergen wrote:

| Hi,
| 
| Tim is probably innocent of this one and the last one.

Ah, OK.  That file listed his name as author, so I assumed
he is to be blamed :-) :-)

| This code as not
| been changed in at least the last 16 years. And even if he is not --
| it's
| so long ago that it certainly became time-barred.

Thanks!

| Regards
| 
| Juergen
| 
| P.S.: Most of this broken code is probably not used - but you already
| know
| that ;-).

Yup; and that is what is making my life miserable at the moment ;-)

\start
Date: 10 Aug 2007 11:45:41 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Use of $

The file spad.lisp contains the following line at toplevel:

   ;; the following initialization of $ must not be a defvar
   ;; since that make $ special
   (setq $ '$) ;; used in def of Ring which is Algebra($)


What is the problem it is intended to solve, and how does that solve
the problem?

The SBCL compiler does not like it, because it thinks $ is not defined.

\start
Date: 10 Aug 2007 12:54:36 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Definition of big float marker

  $BFtag has conflicting settings.

In bootfuns.lisp, it is defined as

        (def-boot-val |$BFtag| '-BF-	   "big float marker")

However, setq.lisp want to set it at

        (setq |$BFtag| '|:BF:|)


Brute force grep reveals both postprop.lisp and property.lisp want
'|:BF:|.

\start
Date: Fri, 10 Aug 2007 14:00:25 -0400
From: Bill Page
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

http://lists.nongnu.org/archive/html/axiom-developer/2005-11/msg00211.html

From: 	Mike Dewar
Subject: 	Re: letting my mud settle
Date: 	Wed, 9 Nov 2005 10:40:09 +0000
User-agent: 	Mutt/1.4.1i

On Tue, Nov 08, 2005 at 12:09:23PM -0500, Bill Page wrote:
> I am not aware of any of Tim's past sins -- only his present
> ones. ;) Building Axiom from sources only, which was apparently
> a requirement imposed by restrictive licensing conditions which
> apparently prevented any of the previously commercial binary
> versions of Axiom to be distributed along with the Axiom source
> code, was certainly a challenge because of the way that Axiom
> had been designed to be "bootstrapped" from an existing running
> copy. But this is no different than the situation with most
> compilers and in particular GNU C (gcc).
Just for the record this is not true.  Arthur Norman offered to provide
an open-source version of CCL to the project which would have allowed
you to build and distribute a Unix version of Axiom from the original NAG
sources without any modifications.  I provided copies of the Axiom
product to several people on the list so you would have had no problem
bootstrapping the first open-source versions from the NAG code.

Eliminating the need for a running Axiom was a good thing to do, but if
anything forced you to do it it was probably the decision to develop on
GCL rather than CCL.

Cheers, Mike.

http://lists.nongnu.org/archive/html/axiom-developer/2005-11/msg00220.html

From: 	Mike Dewar
Subject: 	Re: letting my mud settle
Date: 	Wed, 9 Nov 2005 17:42:31 +0000
User-agent: 	Mutt/1.4.1i

On Wed, Nov 09, 2005 at 09:50:51AM -0500, Bill Page wrote:
> Do you mean that this original "Axiom product" binary - as distinct
> from the commercial binary version - could have been distributed as
> part of the original open source distribution? If that is true, it
> makes me sad that Tim went to all the trouble to embed bootstrap lisp
> code into the build process.
No, I mean that you could have bootstrapped the first open source binary
from the commercial system, and then distributed that first open
source-derived binary.

Cheers, Mike.

-------------------

On 8/10/07, Tim Daly wrote:
> Bill writes:
> > Well, actually I think that was just a misunderstanding on Tim's part.
> > Other emails on this list from Mike Dewar of NAG have made it clear
> > that NAG would have had no objections to releasing an open source
> > version of Axiom that required a running Axiom to compile.
>
> Please reference those emails.

\start
Date: Fri, 10 Aug 2007 13:17:31 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: Definition of big float marker

I think you're seeing symptoms of the massive amount of change
that happened in the scratchpad project. We had so many "new"
changes that the word "new" (as in the new-new-new-new boot
parser) lost all meaning. The things you're finding are either
in dead code or are redefinitions affected by file load order.

All I can suggest is to decide which marker is correct,
move it to the global list in bookvol5, and document its use.

\start
Date: Fri, 10 Aug 2007 13:24:43 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: Definition of big float marker

On Fri, 10 Aug 2007, Tim Daly wrote:

|                           The things you're finding are either
| in dead code or are redefinitions affected by file load order.

OK.

Having all files in Axiom being compiled and properly setting up
dependencies is a good way of discovering many scary bugs.

| All I can suggest is to decide which marker is correct,
| move it to the global list in bookvol5, and document its use.

In my local tree, I'm moving them to bootfuns.lisp and make them
defconstant, as opposed to defparameter or defvar.  Though I'm sure a batter
place exists (which is not bookvol5).

bookvol5 should be stripped down so that logical logical definitions go at
natural places, not just bookvol5.  Many things in bookvol5 do not
belong there, and are not needed to build depsys.

\start
Date: 10 Aug 2007 13:35:05 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: B-MDEF

  The SBCL compiler does not like the definition of B-MDEF in def.lisp:

(defun B-MDEF (FORM SIGNATURE $BODY)
  (declare (ignore SIGNATURE))
  (let* ($OpAssoc
	 ($op (first form))
	 (argl (cdr form))
	 (GARGL (MAPCAR '(LAMBDA (X) (GENSYM)) ARGL))
	 ($BODY (SUBLISLIS GARGL ARGL (|bootTransform| (DEFTRAN $BODY))))
	 ($BODY (LIST 'SUBLISLIS (CONS 'LIST GARGL) 
		      (LIST 'QUOTE GARGL) (LIST 'QUOTE $BODY))))
    (COMP (SUBLIS $OPASSOC
		  (LIST (LIST $OP (LIST 'MLAMBDA (CONS () GARGL) $BODY)))))))

Saying that:

; file: /home/gdr/build/bi/src/interp/def.lisp
; in: DEFUN B-MDEF
;     (MAPCAR '(LAMBDA (BOOT::X) (GENSYM)) BOOT::ARGL)
; --> LET SB-INT:DO-ANONYMOUS BLOCK LET TAGBODY TAGBODY RPLACD LET PROGN SETF 
; --> SB-KERNEL:%RPLACD SETQ THE LIST CONS 
; ==>
;   (FUNCALL #:G70 (CAR #:G69))
; 
; caught WARNING:
;   Asserted type (OR FUNCTION SYMBOL) conflicts with derived type
;   (VALUES CONS &OPTIONAL).
;   See also:
;     The SBCL Manual, Node "Handling of Types"


Indeed, in 
        
        (GARGL (MAPCAR '(LAMBDA (X) (GENSYM)) ARGL))

we really want to say

        (GARGL (MAPCAR #'(LAMBDA (X) (GENSYM)) ARGL))
                       ^
                     was missing

\start
Date: Fri, 10 Aug 2007 14:29:06 -0500
From: Tim Daly
To: Bill Page
Subject: bootstrap Meta/Boot

Mike was certainly very helpful in the early effort to get things
running and I intend no criticism of either his efforts or NAG.

What you said was:
> Other emails on this list from Mike Dewar of NAG have made it clear
> that NAG would have had no objections to releasing an open source
> version of Axiom that required a running Axiom to compile.

Well, clearly NAG would have no opinion about the structure of
the open source building process. Why could they possibly care?
And why is this relevant?




But it is certainly true that there were "restrictive licensing
conditions which apparently prevented any of the previously
COMMERCIAL binary version of Axiom to be distributed along with
the Axiom source code". Unfortunately that conversation is in
private emails.

As for "I provided copies of the Axiom product to several people on
the list so you would have no problem bootstrapping the first
open-source versions from the NAG code"... I did receive a NAG version
of Axiom. I don't remember anyone else who got copies directly from NAG
so I'm unable to comment.  I'm unaware of anyone else working on
open-sourcing Axiom. But Mike and NAG were very helpful here and I 
again publicly thank them for their support.



The bootstrap-from-Axiom issue is not related to the CCL change.
Building Axiom from Axiom is ok if you own the whole project.  But
requiring a running Axiom to build Axiom was not a viable open source
strategy. I didn't see a way to distribute sources that included
pre-compiled binaries.

As for the change from CCL to GCL I've already explained that I was
unable to build a CCL version of Axiom. I spent several months (Sept
to Jan) on the problem.  




In any case I've distributed the original sources to the world.  Since
you raised the issue it appears that you would rather have a different
building strategy than we currently use.  You have the original
sources so you're welcome to create your own branch and try.

\start
Date: 10 Aug 2007 14:42:57 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

Tim Daly writes:

[...]

| The bootstrap-from-Axiom issue is not related to the CCL change.
| Building Axiom from Axiom is ok if you own the whole project.  But
| requiring a running Axiom to build Axiom was not a viable open source
| strategy. I didn't see a way to distribute sources that included
| pre-compiled binaries.

But, you could have built a binary of the open sourced Axiom and put
it there for bootstrapping.  Since most of the stuff were mostly
Linux, you could have done that and the world would have picked up --
as it does today -- and to extend it to other platforms where needed.

[...]

| In any case I've distributed the original sources to the world. 

do you still have a link to the original open sourced Axiom from NAG?

\start
Date: Fri, 10 Aug 2007 15:43:57 -0400
From: Bill Page
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

On 8/10/07, Tim Daly wrote:
> ...
> In any case I've distributed the original sources to the world.  Since
> you raised the issue it appears that you would rather have a different
> building strategy than we currently use.  You have the original
> sources so you're welcome to create your own branch and try.
>

Waldek posted a message to this list a couple of months ago stating
that he had successfully built Axiom from the original NAG sources
using CCL. (Please check the archives.)

\start
Date: Fri, 10 Aug 2007 20:45:38 -0500
From: Tim Daly
To: list
Subject: 20070810.01.tpd.patch

This patch removes src/interp/metameta.lisp.pamphlet which is
no longer used. It assumes the following previously posted
patches have been applied:
20070721.01.tpd.patch
20070721.02.tpd.patch
20070722.01.tpd.patch

===========================================================================
diff --git a/changelog b/changelog
index 962132e..7cbe49b 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,65 @@
+20070810 tpd src/interp/metameta.lisp removed (unused)
+20070810 tpd src/interp/ccl-depsys.lsp remove metameta
+20070810 tpd src/interp/parsing.lisp remove metameta
+20070810 tpd src/interp/Makefile remove metameta
+20070810 tpd src/interp/debugsys.lisp remove metameta.lisp load
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-REPEATOR
+20070810 tpd src/interp/metameta.lisp unused PARSE-REPEATOR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-OPT_EXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-OPT_EXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-LOCAL_VAR
+20070810 tpd src/interp/metameta.lisp unused PARSE-LOCAL_VAR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-DEST_REF
+20070810 tpd src/interp/metameta.lisp unused PARSE-DEST_REF
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-NON_DEST_REF
+20070810 tpd src/interp/metameta.lisp unused PARSE-NON_DEST_REF
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-SEXPR_STRING
+20070810 tpd src/interp/metameta.lisp unused PARSE-SEXPR_STRING
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-CONS_SEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-CONS_SEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-REF_SEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-REF_SEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-SEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-SEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-N_TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-N_TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-REP_TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-REP_TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-FIL_TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-FIL_TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-SUBEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-SUBEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-EXPR2
+20070810 tpd src/interp/metameta.lisp unused PARSE-EXPR2
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-EXPR1
+20070810 tpd src/interp/metameta.lisp unused PARSE-EXPR1
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-EXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-EXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-FID
+20070810 tpd src/interp/metameta.lisp unused PARSE-FID
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-RULE1
+20070810 tpd src/interp/metameta.lisp unused PARSE-RULE1
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-RULE
+20070810 tpd src/interp/metameta.lisp unused PARSE-RULE
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-HEADER
+20070810 tpd src/interp/metameta.lisp unused PARSE-HEADER
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-PROGRAM
+20070810 tpd src/interp/metameta.lisp unused parse-program
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::IN-META
+20070810 tpd src/interp/metalex.lisp.pamphlet unused in-meta function
+20070810 tpd src/interp/metalex.lisp.pamphlet unused meta function
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::NEWRULE
+20070810 tpd src/interp/metalex.lisp unused newrule 
+20070810 tpd src/interp/spad.lisp unused TRAPFLAG
+20070810 tpd src/interp/debug.lisp unused TRAPFLAG
+20070810 tpd src/interp/debug.lisp unused (MAKEPROP 'META '/TRAN '/TRANSMETA)
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::/TRANSMETA
+20070810 tpd src/interp/spad.lisp unused /transmeta 
+20070810 tpd src/interp/parsing.lisp unused transpgvar 
+20070810 tpd src/interp/sys-pkg.lisp unused BOOT::TRANSPGVAR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::TRANSPGVAR
 20070722 tpd src/interp/Makefile cleanup latex warnings
 20070721 wxh src/interp/spad.lisp make evalSharpOne declare arg specials
 20070721 tpd src/interp/setq.lisp update contributor name list
diff --git a/src/boot/ccl-depsys.lsp.pamphlet b/src/boot/ccl-depsys.lsp.pamphlet
index e6a94f8..b0e91fc 100644
--- a/src/boot/ccl-depsys.lsp.pamphlet
+++ b/src/boot/ccl-depsys.lsp.pamphlet
@@ -63,7 +63,6 @@
 (load "def.lisp")
 (load "fnewmeta.lisp")
 (load "metalex.lisp")
-(load "metameta.lisp")
 (load "postprop.lisp")
 (load "preparse.lisp")
 
diff --git a/src/doc/axiom.bib.pamphlet b/src/doc/axiom.bib.pamphlet
index 4bb27e4..97204c7 100644
--- a/src/doc/axiom.bib.pamphlet
+++ b/src/doc/axiom.bib.pamphlet
@@ -671,13 +671,6 @@ pamphlet and booklet files.
 }
 
 @
-\subsection{metameta.lisp}
-<<metameta.lisp>>=
-@MISC{metameta.lisp,
-   path=./src/interp/metameta.lisp.pamphlet
-}
-
-@
 \subsection{modemap.boot}
 <<modemap.boot>>=
 @MISC{modemap.boot,
@@ -13873,13 +13866,6 @@ pamphlet and booklet files.
 }
 
 @
-\subsection{metameta.lisp}
-<<metameta.lisp>>=
-@MISC{metameta.lisp,
-   path=./new/src/interp/metameta.lisp.pamphlet
-}
-
-@
 \subsection{modemap.boot}
 <<modemap.boot>>=
 @MISC{modemap.boot,
@@ -20850,7 +20836,6 @@ pamphlet and booklet files.
 <<macros.lisp>>
 <<metalex.lisp>>
 <<mark.boot>>
-<<metameta.lisp>>
 <<modemap.boot>>
 <<monitor.lisp>>
 <<nci.lisp>>
@@ -22736,7 +22721,6 @@ pamphlet and booklet files.
 <<mark.boot>>
 <<match.boot>>
 <<metalex.lisp>>
-<<metameta.lisp>>
 <<modemap.boot>>
 <<monitor.lisp>>
 <<msg.boot>>
diff --git a/src/interp/Makefile.pamphlet b/src/interp/Makefile.pamphlet
index 23ec4cc..3fa2d97 100644
--- a/src/interp/Makefile.pamphlet
+++ b/src/interp/Makefile.pamphlet
@@ -244,7 +244,6 @@ generations of ``old'' and all meaning of the term is lost.
 OPOBJS=	${AUTO}/parsing.${O}	${AUTO}/bootlex.${O}	\
         ${AUTO}/def.${O}	\
 	${AUTO}/fnewmeta.${O}	${AUTO}/metalex.${O}	\
-	${AUTO}/metameta.${O}	\
 	${AUTO}/parse.${O}	${AUTO}/postpar.${O}	\
 	${AUTO}/postprop.${LISP}	${AUTO}/preparse.${O}
 
@@ -460,7 +459,7 @@ DOCFILES=${DOC}/alql.boot.dvi \
 	 ${DOC}/lisplib.boot.dvi ${DOC}/macex.boot.dvi \
 	 ${DOC}/macros.lisp.dvi ${DOC}/Makefile.dvi \
 	 ${DOC}/mark.boot.dvi ${DOC}/match.boot.dvi \
-	 ${DOC}/metalex.lisp.dvi ${DOC}/metameta.lisp.dvi \
+	 ${DOC}/metalex.lisp.dvi  \
 	 ${DOC}/modemap.boot.dvi ${DOC}/monitor.lisp.dvi \
 	 ${DOC}/msg.boot.dvi ${DOC}/msgdb.boot.dvi \
 	 ${DOC}/nag-c02.boot.dvi ${DOC}/nag-c05.boot.dvi \
@@ -755,7 +754,7 @@ ${DEPSYS}:	${DEP} ${OUT}/sys-pkg.${LISP} ${OUT}/nocompil.${LISP} \
 	        ${OUT}/bootlex.${LISP} ${OUT}/newaux.${LISP} \
 	        ${OUT}/preparse.${LISP} \
 	        ${OUT}/postprop.${LISP} ${OUT}/def.${LISP} \
-	        ${OUT}/metameta.${LISP} ${OUT}/fnewmeta.${LISP} \
+	        ${OUT}/fnewmeta.${LISP} \
 	        ${OUT}/g-boot.${LISP} ${OUT}/c-util.${LISP} \
 	        ${OUT}/g-util.${LISP} \
 	        ${OUT}/clam.${LISP} \
@@ -806,10 +805,6 @@ ${DEPSYS}:	${DEP} ${OUT}/sys-pkg.${LISP} ${OUT}/nocompil.${LISP} \
           '(compile-file "${OUT}/def.${LISP}"' \
           ':output-file "${OUT}/def.${O}"))' >> ${OUT}/makedep.lisp
 	@ echo '(load "${OUT}/def")' >> ${OUT}/makedep.lisp
-	@ echo '(unless (probe-file "${OUT}/metameta.${O}")' \
-          '(compile-file "${OUT}/metameta.${LISP}"' \
-          ':output-file "${OUT}/metameta.${O}"))' >> ${OUT}/makedep.lisp
-	@ echo '(load "${OUT}/metameta")' >> ${OUT}/makedep.lisp
 	@ echo '(unless (probe-file "${OUT}/fnewmeta.${O}")' \
           '(compile-file "${OUT}/fnewmeta.${LISP}"' \
           ':output-file "${OUT}/fnewmeta.${O}"))' >> ${OUT}/makedep.lisp
@@ -1603,53 +1598,6 @@ ${DOC}/metalex.lisp.dvi: ${IN}/metalex.lisp.pamphlet
 
 @
 
-\subsection{metameta.lisp \cite{23}}
-<<metameta.o (AUTO from OUT)>>=
-${AUTO}/metameta.${O}: ${OUT}/metameta.${O}
-	@ echo 71 making ${AUTO}/metameta.${O} from ${OUT}/metameta.${O}
-	@ cp ${OUT}/metameta.${O} ${AUTO}
-
-@
-<<metameta.o (OUT from MID)>>=
-${OUT}/metameta.${O}: ${MID}/metameta.lisp 
-	@ echo 72 making ${OUT}/metameta.${O} from ${MID}/metameta.lisp
-	@ ( cd ${MID} ; \
-	  if [ -z "${NOISE}" ] ; then \
-	   echo '(progn  (compile-file "${MID}/metameta.lisp"' \
-            ':output-file "${OUT}/metameta.${O}") (${BYE}))' | ${DEPSYS} ; \
-	  else \
-	   echo '(progn  (compile-file "${MID}/metameta.lisp"' \
-            ':output-file "${OUT}/metameta.${O}") (${BYE}))' | ${DEPSYS} \
-            >${TMP}/trace ; \
-	  fi )
-	  
-@
-<<metameta.lisp (OUT from MID)>>=
-${OUT}/metameta.${LISP}: ${MID}/metameta.lisp
-	@ echo 73 making ${OUT}/metameta.${LISP} from ${MID}/metameta.lisp
-	@ rm -f ${OUT}/metameta.${O}
-	@ cp ${MID}/metameta.lisp ${OUT}/metameta.${LISP}
-
-@
-<<metameta.lisp (MID from IN)>>=
-${MID}/metameta.lisp: ${IN}/metameta.lisp.pamphlet
-	@ echo 74 making ${MID}/metameta.lisp from ${IN}/metameta.lisp.pamphlet
-	@ ( cd ${MID} ; \
-	  ${TANGLE} ${IN}/metameta.lisp.pamphlet >metameta.lisp )
-	  
-@
-<<metameta.lisp.dvi (DOC from IN)>>=
-${DOC}/metameta.lisp.dvi: ${IN}/metameta.lisp.pamphlet 
-	@echo 75 making ${DOC}/metameta.lisp.dvi from ${IN}/metameta.lisp.pamphlet
-	@(cd ${DOC} ; \
-	cp ${IN}/metameta.lisp.pamphlet ${DOC} ; \
-	${DOCUMENT} ${NOISE} metameta.lisp ; \
-	rm -f ${DOC}/metameta.lisp.pamphlet ; \
-	rm -f ${DOC}/metameta.lisp.tex ; \
-	rm -f ${DOC}/metameta.lisp )
-
-@
-
 \subsection{monitor.lisp \cite{24}}
 <<monitor.o (OUT from MID)>>=
 ${OUT}/monitor.${O}: ${MID}/monitor.lisp
@@ -9019,12 +8967,6 @@ clean:
 <<metalex.lisp (MID from IN)>>
 <<metalex.lisp.dvi (DOC from IN)>>
 
-<<metameta.o (AUTO from OUT)>>
-<<metameta.o (OUT from MID)>>
-<<metameta.lisp (OUT from MID)>>
-<<metameta.lisp (MID from IN)>>
-<<metameta.lisp.dvi (DOC from IN)>>
-
 <<modemap.o (AUTO from OUT)>>
 <<modemap.o (OUT from MID)>>
 <<modemap.clisp (MID from IN)>>
@@ -9406,7 +9348,6 @@ pp
 \bibitem{20} {\bf \$SPAD/src/interp/hash.lisp.pamphlet}
 \bibitem{21} {\bf \$SPAD/src/interp/macros.lisp.pamphlet}
 \bibitem{22} {\bf \$SPAD/src/interp/metalex.lisp.pamphlet}
-\bibitem{23} {\bf \$SPAD/src/interp/metameta.lisp.pamphlet}
 \bibitem{24} {\bf \$SPAD/src/interp/monitor.lisp.pamphlet}
 \bibitem{25} {\bf \$SPAD/src/interp/newaux.lisp.pamphlet}
 \bibitem{26} {\bf \$SPAD/src/interp/nlib.lisp.pamphlet}
diff --git a/src/interp/debug.lisp.pamphlet b/src/interp/debug.lisp.pamphlet
index 9a9e613..f1a4e08 100644
--- a/src/interp/debug.lisp.pamphlet
+++ b/src/interp/debug.lisp.pamphlet
@@ -125,7 +125,6 @@ exit (rds ifile)
 (MAKEPROP 'BOOT '/XCAPE '#\_)
 (MAKEPROP 'SPAD '/XCAPE '#\_)
 (MAKEPROP 'META '/READFUN 'META\,RULE)
-(MAKEPROP 'META '/TRAN '/TRANSMETA)
 (MAKEPROP 'INPUT '/READFUN '|New,LEXPR,Interactive|)
 (MAKEPROP 'INPUT '/TRAN '/TRANSPAD)
 (MAKEPROP 'BOOT '/READFUN '|New,LEXPR1|)
@@ -189,13 +188,13 @@ exit (rds ifile)
 	 ISID NBLNK COMMENTCHR $TOKSTACK (/SOURCEFILES |$sourceFiles|)
 	 METAKEYLST DEFINITION_NAME (|$sourceFileTypes| '(|spad| |boot| |lisp| |lsp| |meta|))
 	 ($FUNCTION FN) $BOOT $NEWSPAD $LINESTACK $LINENUMBER STACK STACKX BACK OK
-	 TRAPFLAG |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE
+	 |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE
 	 (*COMP370-APPLY* (if (eq op 'define) #'eval-defun #'compile-defun)))
 	(declare (special ECHOMETA SINGLINEMODE XCAPE XTOKENREADER INPUTSTREAM
 		     SPADERRORSTREAM ISID NBLNK COMMENTCHR $TOKSTACK /SOURCEFILES
 		     METAKEYLST DEFINITION_NAME |$sourceFileTypes|
 		     $FUNCTION $BOOT $NEWSPAD $LINESTACK $LINENUMBER STACK STACKX BACK OK
-		     TRAPFLAG |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE))
+		     |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE))
         (if (PAIRP FN) (SETQ FN (QCAR FN)))
         (SETQ INFILE (OR INFILE (|getFunctionSourceFile| FN)))
 	  ;; $FUNCTION is freely set in getFunctionSourceFile
@@ -297,7 +296,6 @@ exit (rds ifile)
 		 ;(SETQ ERRCOL 0)
 		 ;(SETQ COUNT 0)
 		 ;(SETQ COLUMN 0)
-		 ;(SETQ TRAPFLAG NIL)
 		 (SETQ OK 'T)
 		 ;(NXTTOK)
 		 ;(SETQ LINE (CURINPUTLINE))
diff --git a/src/interp/debugsys.lisp.pamphlet b/src/interp/debugsys.lisp.pamphlet
index 7f4fa95..1674e8f 100644
--- a/src/interp/debugsys.lisp.pamphlet
+++ b/src/interp/debugsys.lisp.pamphlet
@@ -195,7 +195,6 @@ loaded by hand we need to establish a value.
     (thesymb "/int/interp/def.lisp")
     (thesymb "/int/interp/fnewmeta.lisp")
     (thesymb "/int/interp/metalex.lisp")
-    (thesymb "/int/interp/metameta.lisp")
     (thesymb "/int/interp/parsing.lisp")
     (thesymb "/int/interp/parse.clisp")
     (thesymb "/int/interp/postpar.clisp")
diff --git a/src/interp/interp-proclaims.lisp b/src/interp/interp-proclaims.lisp
index 7d9c8ad..016d485 100644
--- a/src/interp/interp-proclaims.lisp
+++ b/src/interp/interp-proclaims.lisp
@@ -699,8 +699,6 @@
             BOOT::|d03faf| BOOT::|d03eef| BOOT::|d03edf|
             BOOT::|htSystemVariables| BOOT::|htSetVars|
             BOOT::|mkSetTitle| BOOT::|npCategory|
-            BOOT::PARSE-CONS_SEXPR BOOT::PARSE-SEXPR
-            BOOT::PARSE-REF_SEXPR BOOT::PARSE-EXPR2 BOOT::PARSE-EXPR1
             BOOT::|htsv| BOOT::|npDefinitionItem| BOOT::|npDefn|
             BOOT::|npMacro| BOOT::|npMDEFinition| BOOT::|npRule|
             BOOT::RESETHASHTABLES BOOT::READSPADEXPR
@@ -731,8 +729,8 @@
             BOOT::|f02axf| BOOT::|f02awf| BOOT::|f02akf| BOOT::|f02ajf|
             BOOT::|f02agf| BOOT::|htShowPageNoScroll| BOOT::|f02aff|
             BOOT::|f02aef| BOOT::|f02adf| BOOT::|f02abf| BOOT::|f02aaf|
-            BOOT::|measure| BOOT::|writeSaturnSuffix| BOOT::NEWRULE
-            BOOT::PARSE-LOCAL_VAR BOOT::|htErrorStar|
+            BOOT::|measure| BOOT::|writeSaturnSuffix| 
+            BOOT::|htErrorStar|
             BOOT::|queryClients| BOOT::|onDisk| BOOT::|endHTPage|
             BOOT::|readSpadProfileIfThere| BOOT::|bcDraw3Dpar1|
             BOOT::|bcDraw3Dpar| BOOT::|htShowPageStarSaturn|
@@ -842,17 +840,16 @@
             BOOT::|npSCategory| BOOT::|npPrimary| BOOT::|npState|
             BOOT::|npDefaultValue| BOOT::|npAssignVariableName|
             BOOT::|npPDefinition| BOOT::|npDollar|
-            BOOT::|npSQualTypelist| BOOT::PARSE-NON_DEST_REF
-            BOOT::PARSE-OPT_EXPR BOOT::PARSE-REPEATOR
-            BOOT::|npCategoryL| BOOT::PARSE-SEXPR_STRING
-            BOOT::|npProduct| BOOT::PARSE-TEST BOOT::|npIterators|
-            BOOT::PARSE-EXPR BOOT::|npWhile|
-            BOOT::|displayPreCompilationErrors| BOOT::PARSE-N_TEST
-            BOOT::|npForIn| BOOT::PARSE-REP_TEST BOOT::|npGives|
-            BOOT::PARSE-FIL_TEST BOOT::|npLogical| BOOT::PARSE-SUBEXPR
-            BOOT::|npExpress| BOOT::PARSE-FID BOOT::PARSE-RULE
-            BOOT::|npExpress1| BOOT::PARSE-HEADER
-            BOOT::|npCommaBackSet| BOOT::PARSE-RULE1 BOOT::|npQualType|
+            BOOT::|npSQualTypelist| 
+            BOOT::|npCategoryL| 
+            BOOT::|npProduct| BOOT::|npIterators|
+            BOOT::|npWhile|
+            BOOT::|displayPreCompilationErrors| 
+            BOOT::|npForIn| BOOT::|npGives|
+            BOOT::|npLogical| 
+            BOOT::|npExpress| 
+            BOOT::|npExpress1| 
+            BOOT::|npCommaBackSet|  BOOT::|npQualType|
             VMLISP:$TOTAL-GC-TIME BOOT::|npADD|
             BOOT::|npConditionalStatement|
             BOOT::|npQualifiedDefinition| BOOT::|npPushId|
@@ -934,10 +931,10 @@
             BOOT::|menuButton| BOOT::|htSaturnBreak| BOOT::|random|
             BOOT::|dbConsExposureMessage| BOOT::|mkSigPredVectors|
             BOOT::FIRST-ERROR BOOT::|writeSaturnPrefix| BOOT::|on|
-            BOOT::|offDisk| BOOT::|htBigSkip| BOOT::PARSE-PROGRAM
-            BOOT::IN-META BOOT::|traceReply| BOOT::|?t|
+            BOOT::|offDisk| BOOT::|htBigSkip| 
+            BOOT::|traceReply| BOOT::|?t|
             BOOT::SKIP-BLANKS BOOT::|pspacers| BOOT::NEXT-LINES-SHOW
-            BOOT::|resetCounters| BOOT::PARSE-DEST_REF
+            BOOT::|resetCounters| 
             BOOT::SPAD_SHORT_ERROR BOOT::|pcounters|
             BOOT::SPAD_LONG_ERROR BOOT::INIT-BOOT/SPAD-READER
             BOOT::NEXT-LINES-CLEAR BOOT::|resetTimers|
@@ -1675,7 +1672,7 @@
             BOOT::DECIMAL-LENGTH BOOT::|unabbrevAndLoad| BOOT::READLISP
             BOOT::|abbQuery| BOOT::SPAD-EVAL BOOT::/TRANSNBOOT
             BOOT::SPAD-MDTR-2 BOOT::SPAD-MDTR-1 BOOT::/TRANSPAD
-            BOOT::|setAutoLoadProperty| BOOT::/TRANSMETA
+            BOOT::|setAutoLoadProperty| 
             BOOT::|getConstructorUnabbreviation| BOOT::|getLisplibName|
             BOOT::OPTIMIZE&PRINT
             BOOT::|getPartialConstructorModemapSig| BOOT::UNCONS
@@ -2550,7 +2547,7 @@
             BOOT:|initializeSetVariables| BOOT::|inclmsgSay|
             BOOT::|inclmsgConStill| BOOT::|incStringStream|
             BOOT::|inclmsgConActive| BOOT:NUMOFNODES FOAM::TYPE2INIT
-            BOOT:TRANSPGVAR FOAM::FOAM-FUNCTION-INFO BOOT::|GetValue|
+            FOAM::FOAM-FUNCTION-INFO BOOT::|GetValue|
             BOOT::|hasToInfo| FOAM::INSERT-TYPES BOOT::|formatPred|
             BOOT::|chaseInferences,foo| BOOT::|liftCond|
             FOAM::FOAMPROGINFOSTRUCT-P BOOT::|formatInfo|
diff --git a/src/interp/metalex.lisp.pamphlet b/src/interp/metalex.lisp.pamphlet
index 00f1b76..5778b44 100644
--- a/src/interp/metalex.lisp.pamphlet
+++ b/src/interp/metalex.lisp.pamphlet
@@ -58,38 +58,6 @@
  
 (in-package "BOOT")
  
-; *** 1. META file handling
- 
-(defun in-meta ()
-  (setq XTokenReader 'get-META-token)
-  (setq Line-Handler 'next-META-line)
-  (setq Meta_Error_Handler 'meta-meta-error-handler)
-  (setq $BOOT nil))
- 
-(defun newrule ()
-  (in-meta)
-  (setq meta_prefix "PARSE-")
-  (test Rule1)
-  (eval (pop-stack-1))
-  (ioclear)
-  (in-boot))
- 
-(defun meta (&optional (*meta-input-file* "/spad/meta.meta")
-                       (*meta-output-file* nil))
-  (ioclear)
-  (in-meta)
-  (with-open-stream
-    (in-stream (open *meta-input-file* :direction :input))
-    (with-open-stream
-      (out-stream (if *meta-output-file*
-               (open *meta-output-file* :direction :output)
-               *terminal-io*))
-      (format out-stream
-	      "~&;;; -*- Mode:Lisp; Package:Boot  -*-~%~%")
-      (parse-program)
-      (IOClear in-stream out-stream)))
-  T)
- 
 ; *** 2. META Line Handling
  
 (defun next-META-line (&optional (in-stream t))
@@ -319,6 +287,26 @@ special character be the atom whose print name is the character itself."
              (incf $num_of_meta_errors)
              (setq Meta_Errors_Occurred t)))
    nil)
+
+; (trace skip-blanks)
+; (trace get-special-token)
+; (trace token-lookahead-type)
+; (trace make-adjustable-string)
+; (trace print-package)
+; (trace get-number-token)
+
+(trace next-META-line)
+(trace kill-comments)
+(trace kill-trailing-blanks)
+(trace get-META-token)
+(trace get-identifier-token)
+(trace get-string-token)
+(trace get-bstring-token)
+(trace make-defun)
+(trace print-fluids)
+(trace set-prefix)
+(trace print-rule)
+(trace meta-meta-error-handler)
 @
 \eject
 \begin{thebibliography}{99}
diff --git a/src/interp/metameta.lisp.pamphlet b/src/interp/metameta.lisp.pamphlet
deleted file mode 100644
index 47070f8..0000000
--- a/src/interp/metameta.lisp.pamphlet
+++ /dev/null
@@ -1,384 +0,0 @@
-\documentclass{article}
-\usepackage{axiom}
-\begin{document}
-\title{\$SPAD/src/interp metameta.lisp}
-\author{Timothy Daly}
-\maketitle
-\begin{abstract}
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-\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.
-
-@
-<<*>>=
-<<license>>
-
-; .META(META PROGRAM)
-; .PREFIX 'PARSE-'
-; .PACKAGE 'PARSING'
-; .DECLARE(METAPGVAR METAVARLST METAKEYLST METARULNAM TRAPFLAG)
- 
-(IN-PACKAGE "BOOT")
- 
-(DEFPARAMETER METAPGVAR NIL)
-(DEFPARAMETER METAVARLST NIL)
-(DEFPARAMETER METAKEYLST NIL)
-(DEFPARAMETER METARULNAM NIL)
-(DEFPARAMETER TRAPFLAG NIL)
- 
-; PROGRAM:<HEADER*>! <RULE*>! ='.FIN' ;
- 
-(DEFUN PARSE-PROGRAM NIL
-  (AND (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-HEADER))))
-       (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-RULE))))
-       (MATCH-STRING ".FIN")))
- 
-; HEADER:       '.META' '(' IDENTIFIER IDENTIFIER <IDENTIFIER>! ')' .(SETQ XNAME ##3)
-; / '.DECLARE' '(' IDENTIFIER* ')' .(PRINT-FLUIDS #1)
-; / '.PREFIX' STRING .(SET-PREFIX #1)
-; / '.PACKAGE' STRING .(PRINT-PACKAGE #1) ;
- 
-(DEFUN PARSE-HEADER NIL
-  (OR (AND (MATCH-ADVANCE-STRING ".META")
-           (MUST (MATCH-ADVANCE-STRING "("))
-           (MUST (PARSE-IDENTIFIER))
-           (MUST (PARSE-IDENTIFIER))
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-IDENTIFIER)))
-           (MUST (MATCH-ADVANCE-STRING ")"))
-           (ACTION (SETQ XNAME (NTH-STACK 3))))
-      (AND (MATCH-ADVANCE-STRING ".DECLARE")
-           (MUST (MATCH-ADVANCE-STRING "("))
-           (MUST (STAR REPEATOR (PARSE-IDENTIFIER)))
-           (MUST (MATCH-ADVANCE-STRING ")"))
-           (ACTION (PRINT-FLUIDS (POP-STACK-1))))
-      (AND (MATCH-ADVANCE-STRING ".PREFIX")
-           (MUST (PARSE-STRING))
-           (ACTION (SET-PREFIX (POP-STACK-1))))
-      (AND (MATCH-ADVANCE-STRING ".PACKAGE")
-           (MUST (PARSE-STRING))
-           (ACTION (PRINT-PACKAGE (POP-STACK-1))))))
- 
-; RULE:     RULE1 ';' .(PRINT-RULE #1) / ^='.FIN' .(META-SYNTAX-ERROR) ;
- 
-(DEFUN PARSE-RULE NIL
-  (OR (AND (PARSE-RULE1)
-           (MUST (MATCH-ADVANCE-STRING ";"))
-           (ACTION (PRINT-RULE (POP-STACK-1))))
-      (AND (NOT (MATCH-STRING ".FIN"))
-           (ACTION (META-SYNTAX-ERROR)))))
- 
-; RULE1: IDENTIFIER .(SETQ METARULNAM (INTERN (STRCONC META_PREFIX ##1)))
-; <'{' FID* '}'>! ':' EXPR =';'
-; < =$METAPGVAR +(PROG =(TRANSPGVAR METAPGVAR) (RETURN #1))
-; .(SETQ METAPGVAR NIL) >
-; +=(MAKE-DEFUN #3 #2 #1) ;
- 
-(DEFUN PARSE-RULE1 NIL
-  (AND (PARSE-IDENTIFIER)
-       (ACTION (SETQ METARULNAM (INTERN (STRCONC |META_PREFIX| (NTH-STACK 1)))))
-       (BANG |FIL_TEST|
-             (OPTIONAL (AND (MATCH-ADVANCE-STRING "{")
-                            (MUST (STAR REPEATOR (PARSE-FID)))
-                            (MUST (MATCH-ADVANCE-STRING "}")))))
-       (MUST (MATCH-ADVANCE-STRING ":"))
-       (MUST (PARSE-EXPR))
-       (MUST (MATCH-STRING ";"))
-       (OPTIONAL (AND METAPGVAR
-                      (PUSH-REDUCTION 'PARSE-RULE1
-                                      (CONS 'PROG
-                                            (CONS (TRANSPGVAR METAPGVAR)
-                                                  (CONS (CONS
-                                                         'RETURN
-                                                         (CONS (POP-STACK-1) NIL))
-                                                        NIL))))
-                      (ACTION (SETQ METAPGVAR NIL))))
-       (PUSH-REDUCTION 'PARSE-RULE1
-                       (MAKE-DEFUN (POP-STACK-3) (POP-STACK-2) (POP-STACK-1)))))
- 
-; FID:  IDENTIFIER +#1 ;
- 
-(DEFUN PARSE-FID NIL
-  (AND (PARSE-IDENTIFIER)
-       (PUSH-REDUCTION 'PARSE-FID (POP-STACK-1))))
- 
-; EXPR:   SUBEXPR
-; <   EXPR1* +(OR #2 -#1)
-; / EXPR2* +(OR #2 -#1) >  ;
- 
-(DEFUN PARSE-EXPR NIL
-  (AND (PARSE-SUBEXPR)
-       (OPTIONAL (OR (AND (STAR REPEATOR (PARSE-EXPR1))
-                          (PUSH-REDUCTION 'PARSE-EXPR
-                                          (CONS 'OR
-                                                (CONS (POP-STACK-2)
-                                                      (APPEND (POP-STACK-1) NIL)))))
-                     (AND (STAR REPEATOR (PARSE-EXPR2))
-                          (PUSH-REDUCTION 'PARSE-EXPR
-                                          (CONS 'OR
-                                                (CONS (POP-STACK-2)
-                                                      (APPEND (POP-STACK-1) NIL)))))))))
- 
-; EXPR1:  '/' <^'/'>  SUBEXPR   ;
- 
-(DEFUN PARSE-EXPR1 NIL
-  (AND (MATCH-ADVANCE-STRING "/")
-       (OPTIONAL (NOT (MATCH-ADVANCE-STRING "/")))
-       (MUST (PARSE-SUBEXPR))))
- 
-; EXPR2:  '\\' <^'\\'>  SUBEXPR  ;
- 
-(DEFUN PARSE-EXPR2 NIL
-  (AND (MATCH-ADVANCE-STRING "\\")
-       (OPTIONAL (NOT (MATCH-ADVANCE-STRING "\\")))
-       (MUST (PARSE-SUBEXPR))))
- 
-; SUBEXPR:FIL_TEST <^?$TRAPFLAG FIL_TEST>*!
-; <FIL_TEST <?$TRAPFLAG +(MUST #1)> >*!
-; +(#3 -#2 -#1) +=(MAKE-PARSE-FUNCTION #1 "AND) ;
- 
-(DEFUN PARSE-SUBEXPR NIL
-  (AND (PARSE-FIL_TEST)
-       (BANG |FIL_TEST|
-             (OPTIONAL (STAR |OPT_EXPR|
-                             (AND (NOT TRAPFLAG)
-                                  (PARSE-FIL_TEST)))))
-       (BANG |FIL_TEST|
-             (OPTIONAL (STAR |OPT_EXPR|
-                             (AND (PARSE-FIL_TEST)
-                                  (OPTIONAL (AND TRAPFLAG
-                                                 (PUSH-REDUCTION 'PARSE-SUBEXPR
-                                                                 (CONS
-                                                                  'MUST
-                                                                  (CONS (POP-STACK-1) NIL))))))
-                             )))
-       (PUSH-REDUCTION 'PARSE-SUBEXPR
-                       (CONS (POP-STACK-3)
-                             (APPEND (POP-STACK-2) (APPEND (POP-STACK-1) NIL))))
-       (PUSH-REDUCTION 'PARSE-SUBEXPR (MAKE-PARSE-FUNCTION (POP-STACK-1) 'AND))))
- 
-; FIL_TEST: REP_TEST <'!' +(BANG FIL_TEST #1)>      ;
- 
-(DEFUN PARSE-FIL_TEST NIL
-  (AND (PARSE-REP_TEST)
-       (OPTIONAL (AND (MATCH-ADVANCE-STRING "!")
-                      (PUSH-REDUCTION 'PARSE-FIL_TEST
-                                      (CONS 'BANG
-                                            (CONS '|FIL_TEST| (CONS (POP-STACK-1) NIL))))))))
- 
-; REP_TEST: N_TEST <REPEATOR>  ;
- 
-(DEFUN PARSE-REP_TEST NIL
-  (AND (PARSE-N_TEST)
-       (OPTIONAL (PARSE-REPEATOR))))
- 
-; N_TEST:   '^' TEST  +(NOT #1) / TEST  ;
- 
-(DEFUN PARSE-N_TEST NIL
-  (OR (AND (MATCH-ADVANCE-STRING "^")
-           (MUST (PARSE-TEST))
-           (PUSH-REDUCTION 'PARSE-N_TEST (CONS 'NOT (CONS (POP-STACK-1) NIL))))
-      (PARSE-TEST)))
- 
-; TEST:     IDENTIFIER (    '{' <SEXPR*>! '}'
-; +(=(INTERN (STRCONC META_PREFIX #2)) -#1)
-; / +(=(INTERN (STRCONC META_PREFIX #1))))        .(SETQ TRAPFLAG T)
-; / STRING  +(MATCH-ADVANCE-STRING #1)            .(SETQ TRAPFLAG T)
-; / '=' REF_SEXPR                                 .(SETQ TRAPFLAG T)
-; / '?' REF_SEXPR                                 .(SETQ TRAPFLAG NIL)
-; / '.' SEXPR         +(ACTION #1)                .(SETQ TRAPFLAG NIL)
-; / '+' CONS_SEXPR    +(PUSH-REDUCTION =(LIST "QUOTE METARULNAM) #1)
-; .(SETQ TRAPFLAG NIL)
-; / '(' EXPR ')'                                  .(SETQ TRAPFLAG T)
-; / '<' EXPR '>'      .(PARSE-OPT_EXPR)           .(SETQ TRAPFLAG NIL) ;
- 
-(DEFUN PARSE-TEST NIL
-  (OR (AND (PARSE-IDENTIFIER)
-           (MUST (OR (AND (MATCH-ADVANCE-STRING "{")
-                          (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-SEXPR))))
-                          (MUST (MATCH-ADVANCE-STRING "}"))
-                          (PUSH-REDUCTION 'PARSE-TEST
-                                          (CONS (INTERN (STRCONC
-                                                         |META_PREFIX|
-                                                         (POP-STACK-2)))
-                                                (APPEND (POP-STACK-1) NIL))))
-                     (PUSH-REDUCTION 'PARSE-TEST
-                                     (CONS (INTERN (STRCONC |META_PREFIX| (POP-STACK-1)))
-                                           NIL))))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (PARSE-STRING)
-           (PUSH-REDUCTION 'PARSE-TEST
-                           (CONS 'MATCH-ADVANCE-STRING (CONS (POP-STACK-1) NIL)))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (MATCH-ADVANCE-STRING "=")
-           (MUST (PARSE-REF_SEXPR))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (MATCH-ADVANCE-STRING "?")
-           (MUST (PARSE-REF_SEXPR))
-           (ACTION (SETQ TRAPFLAG NIL)))
-      (AND (MATCH-ADVANCE-STRING ".")
-           (MUST (PARSE-SEXPR))
-           (PUSH-REDUCTION 'PARSE-TEST (CONS 'ACTION (CONS (POP-STACK-1) NIL)))
-           (ACTION (SETQ TRAPFLAG NIL)))
-      (AND (MATCH-ADVANCE-STRING "+")
-           (MUST (PARSE-CONS_SEXPR))
-           (PUSH-REDUCTION 'PARSE-TEST
-                           (CONS 'PUSH-REDUCTION
-                                 (CONS (LIST 'QUOTE METARULNAM) (CONS (POP-STACK-1) NIL))))
-           (ACTION (SETQ TRAPFLAG NIL)))
-      (AND (MATCH-ADVANCE-STRING "(")
-           (MUST (PARSE-EXPR))
-           (MUST (MATCH-ADVANCE-STRING ")"))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (MATCH-ADVANCE-STRING "<")
-           (MUST (PARSE-EXPR))
-           (MUST (MATCH-ADVANCE-STRING ">"))
-           (ACTION (PARSE-OPT_EXPR))
-           (ACTION (SETQ TRAPFLAG NIL)))))
- 
-; SEXPR:          IDENTIFIER / NUMBER / STRING / NON_DEST_REF / DEST_REF / LOCAL_VAR
-; / '"' SEXPR +(QUOTE #1) / '=' SEXPR / '(' <SEXPR*>! ')' ;
- 
-(DEFUN PARSE-SEXPR NIL
-  (OR (PARSE-IDENTIFIER)
-      (PARSE-NUMBER)
-      (PARSE-STRING)
-      (PARSE-NON_DEST_REF)
-      (PARSE-DEST_REF)
-      (PARSE-LOCAL_VAR)
-      (AND (MATCH-ADVANCE-STRING "\"")
-           (MUST (PARSE-SEXPR))
-           (PUSH-REDUCTION 'PARSE-SEXPR (CONS 'QUOTE (CONS (POP-STACK-1) NIL))))
-      (AND (MATCH-ADVANCE-STRING "=")
-           (MUST (PARSE-SEXPR)))
-      (AND (MATCH-ADVANCE-STRING "(")
-           (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-SEXPR))))
-           (MUST (MATCH-ADVANCE-STRING ")")))))
- 
-; REF_SEXPR: STRING +(MATCH-STRING #1) / SEXPR ;
- 
-(DEFUN PARSE-REF_SEXPR NIL
-  (OR (AND (PARSE-STRING)
-           (PUSH-REDUCTION 'PARSE-REF_SEXPR (CONS 'MATCH-STRING (CONS (POP-STACK-1) NIL))))
-      (PARSE-SEXPR)))
- 
-; CONS_SEXPR: IDENTIFIER <^=(MEMBER ##1 METAPGVAR) +(QUOTE #1)>
-; / LOCAL_VAR +(QUOTE #1)
-; / '(' <SEXPR_STRING>! ')'
-; / SEXPR ;
- 
-(DEFUN PARSE-CONS_SEXPR NIL
-  (OR (AND (PARSE-IDENTIFIER)
-           (OPTIONAL (AND (NOT (MEMBER (NTH-STACK 1) METAPGVAR))
-                          (PUSH-REDUCTION 'PARSE-CONS_SEXPR
-                                          (CONS 'QUOTE (CONS (POP-STACK-1) NIL))))))
-      (AND (PARSE-LOCAL_VAR)
-           (PUSH-REDUCTION 'PARSE-CONS_SEXPR (CONS 'QUOTE (CONS (POP-STACK-1) NIL))))
-      (AND (MATCH-ADVANCE-STRING "(")
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-SEXPR_STRING)))
-           (MUST (MATCH-ADVANCE-STRING ")")))
-      (PARSE-SEXPR)))
- 
-; SEXPR_STRING: CONS_SEXPR <SEXPR_STRING>!    +(CONS #2 #1)
-; / '-' CONS_SEXPR <SEXPR_STRING>! +(APPEND #2 #1)      ;
- 
-(DEFUN PARSE-SEXPR_STRING NIL
-  (OR (AND (PARSE-CONS_SEXPR)
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-SEXPR_STRING)))
-           (PUSH-REDUCTION 'PARSE-SEXPR_STRING
-                           (CONS 'CONS (CONS (POP-STACK-2) (CONS (POP-STACK-1) NIL)))))
-      (AND (MATCH-ADVANCE-STRING "-")
-           (MUST (PARSE-CONS_SEXPR))
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-SEXPR_STRING)))
-           (PUSH-REDUCTION 'PARSE-SEXPR_STRING
-                           (CONS 'APPEND (CONS (POP-STACK-2) (CONS (POP-STACK-1) NIL)))))))
- 
-; NON_DEST_REF: '##' NUMBER +(NTH-STACK #1) ;
- 
-(DEFUN PARSE-NON_DEST_REF NIL
-  (AND (MATCH-ADVANCE-STRING "##")
-       (MUST (PARSE-NUMBER))
-       (PUSH-REDUCTION 'PARSE-NON_DEST_REF (CONS 'NTH-STACK (CONS (POP-STACK-1) NIL)))))
- 
-; DEST_REF:     '#' NUMBER +=(LIST (INTERN (STRCONC 'POP-STACK-' (STRINGIMAGE #1)))) ;
- 
-(DEFUN PARSE-DEST_REF NIL
-  (AND (MATCH-ADVANCE-STRING "#")
-       (MUST (PARSE-NUMBER))
-       (PUSH-REDUCTION 'PARSE-DEST_REF
-                       (LIST (INTERN (STRCONC "POP-STACK-" (STRINGIMAGE (POP-STACK-1))))))))
- 
-; LOCAL_VAR:    '$' (   IDENTIFIER / NUMBER +=(GETGENSYM #1) .(PUSH ##1 METAPGVAR)) ;
- 
-(DEFUN PARSE-LOCAL_VAR NIL
-  (AND (MATCH-ADVANCE-STRING "$")
-       (MUST (OR (PARSE-IDENTIFIER)
-                 (AND (PARSE-NUMBER)
-                      (PUSH-REDUCTION 'PARSE-LOCAL_VAR (GETGENSYM (POP-STACK-1)))
-                      (ACTION (PUSH (NTH-STACK 1) METAPGVAR)))))))
- 
-; OPT_EXPR:     <'*' +(STAR OPT_EXPR #1) / REPEATOR> +(OPTIONAL #1) ;
- 
-(DEFUN PARSE-OPT_EXPR NIL
-  (AND (OPTIONAL (OR (AND (MATCH-ADVANCE-STRING "*")
-                          (PUSH-REDUCTION 'PARSE-OPT_EXPR
-                                          (CONS 'STAR
-                                                (CONS '|OPT_EXPR|
-                                                      (CONS (POP-STACK-1) NIL)))))
-                     (PARSE-REPEATOR)))
-       (PUSH-REDUCTION 'PARSE-OPT_EXPR (CONS 'OPTIONAL (CONS (POP-STACK-1) NIL)))))
- 
-; REPEATOR:     ('*' / BSTRING +(AND (MATCH-ADVANCE-STRING #1) (MUST ##1)))
-; +(STAR REPEATOR #1) ;
- 
-(DEFUN PARSE-REPEATOR NIL
-  (AND (OR (MATCH-ADVANCE-STRING "*")
-           (AND (PARSE-BSTRING)
-                (PUSH-REDUCTION 'PARSE-REPEATOR
-                                (CONS 'AND
-                                      (CONS (CONS 'MATCH-ADVANCE-STRING
-                                                  (CONS (POP-STACK-1) NIL))
-                                            (CONS (CONS 'MUST (CONS (NTH-STACK 1) NIL))
-                                                  NIL))))))
-       (PUSH-REDUCTION 'PARSE-REPEATOR
-                       (CONS 'STAR (CONS 'REPEATOR (CONS (POP-STACK-1) NIL))))))
- 
-; .FIN ;
-@
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} nothing
-\end{thebibliography}
-\end{document}
diff --git a/src/interp/parsing.lisp.pamphlet b/src/interp/parsing.lisp.pamphlet
index cce7470..8dbb420 100644
--- a/src/interp/parsing.lisp.pamphlet
+++ b/src/interp/parsing.lisp.pamphlet
@@ -53,10 +53,6 @@
 ;          in META/LISP, R.D. Jenks, Tech Report, IBM T.J. Watson Research Center,
 ;          1969.  Familiarity with this document is assumed.
 ;
-;          The parser generator itself is described in either the file
-;          MetaBoot.lisp (hand-coded version) or the file MetaMeta.lisp (machine
-;          generated from self-descriptive Meta code), both of which load themselves
-;          into package Parsing.
 
 ; CONTENTS:
 ;
@@ -85,8 +81,6 @@
 ;       5. Routines for inspecting and resetting total I/O system state
 ;
 ;       METALEX.LISP:  Meta file handling, auxiliary parsing actions and tokenizing
-;       METAMETA.LISP: Meta parsing
-;
 ;       BOOTLEX.LISP:  Boot file handling, auxiliary parsing actions and tokenizing
 ;       NEWMETA.LISP:  Boot parsing
 
@@ -875,8 +869,6 @@ Symbolics read-line returns embedded newlines in a c-m-Y.")
 
 (defparameter /genvarlst nil    "??")
 
-(defun transpgvar (metapgvar) (remove-duplicates metapgvar))
-
 (defparameter /gensymlist nil   "List of rule local variables generated by getgensym.")
 
 (defun getgensym (n)
diff --git a/src/interp/spad.lisp.pamphlet b/src/interp/spad.lisp.pamphlet
index c39b435..cfc828f 100644
--- a/src/interp/spad.lisp.pamphlet
+++ b/src/interp/spad.lisp.pamphlet
@@ -169,15 +169,6 @@
 
 (DEFUN /TRANSNBOOT (X) (S-PROCESS X) NIL)
 
-(DEFUN /TRANSMETA (X)
-  (PROG (KEYNAM ROOTFN U)
-	(SETQ ROOTFN (/MFINDROOT (CAR /SOURCEFILES)))
-	(SETQ $LASTPREFIX (GET ROOTFN 'METAPFX))
-	(SETQ KEYNAM (INTERNL $LASTPREFIX (PNAME ROOTFN) "KEY"))
-	(SET KEYNAM (REMDUP (APPEND METAKEYLST (EVAL KEYNAM))))
-	(SETQ U (GETRULEFUNLISTS ROOTFN (LIST X)))
-	(SUBLISNQ (PAIR (CADR U) (CAR U)) X)))
-
  ;; NIL needed below since END\_UNIT is not generated by current parser
 (defun |isTokenDelimiter| () (MEMBER (CURRENT-SYMBOL) '(\) END\_UNIT NIL)))
 
@@ -486,7 +477,7 @@ special.
     (let (ZZ str N RLGENSYMFG RLGENSYMLST |NewFLAG| XCAPE *PROMPT*
 	  SINGLELINEMODE OK ISID NBLNK COUNT CHR ULCASEFG ($LINESTACK 'BEGIN_UNIT)
 	  $NEWLINSTACK $TOKSTACK COMMENTCHR TOK LINE BACK INPUTSTREAM XTRANS
-	  XTOKENREADER STACK STACKX TRAPFLAG)
+	  XTOKENREADER STACK STACKX)
       (SETQ XTRANS '|boot-New|
 	    XTOKENREADER 'NewSYSTOK
 	    SYNTAX_ERROR 'SPAD_SYNTAX_ERROR)
@@ -563,7 +554,7 @@ special.
 	  (NewFLAG T) (XTRANS '|boot-New|) (XCAPE '!)
 	  (COMMENTCHR 'NOTHING)	 (XTOKENREADER 'NewSYSTOK)
 	  ($NBOOT T) (ERRCOL 0) (COUNT 0) (COLUMN 0)
-	  (TRAPFLAG NIL) (OK T)	 (SPADERRORSTREAM CUROUTSTREAM)
+	  (OK T) (SPADERRORSTREAM CUROUTSTREAM)
 	  ($LINESTACK 'BEGIN_UNIT)
 	  (INPUTSTREAM LINESET)
 	  (CHR 'ENDOFLINECHR))
diff --git a/src/interp/sys-pkg.lisp.pamphlet b/src/interp/sys-pkg.lisp.pamphlet
index 850237d..eaa76b7 100644
--- a/src/interp/sys-pkg.lisp.pamphlet
+++ b/src/interp/sys-pkg.lisp.pamphlet
@@ -174,7 +174,7 @@ provides support for compiler code.
 	 BOOT::$FILELINENUMBER BOOT::|$timerTicksPerSecond|
 	 BOOT::|bootUnionPrint| BOOT::|$consistencyCheck|
 	 BOOT::|$oldTime| BOOT::$NEWSPAD BOOT::NUMOFNODES
-	 BOOT::|$ResMode| BOOT::S* BOOT::TRANSPGVAR BOOT::$BOXSTRING
+	 BOOT::|$ResMode| BOOT::S*  BOOT::$BOXSTRING
 	 BOOT::|$BasicPredicates| BOOT::|$eltIfNil| BOOT::$FUNNAME_TAIL
 	 BOOT::|$QuickCode| BOOT::GENVAR BOOT::|$TypeEqui|
 	 BOOT::TOKEN-TYPE BOOT::|updateSourceFiles| BOOT::|$BFtag|

\start
Date: Fri, 10 Aug 2007 22:51:32 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: Successful build-improvements compilation

On 10 Aug 2007 11:05:33 -0500, Gabriel Dos Reis wrote:
>
>   Issue tracked down and fixed.  Patch installed at revision 704.
>

Thanks! It works now. :-)

\start
Date: Fri, 10 Aug 2007 22:28:00 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: Successful build-improvements compilation

On Fri, 10 Aug 2007, Bill Page wrote:

| On 10 Aug 2007 11:05:33 -0500, Gabriel Dos Reis wrote:
| >
| >   Issue tracked down and fixed.  Patch installed at revision 704.
| >
| 
| Thanks! It works now. :-)

\start
Date: Fri, 10 Aug 2007 23:34:13 -0400
From: Bill Page
To: list
Subject: Statistik Wiki implementation of Axiom interface
Cc: Markus Cozowicz

Markus Cozowicz has implemented a MediaWiki interface for Axiom. This
allows Axiom to be used on MediaWiki (the same wiki software as used
by Wikipedia) just like we use it now on the Axiom Wiki.

I just had a chance to get back to this and take a closer look. I
think it is great!

Please see:

  http://www.eisber.net/StatWiki/index.php/Axiom

  http://www.mediawiki.org/wiki/Extension:Axiom

There might be some very good reasons to consider using MediaWiki
instead of the MathAcion extension of ZWiki although I am certainly
not advocating this right now. But I would be very happy to help if
other Axiom developers or users are interested in setting up such a
system for Axiom use.

Your comments would be very much appreciated.

Regards,
Bill Page

--------------

From: Markus Cozowicz
To: Bill Page
CC: <list>, Martin Rubey
Date: May 27 2007 - 7:21pm

Hi,

I'm filtering the commands you provided to improve security. I don't
perform chroot and still use the apache user (too much work).
I improved the Latex a little.

For installation or linking please use
http://www.mediawiki.org/wiki/Extension:Axiom .

I tested http://wiki.axiom-developer.org/VeryLongLaTeX and all of them
work.
I'm not really sure how to do formula line breaking - is there a latex
option I could insert at the beginning?

If you want to provide any Latex tests please edit
http://www.eisber.net/StatWiki/index.php/Axiom - it would be nice if you
register, so I know you added it.

I'll try graphics right now.

Thx Markus

-----Original Message-----
From: Bill Page [mailto:Bill Page]
Sent: Sonntag, 27. Mai 2007 20:42
To: Markus Cozowicz
Cc: list
Subject: RE: Axiom on MediaWiki (was: Axiom)

Markus,

Thank you very much for this initial work! I think it is very
promising.

On May 27, 2007 12:19 PM Markus Cozowicz wrote:
>
> I found some time on the weekend to work on it.
>
> Have a look at http://www.eisber.net/StatWiki/index.php/Temp
>
> I'm actually reusing <math>-tag from MediaWiki, which has
> limited Latex support. Thus I have to do some conversions and
> stripping. I don't think full support of all Latex outputted
> by Axiom is possible, but to get a reasonable amount, I'd have
> to go through some more samples.
>
> Some questions:
>
> - Do you have list of functions that impose security problems?

There are at least two classes of operations that potentially
pose security threats when running Axiom pubicly online. One
is the

)system ...

command which permits the user to open access to all system
commands. The 2nd entry point is via Lisp which can be
invoked either as a commands such as

)lisp

and

)fin

of via a function call like this

(SI_:_:SYSTEM "...")$Lisp

Both of these leave the system wide open. Unfortunately both
of them also have potentially quite valid uses. I think it
fair to say that the developers of Axiom have given almost
no thought at all to the need for security since the standard
model is to have Axiom running only locally on you desktop.

If you are concerned about security (I don't it take for
granted that you necessarily need to be, given our experience
over the last three years at axiom-developer.org), then I
would highly recommend that first of all you should run Axiom
in a chroot environment.

> - Do you have testcases for Latex output?
>

No, I am sorry that we do not have such official test cases.
I would be glad to develop these with you.

We have however documented some problem cases on the Axiom
Wiki. E.g.

http://wiki.axiom-developer.org/VeryLongLaTeX

> I saw that you support graphics too with postscript output.

Axiom can generate graphics with postscript output if it
is run in an X-windows environment. This is possible even
on a headless server by installing the virtual framebuffer
driver Xfbdev and the xvfb-run, although I have had some
trouble interacting with this configuration via a pipe. I
think to do this successfully requires pty support and
something like pexpect.

Right now we do cannot automatically generate graphics for
inclusion in the Axiom Wiki.

See some sparse notes here:

http://wiki.axiom-developer.org/SummerOfCode
http://wiki.axiom-developer.org/GraphicsOnMathAction

> The R-plugin for media wiki already does postscript to png
> conversion for R graphics...
> It shouldn't be too hard to adapt that for Axiom.
>

Great!

Regards,
Bill Page.

>
> -----Original Message-----
> From: Bill Page [mailto:Bill Page]
> Sent: Dienstag, 10. April 2007 03:08
> To: Markus Cozowicz
> Cc: 'Axiom-Developer'
> Subject: Axiom on MediaWiki (was: Axiom)
>
> Markus,
>
> I hope you do not mind that I am copying this to the Axiom
> developer mailing list. I think there may be some other
> people here who are interested in this subject.
>
> On April 9, 2007 6:43 PM Markus Cozowicz wrote:
>
> > I'm actually trying to integrate Axiom into MediaWiki. I'm
> > using it to write my statistics homework (www.eisber.net/StatWiki).
>
> Well, I thinks that's a pretty ambitious project just to do
> your homework! :-) But I think this is interesting for much
> more than that.
>
> > MediaWiki is written in PHP.
>
> Yes. Very famous. It is the wiki software behind Wikipedia.
> I think it is a very good choice (except for PHP, but that's
> a different story).
>
> > I'm not sure if I actually want to properly interface with
> > Axiom, as I'm only interested in the generated latex, that
> > needs to be piped into texvc (yet another binary - the latex
> > interface used in MediaWiki).
>
> I don't know what you mean exactly by "properly interface with
> Axiom". Axiom can generate LaTeX output for the results that it
> calculates. I assume that if you are interested in Axiom, you
> are also interested in symbolic computer algebra in some form
> or other - otherwise I don't see much point in using Axiom just
> to generate LaTeX output. I think you would find it rather
> awkward if that was all you wanted it to do.
>
> I suppose that you are familiar with the Axiom Wiki web site:
> http://wiki.axiom-developer.org
> If you are using Axiom for statistics - even if it is just for
> a course - then you are certainly welcome to use this web site
> (which is publically available) or it's sister portal site:
> http://portal.axiom-developer.org
> where you can log-in and control who gets access to the pages
> you prepare. We are always interested in more examples of
> applications where Axiom can be used. Your exercises might
> help other people realize how Axiom can be used in their
> own situation.
>
> As you can discover from the wiki site, these web sites are
> based on Zwiki, Zope and Python - quite different from most
> PHP applications although they accomplish mostly the same
> thing in the end.
>
> If you are more interested in continuing the development of
> a general purpose MediaWiki plug-in that allows MediaWiki to
> send commands to Axiom and display the results on a wiki page
> in nicely LaTeX typeset form, then as an Axiom developer I am
> very interested in that. I would very much like to be able to
> offer such an interface for Axiom to other MediaWiki users.
> So I would be glad to help you with this.
>
> > Can I disabled shell execution in Axiom? Because for security
> > reason, I probably don't want anybody to execute arbitrary
> > code on my server.
>
> Axiom is not designed with this kind of security in mind, but
> in the PHP interface to Axiom, it would be possible to intercept
> commands which might execute arbitrary code and still leave a
> significant subset of Axiom available to the user. If malicous
> code is a serious risk, I think the best option would be to run
> Axiom in a chroot environment or perhaps on a separate virtual
> machine using Xen or other VM tool.

\start
Date: Fri, 10 Aug 2007 20:55:37 -0700
From: Ed Borasky
To: list
Subject: Re: bootstrap Meta/Boot

Gabriel Dos Reis wrote:
> Tim Daly writes:
> 
> [...]
> 
> | Writing Boot to generate Lisp is like writing Fortran to generate Aldor.
> | If you are a Fortran programmer you won't see why that's a problem.
> | If you are an Aldor programmer you can't imagine why that isn't a problem.
> | 
> | But you can't make Fortran programmers into Aldor programmers.

I guess I need to learn Aldor then just to prove a Fortran programmer
can make himself into an Aldor programmer. :)

But seriously, folks ... I was using Fortran as a scripting language in
the days when there *weren't* scripting languages. There were virtual
machines written in Fortran, AI programs written in Fortran, accounting
and finance applications written in Fortran, maybe even operating
systems written in Fortran. And just about every major large-scale
scientific application code written in Fortran implements a
domain-specific language -- in Fortran, of course.

If you want to have fun sometime, dig up Chuck Moore's papers on how he
created Forth. It was a merging of Burroughs Algol, Fortran and IBM 1130
machine language. About the only programming languages that *aren't*
descendants of Fortran are Lisp, COBOL and APL.

\start
Date: Fri, 10 Aug 2007 21:08:58 -0700
From: Ed Borasky
To: list
Subject: Re: Lisp in Small Pieces

Bill Page wrote:
> On 8/10/07, C Y wrote:
>> Not at $4 any more. I didn't notice it in time.  Arrrgh.
>>
> 
> :-) I think I got the last one. When I went to amazon.ca it said: 1
> new copy for $3.99 and about 10 used copies for about $70. I was
> afraid the my order would be cancelled by the time I got to check-out
> but in the end I got a confirmation email that said I would be
> receiving my book for $3.99 + about $6 for shipping, not bad for 900+
> page book I thought. Now we will see if it actually shows up in a few
> days.
> 
> Regards,
> Bill Page.

Amazon USA had some at something like $51 US. I got one. It's great --
well worth $51!

\start
Date: 10 Aug 2007 23:51:03 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: 20070810.01.tpd.patch

Tim Daly writes:

| This patch removes src/interp/metameta.lisp.pamphlet which is
| no longer used. 

This should go to silver.

\start
Date: Sat, 11 Aug 2007 13:55:04 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: Successful build-improvements compilation

Hello Gaby,

I think that did it also here.

I've not done a complete new build but just "svk update" and
"configure && make && make install". Then hyperdoc pops up.

Thank you.

Ralf

old> ! char	*HypertexProgram        = "$AXIOM/bin/hypertex -s";
new> ! char	*HypertexProgram        = "$AXIOM/lib/hypertex -s";

\start
Date: 11 Aug 2007 07:50:12 -0500
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: Successful build-improvements compilation

Ralf Hemmecke writes:

| Hello Gaby,
| 
| I think that did it also here.
| 
| I've not done a complete new build but just "svk update" and
| "configure && make && make install". Then hyperdoc pops up.
| 
| Thank you.


\start
Date: Sat, 11 Aug 2007 16:55:12 +0200
From: Gregory Vanuxem
To: Tim Daly
Subject: Re: 20070810.01.tpd.patch

Hello Tim,

Le vendredi 10 ao=FBt 2007 =E0 20:45 -0500, Tim Daly a
=E9crit :

[...]

> --- a/src/interp/metalex.lisp.pamphlet
> +++ b/src/interp/metalex.lisp.pamphlet

[...]

> @@ -319,6 +287,26 @@ special character be the atom whose print name is =
the character itself."
>               (incf $num_of_meta_errors)
>               (setq Meta_Errors_Occurred t)))
>     nil)
> +
> +; (trace skip-blanks)
> +; (trace get-special-token)
> +; (trace token-lookahead-type)
> +; (trace make-adjustable-string)
> +; (trace print-package)
> +; (trace get-number-token)
> +
> +(trace next-META-line)
> +(trace kill-comments)
> +(trace kill-trailing-blanks)
> +(trace get-META-token)
> +(trace get-identifier-token)
> +(trace get-string-token)
> +(trace get-bstring-token)
> +(trace make-defun)
> +(trace print-fluids)
> +(trace set-prefix)
> +(trace print-rule)
> +(trace meta-meta-error-handler)

Is this intentional ? And why ?

\start
Date: Sat, 11 Aug 2007 10:04:39 -0500
From: Tim Daly
To: Arthur Ralfs, James Davenport, Mike Dewar
Subject: 20070811.01.tpd.patch

*,

Arthur Ralfs has written a new MathML output mode for Axiom.
This has been added to the system. To see the MathML output
you type:

 )set output mathml on

If you only want MathML output and not the algebra output then
add the additional command:

 )set output algebra off

Documentation is available in a fully built system by typing:

xdvi $AXIOM/doc/src/algebra/mathml.spad.dvi

A set of test cases are available in a fully built system at:

xdvi $AXIOM/doc/src/input/mathml.input.dvi

\start
Date: Sat, 11 Aug 2007 11:05:03 -0400
From: Bill Page
To: Ed Borasky
Subject: Re: bootstrap Meta/Boot

On 8/10/07, Ed Borasky wrote:
> Gabriel Dos Reis wrote:
> > Tim Daly writes:
> >
> > [...]
> >
> > | Writing Boot to generate Lisp is like writing Fortran to generate Aldor.
> > | If you are a Fortran programmer you won't see why that's a problem.
> > | If you are an Aldor programmer you can't imagine why that isn't a problem.
> > |
> > | But you can't make Fortran programmers into Aldor programmers.
>
> ...
> If you want to have fun sometime, dig up Chuck Moore's papers on how he
> created Forth. It was a merging of Burroughs Algol, Fortran and IBM 1130
> machine language. About the only programming languages that *aren't*
> descendants of Fortran are Lisp, COBOL and APL.
>

The first Lisp I ever used was written in Fortran and ran on a PDP 11. :-)

\start
Date: Sat, 11 Aug 2007 10:17:52 -0500
From: Tim Daly
To: Gregory Vanuxem
Subject: 20070810.01.tpd.patch bug

No, the traces should not be there.
Part of my testing machinery escaped.
I'll fix that shortly.

\start
Date: Sat, 11 Aug 2007 10:31:13 -0500
From: Tim Daly
To: list
Subject: 20070811.02.tpd.patch

The following patch removes the trace commands from the file
src/interp/metalex.lisp.pamphlet.

It assumes the following patches:
20070721.01.tpd.patch
20070721.02.tpd.patch
20070722.01.tpd.patch
20070810.01.tpd.patch
20070811.01.tpd.patch

====================================================================
diff --git a/changelog b/changelog
index e3d84c9..6b8cd6f 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070811 gxv src/interp/metalex.lisp remove trace commands
 20070811 tpd src/input/Makefile add mathml.input
 20070811 tpd src/input/mathml.input write test cases
 20070810 tpd readme add Arthur C. Ralfs
diff --git a/src/interp/metalex.lisp.pamphlet b/src/interp/metalex.lisp.pamphlet
index 5778b44..bd491f9 100644
--- a/src/interp/metalex.lisp.pamphlet
+++ b/src/interp/metalex.lisp.pamphlet
@@ -288,25 +288,6 @@ special character be the atom whose print name is the character itself."
              (setq Meta_Errors_Occurred t)))
    nil)
 
-; (trace skip-blanks)
-; (trace get-special-token)
-; (trace token-lookahead-type)
-; (trace make-adjustable-string)
-; (trace print-package)
-; (trace get-number-token)
-
-(trace next-META-line)
-(trace kill-comments)
-(trace kill-trailing-blanks)
-(trace get-META-token)
-(trace get-identifier-token)
-(trace get-string-token)
-(trace get-bstring-token)
-(trace make-defun)
-(trace print-fluids)
-(trace set-prefix)
-(trace print-rule)
-(trace meta-meta-error-handler)
 @
 \eject
 \begin{thebibliography}{99}

\start
Date: Sat, 11 Aug 2007 08:39:29 -0700
From: Ed Borasky
To: list
Subject: Re: bootstrap Meta/Boot

Bill Page wrote:
> The first Lisp I ever used was written in Fortran and ran on a PDP 11. :-)
The assembly language of the original PDP 11 (before all the ugly
extensions, etc., got tacked onto it) was so simple, logical, rational
and elegant that I can't imagine a Lisp interpreter for it written in
anything other than assembler. The only architecture I've ever seen that
even came close IMHO was the Texas Instruments 9900.

But the *real* Lispniks of the day used PDP 6/10 "mainframes" -- how
were those implemented?

\start
Date: 11 Aug 2007 11:29:16 -0500
From: Gabriel Dos Reis
To: list
Subject: ChangeLog on Silver

  I have some changes to Silver down in pipeline (some of them were
brought here and discussed on the list).  However, before doing that,
I would like to establish as a policy that we use -- from now on --
the `standard' ChangeLog format to record history of changes.  This
means we enter entries like this:

   2007-06-30  Gabriel Dos Reis  Gabriel Dos Reis

           * vmlisp.lisp.pamphlet (MACRO-MISSINGARGS): Fix thinko.


If you're using Emacs for editing, Emacs can help you if you're in the
file you're editing (or the body of the function you're changing) and
hit the sequence

      C-x 4 a.


Unlike GCC, GDB, Axiom.build-improvements, and some other projects, I
suggest we use only one ChangeLog file, to keep the spirit of the
current practice.

I'll be implementing that on Silver shortly.

\start
Date: 11 Aug 2007 11:32:57 -0500
From: Gabriel Dos Reis
To: list
Subject: GCL-2.6.8pre and type punning

  Building GCL-2.6.8pre included in Axiom elicites lots of warnings
of the style:

gcc -c -Wall -DVOL=volatile -fsigned-char -pipe -O3 -fomit-frame-pointer  -I/home/gdr/src/axiom/trunk/lsp/gcl-2.6.8pre/o -I../h -I../gcl-tk hash.c 
hash.d: In function 'hash_eql':
hash.d:72: warning: dereferencing type-punned pointer will break strict-aliasing rules
hash.d:75: warning: dereferencing type-punned pointer will break strict-aliasing rules

[....]

gcl_arraylib.c: In function 'init_gcl_arraylib':
gcl_arraylib.c:4: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c: In function 'LI1':
gcl_arraylib.c:23: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:36: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:44: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:50: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:70: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:72: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:78: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c: In function 'LI3':
gcl_arraylib.c:239: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:254: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c: In function 'LI6':
gcl_arraylib.c:352: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c:352: warning: dereferencing type-punned pointer will break strict-aliasing rules
gcl_arraylib.c: In function 'LI8':
gcl_arraylib.c:417: warning: dereferencing type-punned pointer will break strict-aliasing rules


This is with the system compiler from SUSE Linux 10.2:

gdr@gauss:~> gcc -v
Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.1.2 --enable-ssp --disable-libssp --disable-libgcj --with-slibdir=/lib64 --with-system-zlib --enable-shared --enable-__cxa_atexit --enable-libstdcxx-allocator=new --program-suffix=-4.1 --enable-version-specific-runtime-libs --without-system-libunwind --with-cpu=generic --host=x86_64-suse-linux
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)

\start
Date: Sat, 11 Aug 2007 11:36:53 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: ChangeLog on Silver

We already have a standard changelog format.
It's been "standard" since August 20, 2003, approximately 4 years.
See the file changelog.

\start
Date: Sat, 11 Aug 2007 11:38:02 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

On Sat, 11 Aug 2007, Tim Daly wrote:

| Gaby,
| 
| We already have a standard changelog format.

No, we don't.  
We have Tim-ChangeLog format.  That isn't a standard changelog format. 

\start
Date: Sat, 11 Aug 2007 12:42:04 -0400
From: Bill Page
To: Ed Borasky
Subject: Re: bootstrap Meta/Boot

On 8/11/07, Ed Borasky Ed Borasky wrote:
> Bill Page wrote:
> > The first Lisp I ever used was written in Fortran and ran on a PDP 11. :-)
> The assembly language of the original PDP 11 (before all the ugly
> extensions, etc., got tacked onto it) was so simple, logical, rational
> and elegant that I can't imagine a Lisp interpreter for it written in
> anything other than assembler. The only architecture I've ever seen that
> even came close IMHO was the Texas Instruments 9900.
>
> But the *real* Lispniks of the day used PDP 6/10 "mainframes" -- how
> were those implemented?
>

You can find (almost) anything on the Web, so I took a quick look to
see if I could locate the version of Lisp written in Fortran that I
compiled and installed on a PDP 11 so many years ago. As I recall it
came from a PDP 11 contributed library. (No one actually wanted to
*buy* a licensed copy of Lisp, even then :). I didn't find what I was
looking for but just to prove that what I said has some credibility
let me quote:

Twisted Documentation: Lisp in Python

Chris Meyers

http://www.ibiblio.org/obp/py4fun/lisp/lisp.html

"So when I came across "Lisp in Lisp" taking up most of page 13 of the
Lisp 1.5 Users Manual I had a stronger motivation than just esthetics
to do something with it. I figured that if I could translate just that
much Lisp into Fortran, then I would have the means to run other Lisp
programs. It was much easier said than done. Fortran did not support
recursion and this was an example of true "functional programming".
There was not a single GOTO or variable assignment. Each function call
and return had to done in Fortran with computed GOTO's, first pushing
or popping information on stacks implemented with Fortran arrays. It
was very messy. Later I did a version in PDP-11 Assembler and, still
later, one in Pascal which was pretty clean."

http://www.springerlink.com/content/g653169260k53444/

acques Cohen1 and Carl Zuckerman1
(1) 	Brandeis University, 02154 Waltham, Massachusetts, USA

Received: 7 March 1972  Revised: 10 May 1972
Abstract  This paper describes the implementation of a pedagogical
version of Evalquote with a set of Fortran subroutines. Their study
enables the user to understand the programming machinery needed to
interpret Lisp programs; the implementation of the subroutines allows
him to run pure Lisp in machines for which only Fortran is available.
The approach used in this paper is to define a stack-machine capable
of executing a sequence of pseudo-instructions which represent a Lisp
program in post-fixed notation. These instructions are easily
simulated by Fortran subroutines. Once the subroutines are implemented
in a computer it is a simple matter to manually transcribe Evalquote
into a sequence of these pseudo-instructions and thus obtain a Lisp
interpreter with a minimum of programming effort. The paper does not
attempt to describe a complete and efficient Lisp interpreter;
instead, it concentrates on the description of a minimal set of
pseudo-instructions and their actions.

\start
Date: Sat, 11 Aug 2007 09:45:20 -0700
From: Ed Borasky
To: list
Subject: Re: ChangeLog on Silver

Gabriel Dos Reis wrote:
> Hi,
> 
>   I have some changes to Silver down in pipeline (some of them were
> brought here and discussed on the list).  However, before doing that,
> I would like to establish as a policy that we use -- from now on --
> the `standard' ChangeLog format to record history of changes.  This
> means we enter entries like this:
> 
>    2007-06-30  Gabriel Dos Reis  Gabriel Dos Reis
> 
>            * vmlisp.lisp.pamphlet (MACRO-MISSINGARGS): Fix thinko.
> 
> 
> If you're using Emacs for editing, Emacs can help you if you're in the
> file you're editing (or the body of the function you're changing) and
> hit the sequence
> 
>       C-x 4 a.
> 
> 
> Unlike GCC, GDB, Axiom.build-improvements, and some other projects, I
> suggest we use only one ChangeLog file, to keep the spirit of the
> current practice.
> 
> I'll be implementing that on Silver shortly.

Excellent timing, actually ... I've been meaning to pulse Gentoo Linux
(again) about getting Axiom Silver into Portage. They are still
distributing Axiom by building it on your machine from the September
2005 tarball, not even from the "Gold" repository! I've had excellent
luck on my Gentoo systems, both x86 and amd64, with both Silver and
Gold. If it got into Portage, that would immediately get it tested on
PPC and Sparc boxes too, and maybe some of the less known architectures.

What's the most recent Axiom that will build and execute on Windows, by
the way? Although a lot of folks deprecate Cygwin ("deprecate" is a mild
word -- usually I hear a term that *rhymes* with "deprecate" :)) I think
a Cygwin Axiom would be better than a native port, since Hyperdoc would
be there, as would (IIRC) the TeXmacs interface.

\start
Date: 11 Aug 2007 11:53:59 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

Tim, look at 

        http://www.gnu.org/prep/standards/html_node/Change-Logs.html

No need to invent anything here.  

Plus, existing editors already assist in the matter.

\start
Date: 11 Aug 2007 12:01:03 -0500
From: Gabriel Dos Reis
To: Ed Borasky
Subject: Re: ChangeLog on Silver

Ed Borasky writes:

[...]

| What's the most recent Axiom that will build and execute on Windows, by
| the way?

I don't know how to to do build of recent Axiom.silver on Windows.
There are many options: 

   * Bill maintains a branch of Axiom with changes only for windows.
     As far as I know it isn't up to date

   * Axiom.build-improvements builds on Windows, all platforms
     supported by Axiom.silver, and many more.

   * Axiom.wh-sandbox, based on Axiom.build-improvements, support
     similar number of achitectures and have more fixes.


I'm trying to get initial bits of Axiom.build-improvements to
Axiom.silver.  Those bits will be incremental -- I'm afraid.


| Although a lot of folks deprecate Cygwin ("deprecate" is a mild
| word -- usually I hear a term that *rhymes* with "deprecate" :)) I think
| a Cygwin Axiom would be better than a native port, since Hyperdoc would
| be there, as would (IIRC) the TeXmacs interface.

Different people have different opinions on the matter.  

I have been doing native builds of Axiom on Windows and I'm happy with
it.  Last time I tried, Axiom build on Cygwin won't succeed because of
GCL issues.

\start
Date: Sat, 11 Aug 2007 09:59:51 -0700
From: Ed Borasky
To: list
Subject: Re: bootstrap Meta/Boot

Bill Page wrote:
> You can find (almost) anything on the Web 

[snip]

Yes you can ... so, under the heading of "Nostalgia Ain't What It Used
To Be",

http://www.cs.ru.nl/~freek/aut/

\start
Date: 11 Aug 2007 12:10:35 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: B-MDEF

Gabriel Dos Reis writes:

| Tim --
| 
|   The SBCL compiler does not like the definition of B-MDEF in def.lisp:
| 
| (defun B-MDEF (FORM SIGNATURE $BODY)
|   (declare (ignore SIGNATURE))
|   (let* ($OpAssoc
| 	 ($op (first form))
| 	 (argl (cdr form))
| 	 (GARGL (MAPCAR '(LAMBDA (X) (GENSYM)) ARGL))
| 	 ($BODY (SUBLISLIS GARGL ARGL (|bootTransform| (DEFTRAN $BODY))))
| 	 ($BODY (LIST 'SUBLISLIS (CONS 'LIST GARGL) 
| 		      (LIST 'QUOTE GARGL) (LIST 'QUOTE $BODY))))
|     (COMP (SUBLIS $OPASSOC
| 		  (LIST (LIST $OP (LIST 'MLAMBDA (CONS () GARGL) $BODY)))))))
| 
| Saying that:
| 
| ; file: /home/gdr/build/bi/src/interp/def.lisp
| ; in: DEFUN B-MDEF
| ;     (MAPCAR '(LAMBDA (BOOT::X) (GENSYM)) BOOT::ARGL)
| ; --> LET SB-INT:DO-ANONYMOUS BLOCK LET TAGBODY TAGBODY RPLACD LET PROGN SETF 
| ; --> SB-KERNEL:%RPLACD SETQ THE LIST CONS 
| ; ==>
| ;   (FUNCALL #:G70 (CAR #:G69))
| ; 
| ; caught WARNING:
| ;   Asserted type (OR FUNCTION SYMBOL) conflicts with derived type
| ;   (VALUES CONS &OPTIONAL).
| ;   See also:
| ;     The SBCL Manual, Node "Handling of Types"
| 
| 
| Indeed, in 
|         
|         (GARGL (MAPCAR '(LAMBDA (X) (GENSYM)) ARGL))
| 
| we really want to say
| 
|         (GARGL (MAPCAR #'(LAMBDA (X) (GENSYM)) ARGL))
|                        ^
|                      was missing

Fixed with the patch below.
Applied to Axiom.silver.

-- Gaby

2007-08-11  Gabriel Dos Reis  Gabriel Dos Reis

	* src/interp/def.lisp.pamphlet (B-MDEF): Fix typo.

  
  20070716 tpd src/doc/axiom.bib move developernotes to bookvol4
*** src/interp/def.lisp.pamphlet	(revision 22516)
--- src/interp/def.lisp.pamphlet	(local)
*************** foo defined inside of fum gets renamed a
*** 129,135 ****
    (declare (ignore SIGNATURE))
   (let* ($OpAssoc
          ($op (first form)) (argl (cdr form))
!         (GARGL (MAPCAR '(LAMBDA (X) (GENSYM)) ARGL))
          ($BODY (SUBLISLIS GARGL ARGL (|bootTransform| (DEFTRAN $BODY))))
          ($BODY (LIST 'SUBLISLIS (CONS 'LIST GARGL) (LIST 'QUOTE GARGL)
                       (LIST 'QUOTE $BODY))))
--- 129,135 ----
    (declare (ignore SIGNATURE))
   (let* ($OpAssoc
          ($op (first form)) (argl (cdr form))
!         (GARGL (MAPCAR #'(LAMBDA (X) (GENSYM)) ARGL))
          ($BODY (SUBLISLIS GARGL ARGL (|bootTransform| (DEFTRAN $BODY))))
          ($BODY (LIST 'SUBLISLIS (CONS 'LIST GARGL) (LIST 'QUOTE GARGL)
                       (LIST 'QUOTE $BODY))))


\start
Date: Sat, 11 Aug 2007 12:17:33 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: ChangeLog on Silver

So you felt that the project standard should be overruled for
a standard you found elsewhere. Then you ignored my objection
and made the change to trunk. Is that correct?

\start
Date: Sat, 11 Aug 2007 12:23:14 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

On Sat, 11 Aug 2007, Tim Daly wrote:

| So you felt that the project standard should be overruled for
| a standard you found elsewhere.

It is not a standard I found elsewhere.  It is a widely used standard,
adopted by the free software community.  We have no need to invent anything
here. 

There is no place for NIH.

| Then you ignored my objection and made the change to trunk.

I did not ignore it.  On the contrary, I addressed it. 

\start
Date: Sat, 11 Aug 2007 12:29:53 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: ChangeLog on Silver

So you feel that Martin's democracy rules are nonsense
and that your opinion is now the rule of law?

\start
Date: Sat, 11 Aug 2007 12:31:07 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

On Sat, 11 Aug 2007, Tim Daly wrote:

| So you feel that Martin's democracy rules are nonsense
| and that your opinion is now the rule of law?

That has nothing to do with this.  

As for the rules Martin proposed, I already expressed my difference and
posted amendments/suggestions.

\start
Date: 11 Aug 2007 12:41:02 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: getrulefunlists

Gabriel Dos Reis writes:

| Tim --
| 
|   Yet one more.  Consider the routine GETFUNLISTS from
| src/interp/parsing.lisp:
| 
| 
| (defun getrulefunlists  (rootfun rs)
|   (let* ((metapfx (or (get rootfun 'metapfx) ""))
|          (mainfun (internl metapfx (pname rootfun)))
|          (mainfunstr (pname mainfun))
|          (flnam (internl mainfunstr "FUN"))
|          (pfx-funlist (union (cons mainfun
|                                    (if (atom (eval flnam))
| 				       nil 
| 				     (eval flnam)))
|                              (mapcar #'(lambda (x) (internl metapfx (pname x)))
|                                      (assocleft rs))))
|          n unpfx-funlist)
|     (set flnam pfx-funlist)
|     (if (not (lessp (setq n (length metapfx)) 0))
|         (setq unpfx-funlist
|               (mapcar #'(lambda (x) 
| 			  (intern (subseq (copy-symbol (pname x)) n)))
| 		      pfx-funlist)))
|     (if unpfx-funlist (list pfx-funlist unpfx-funlist))))
| 
| 
| The type checker of the SBCL compiler does not like it, saying:
| 
| ; file: /home/gdr/build/bi/src/interp/parsing.lisp
| ; in: DEFUN GETRULEFUNLISTS
| ;     (INTERN (SUBSEQ (COPY-SYMBOL (VMLISP:PNAME BOOT::X)) BOOT::N))
| ; 
| ; note: deleting unreachable code
| ; 
| ; caught WARNING:
| ;   Asserted type STRING conflicts with derived type (VALUES LIST &OPTIONAL).
| ;   See also:
| ;     The SBCL Manual, Node "Handling of Types"
| 
| 
| Indeed, if you look again at the incriminated form:
| 
| 	(intern (subseq (copy-symbol (pname x)) n))
| 
| it does not make sense to me how it could possibly work -- using Common Lisp
| semantics.  Indeed, copy-symbol will return a symbol and a symbol is not 
| a sequence.  I suspect what you want to pass to SUBSEQ if actually the
| SYMBOL-NAME of the new symbol.

Fixed with this.
Installed on Axiom.silver.

-- Gaby

2007-08-11  Gabriel Dos Reis  Gabriel Dos Reis
  
	* src/interp/parsing.lisp.pamphlet (getrulefunlists): Extract the
	name of the new symbol before calling subseq.

*** src/interp/parsing.lisp.pamphlet	(revision 21589)
--- src/interp/parsing.lisp.pamphlet	(local)
*************** Symbolics read-line returns embedded new
*** 908,914 ****
      (set flnam pfx-funlist)
      (if (not (lessp (setq n (length metapfx)) 0))
          (setq unpfx-funlist
!               (mapcar #'(lambda (x) (intern (subseq (copy-symbol (pname x)) n)))
                         pfx-funlist)))
      (if unpfx-funlist (list pfx-funlist unpfx-funlist))))
  
--- 908,914 ----
      (set flnam pfx-funlist)
      (if (not (lessp (setq n (length metapfx)) 0))
          (setq unpfx-funlist
!               (mapcar #'(lambda (x) (intern (subseq (symbol-name (copy-symbol (pname x))) n)))
                         pfx-funlist)))
      (if unpfx-funlist (list pfx-funlist unpfx-funlist))))
  

\start
Date: 11 Aug 2007 13:41:36 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: getrulefunlists

Gabriel Dos Reis writes:
> *** src/interp/parsing.lisp.pamphlet	(revision 21589)
> --- src/interp/parsing.lisp.pamphlet	(local)
> *************** Symbolics read-line returns embedded new
> *** 908,914 ****
>       (set flnam pfx-funlist)
>       (if (not (lessp (setq n (length metapfx)) 0))
>           (setq unpfx-funlist
> !               (mapcar #'(lambda (x) (intern (subseq (copy-symbol (pname x)) n)))
>                          pfx-funlist)))
>       (if unpfx-funlist (list pfx-funlist unpfx-funlist))))
>   
> --- 908,914 ----
>       (set flnam pfx-funlist)
>       (if (not (lessp (setq n (length metapfx)) 0))
>           (setq unpfx-funlist
> !               (mapcar #'(lambda (x) (intern (subseq (symbol-name (copy-symbol (pname x))) n)))
>                          pfx-funlist)))
>       (if unpfx-funlist (list pfx-funlist unpfx-funlist))))

I dont understand this change.

In vmlisp.lisp:  

  (defun pname (x)
      (cond ((symbolp x) (symbol-name x))
        ((characterp x) (string x))
        (t nil)))


Thus (subseq (pname x) n)  should be sufficient.  Quite a lot of
redundant code in the above.

\start
Date: Sat, 11 Aug 2007 12:46:25 -0500
From: Tim Daly
To: Gabriel Dos Reis
Subject: ChangeLog on Silver

The Axiom project is not the GNU project. 
It is not the Debian project, which has different standards.
We have our own standards.

> That has nothing to do with this.

So you declare, so it is...
In fact, it has everything to do with this. 
You simply ignored me.

> As for the rules Martin proposed, I already expressed my difference and
> posted amendments/suggestions.

So now this is "Gaby's Project"?

\start
Date: Sat, 11 Aug 2007 12:47:17 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: getrulefunlists

On Sat, 11 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > *** src/interp/parsing.lisp.pamphlet	(revision 21589)
| > --- src/interp/parsing.lisp.pamphlet	(local)
| > *************** Symbolics read-line returns embedded new
| > *** 908,914 ****
| >       (set flnam pfx-funlist)
| >       (if (not (lessp (setq n (length metapfx)) 0))
| >           (setq unpfx-funlist
| > !               (mapcar #'(lambda (x) (intern (subseq (copy-symbol (pname x)) n)))
| >                          pfx-funlist)))
| >       (if unpfx-funlist (list pfx-funlist unpfx-funlist))))
| >   
| > --- 908,914 ----
| >       (set flnam pfx-funlist)
| >       (if (not (lessp (setq n (length metapfx)) 0))
| >           (setq unpfx-funlist
| > !               (mapcar #'(lambda (x) (intern (subseq (symbol-name (copy-symbol (pname x))) n)))
| >                          pfx-funlist)))
| >       (if unpfx-funlist (list pfx-funlist unpfx-funlist))))
| 
| I dont understand this change.

I expalined the problem earlier:

   copy-symbol returns a symbol, not a string that could be considered
   as a sequence, and not a character that we could use PNAME to turn
   into symbol.  Juts a symbol.  


All I fixed is an obvious type error.  Whether the function is more 
computationally expensive than it needs to be is a separate matter.

Now that it is type correct, you can rewrite the whole function reducing
reduncies :-)

\start
Date: Sat, 11 Aug 2007 12:48:02 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

On Sat, 11 Aug 2007, Tim Daly wrote:

| So now this is "Gaby's Project"?

I'm not going to follow you there.

\start
Date: Sat, 11 Aug 2007 12:50:07 -0500 (CDT)
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

On Sat, 11 Aug 2007, Tim Daly wrote:

| You simply ignored me.

As you say "So you declare, so it is..."

No, I did not ignore you.  I carefully considered your reply and
properly addressed it.

\start
Date: Sat, 11 Aug 2007 14:03:07 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: re: ChangeLog on Silver

On 8/11/07, Gabriel Dos Reis wrote:
> On Sat, 11 Aug 2007, Tim Daly wrote:
>
> | You simply ignored me.
>
> As you say "So you declare, so it is..."
>
> No, I did not ignore you.  I carefully considered your reply and
> properly addressed it.
>

Gaby,

FWIW, you've got my "vote":

+1

It seems that this is the only way the Axiom project can progress. I
hope you will be able to proceed with changes to the build system.

\start
Date: Sat, 11 Aug 2007 13:05:27 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: re: ChangeLog on Silver

Bill --
  
  Thanks for your encouragement.

On Sat, 11 Aug 2007, Bill Page wrote:


| It seems that this is the only way the Axiom project can progress. I
| hope you will be able to proceed with changes to the build system.

with enough consensus.

I hope too be able to get a non-controversial initial bit in by this
week-end -- but hey, week-end is all I get with my family...

\start
Date: 11 Aug 2007 13:40:31 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: $traceflag

Gabriel Dos Reis writes:

| Tim --
| 
|   I believe the use of  $TRACEFLAG in the routine S-PROCESS (spad.lisp)
| is a typo for |$TraceFlag|.

Fixed with this.
Applied to Axiom.silver.

-- Gaby

2007-08-11  Gabriel Dos Reis  Gabriel Dos Reis

	* src/interp/spad.lisp.pamphlet (S-PROCESS): Fix typo.

*** src/interp/spad.lisp.pamphlet	(revision 21590)
--- src/interp/spad.lisp.pamphlet	(local)
***************
*** 422,428 ****
  	(|$LocalFrame| '((NIL))))
    (prog ((CURSTRM CUROUTSTREAM) |$s| |$x| |$m| u)
       (declare (special CURSTRM |$s| |$x| |$m| CUROUTSTREAM))
!       (SETQ $TRACEFLAG T)
        (if (NOT X) (RETURN NIL))
        (setq X (if $BOOT (DEF-RENAME (|new2OldLisp| X))
  		  (|parseTransform| (|postTransform| X))))
--- 422,428 ----
  	(|$LocalFrame| '((NIL))))
    (prog ((CURSTRM CUROUTSTREAM) |$s| |$x| |$m| u)
       (declare (special CURSTRM |$s| |$x| |$m| CUROUTSTREAM))
!       (SETQ |$TraceFlag| T)
        (if (NOT X) (RETURN NIL))
        (setq X (if $BOOT (DEF-RENAME (|new2OldLisp| X))
  		  (|parseTransform| (|postTransform| X))))


\start
Date: Sat, 11 Aug 2007 20:37:03 +0200
From: Juergen Weiss
To: Bill Page, Gabriel Dos Reis
Subject: re: ChangeLog on Silver

We should go with the standards used by other projects and supported in
standard tools (as emacs etc). This helps all developers. There should =
be
a real good reason to deviate from `best practices=B4. And I do not see
any reason not to use the changelog format supported by standard
editors. So I vote for the change.

> -----Original Message-----
>
> On 8/11/07, Gabriel Dos Reis wrote:
> > On Sat, 11 Aug 2007, Tim Daly wrote:
> >
> > | You simply ignored me.
> >
> > As you say "So you declare, so it is..."
> >
> > No, I did not ignore you.  I carefully considered your reply and
> > properly addressed it.
> >
>
> Gaby,
>
> FWIW, you've got my "vote":
>
> +1
>
> It seems that this is the only way the Axiom project can progress. I
> hope you will be able to proceed with changes to the build system.

\start
Date: Sat, 11 Aug 2007 20:55:38 +0200 (CEST)
From: Franz Lehner
To: Ralf Hemmecke
Subject: Re: aldor stream oddities

> Now, in Axiom we should have a problem with saying that S is an additive 
> group.
That's true. All axioms are satisfied, except uniqueness of inverses 
and the neutral element. What should it be? A FuzzyAbelianGroup?
> (4) -> zero?(t-t)
>    (4)  false
>            Type: Boolean
>
> I don't.
Although zero? doesn't report it, t-t will always behave like the 0 
element. So in fact -t is the inverse of t for all practical purposes.
But I don't expect Axiom to prove equality where it is impossible to have 
a proof, just spit out a message like "true up to order n" and then prove 
equality myself.
> The category Ring is reserved for structures with complete equality testing.
Is this the plan for Axiom too?
What will happen to ExpressionField? I recall there are undecidable 
problems in the latter as well.

Here is a proposal (in SPAD) for a recursive stream generator which looks 
at all previous elements, not just the last one. It could probably be done with 
the existing generate(S->S,S), but this one looks more natural.

====================================================================
     Exports == with

       generate: (List S->S,S) -> Stream S
       ++ \spad{generate(f:List S->S,x)} generates an infinite stream
       ++ whose first element is x and whose nth element (\spad{n > 1})
       ++ is f applied to the list of all previous elements.
       ++ Note: \spad{generate(f,x) = [x,f([x]),f([x,f([x])]),..]

     Implementation == add

       lstgen:(List S->S,List S) -> Stream S

       lstgen(f:(List S) -> S,ls:List S):Stream S ==
             delay(ss:=f(ls); concat(ss, lstgen(f,concat(ls, ss))))

       generate(f:(List S)->S,s:S):Stream S == concat(s,lstgen(f,[s]))
====================================================================

again I only could test it as a package due to the bootstrap problem in 
the spoon.

\start
Date: Sat, 11 Aug 2007 14:21:39 -0500 (CDT)
From: Gabriel Dos Reis
To: Martin Rubey
Subject: re: ChangeLog on Silver

Martin --

  Did you get my amendments/suggestions to your proposed model?

Bill --

  I sent an email to mathaction (which I'm subscribed to) but I'm
not seeing anything out...

\start
Date: 11 Aug 2007 17:52:14 -0500
From: Gabriel Dos Reis
To: list
Subject: A curious algebra failure

  This issue pops up while looking at a type error in
src/interp/c-util.boot. 

  1.  The type error

     Consider the function pmatch() from c-util.boot

         pmatch(s,p) == pmatchWithSl(s,p,"ok")

     That function is essentially called by the compiler to check
     whether an expression e in mode m is coercible to mode m', as
     can be seen from coerceable() defined in compile.boot

       coerceable(m,m',e) ==
	 m=m' => m
	 -- must find any free parameters in m
	 sl:= pmatch(m',m) => SUBLIS(sl,m')
	 coerce(["$fromCoerceable$",m,e],m') => m'
	 nil

      Basically, the expression e of mode m is coercible to mode m' if
         (a) m and m' are identical -- the identity conversion;
   
         (b) m and m' can be unified by instantiating variables in m
              -- instantiatiion conversion, the case handled by pmatch;

         (c) or by attempting the actual conversion and see what
              happens -- the "speculative" call to coerce();
         
         (d) and that is all.
        


       So far, so good.

       Now, let's look at the definition of pmatchWithSl() in c-util.boot:

	   pmatchWithSl(s,p,al) ==
	     s=$EmptyMode => nil
	     s=p => al
	     v:= ASSOC(p,al) => s=rest v or al
	     MEMQ(p,$PatternVariableList) => [[p,:s],:al]
	     null atom p and null atom s and_
		     (al':= pmatchWithSl(first s,first p,al)) and
	       pmatchWithSl(rest s,rest p,al')

       Essentially, pmatchWithSl() computes a substitution that would
       make the pattern p match the value s.  It uses a simply minded
       unification algorithm, and is probably not efficient but that
       is not of concern here.

       A simple type inference shows that the third argument to
       pmatchWithSl() must be an association list.  Therefore, the 
       current definition of pmatch() is ill-formed.


   2.  The correct definition of pmatch

       Now that we have established that the existing definition of
       pmatch is incorrect, what should a correct definition look
       like?  Well, the whole thing pmatch() computes is a `minimal'
       substitution that makes p match s.  So, it should start with
       the identity substituation (or null substitution) and updates
       it as it goes through the unification process.  So the correct
       definition is:

         pmatch(s,p) == pmatchWithSl(s,p,[nil])

       where [nil] stands for the identity substitution.


   3.  The problem in Algebra bootstrap

       After correction of pmatch(), I started a fresh build with
       maximum safety turn on.  Everything proceeded well till
       compilation of MONAD.spad where I see a failure with the
       following message:

------------------------------------------------------------------------
   initializing NRLIB MONAD- for Monad& 
   compiling into NRLIB MONAD- 
   importing RepeatedSquaring S
   compiling exported ** : (S,PositiveInteger) -> S
****** comp fails at level 1 with expression: ******
error in function ** 

(S)
****** level 1  ******
$x:= S
$m:= (Join (SetCategory) (CATEGORY domain (SIGNATURE * ($ $ $))))
$f:=
((((|n| # #) (|x| # #) (* # # #) (** # # #) ...)))
 
   >> Apparent user error:
   Cannot coerce S 
      of mode (Monad) 
      to mode (Join (SetCategory) (CATEGORY domain (SIGNATURE * ($ $ $)))) 




        Looking at the definition of MONAD, reproduced below, I see no
        reason to expect that the call to expt(x,n) should work. What
        am I missing?


Thanks,

-- Gaby

)abbrev category MONAD Monad
++ Authors: J. Grabmeier, R. Wisbauer
++ Date Created: 01 March 1991
++ Date Last Updated: 11 June 1991
++ Basic Operations: *, **
++ Related Constructors: SemiGroup, Monoid, MonadWithUnit
++ Also See:
++ AMS Classifications:
++ Keywords: Monad,  binary operation
++ Reference:
++  N. Jacobson: Structure and Representations of Jordan Algebras
++  AMS, Providence, 1968
++ Description:
++  Monad is the class of all multiplicative monads, i.e. sets
++  with a binary operation.
Monad(): Category == SetCategory with
    --operations
      "*": (%,%) -> %
        ++ a*b is the product of \spad{a} and b in a set with
        ++ a binary operation.
      rightPower: (%,PositiveInteger) -> %
        ++ rightPower(a,n) returns the \spad{n}-th right power of \spad{a},
        ++ i.e. \spad{rightPower(a,n) := rightPower(a,n-1) * a} and
        ++ \spad{rightPower(a,1) := a}.
      leftPower: (%,PositiveInteger) -> %
        ++ leftPower(a,n) returns the \spad{n}-th left power of \spad{a},
        ++ i.e. \spad{leftPower(a,n) := a * leftPower(a,n-1)} and
        ++ \spad{leftPower(a,1) := a}.
      "**": (%,PositiveInteger) -> %
        ++ a**n returns the \spad{n}-th power of \spad{a},
        ++ defined by repeated squaring.
    add
      import RepeatedSquaring(%)
      x:% ** n:PositiveInteger == expt(x,n)
      rightPower(a,n) ==
--        one? n => a
        (n = 1) => a
        res := a
        for i in 1..(n-1) repeat res := res * a
        res
      leftPower(a,n) ==
--        one? n => a
        (n = 1) => a
        res := a
        for i in 1..(n-1) repeat res := a * res
        res

\start
Date: Sat, 11 Aug 2007 18:25:56 -0500
From: Tim Daly
To: Martin Rubey
Subject: ChangeLog on Silver

> I felt quite bad when I saw Gaby's post announcing the ChangeLog format
> change and a little while later Tim's reply:

Right. So the sequence went:
Gaby's post, my objection, Gaby's change to trunk, Gaby's reply

So there really was no voting, no attempt at democracy, 
no effort your part to enforce the "democracy" you so
badly wanted. Just silence.

> Meanwhile I feel much better. There has been a vote.

Right. After the fact. You're happy that you didn't have to 
step in and enforce your new "democracy" because the vote came
down in your favor.

Nice job. Love the way you're running the project.
Keep up the sham.

What a waste of time.

\start
Date: 11 Aug 2007 18:35:51 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

Tim Daly writes:

| Martin,
| 
| > I felt quite bad when I saw Gaby's post announcing the ChangeLog format
| > change and a little while later Tim's reply:
| 
| Right. So the sequence went:
| Gaby's post, my objection, Gaby's change to trunk, Gaby's reply
                            ^

You're missing Gaby's replies.

\start
Date: Sat, 11 Aug 2007 19:53:10 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

From: Stephen Wilson
Date: 11 Aug 2007 19:52:56 -0400
--text follows this line--
Gabriel Dos Reis writes:
> 	   pmatchWithSl(s,p,al) ==
> 	     s=$EmptyMode => nil
> 	     s=p => al
> 	     v:= ASSOC(p,al) => s=rest v or al
> 	     MEMQ(p,$PatternVariableList) => [[p,:s],:al]
> 	     null atom p and null atom s and_
> 		     (al':= pmatchWithSl(first s,first p,al)) and
> 	       pmatchWithSl(rest s,rest p,al')

This function does not appear consistent.

   v:= ASSOC(p,al) => s=rest v or al

This line can have the function return true instead of an alist,
potentially spoiling the recursive calls and the subsequent binding to
al'.  Possibly (not totally sure) it should read:
        
   v:= ASSOC(p,al) and s=rest v => al

Simply redefining pname and )co MONAD.spad as you suggested does not
reveal the algebra failure you reported.  Is this occurring only upon
a complete rebuild for you?

\start
Date: Sat, 11 Aug 2007 19:04:34 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: A curious algebra failure

On Sat, 11 Aug 2007, Stephen Wilson wrote:

| From: Stephen Wilson
| Date: 11 Aug 2007 19:52:56 -0400
| In-Reply-To: <87odhd65wh.fsf@soliton.cs.tamu.edu>
| Message-ID: <87d4xtr5lz.fsf@lattice.localdomain>
| Lines: 26
| User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.4
| MIME-Version: 1.0
| Content-Type: text/plain; charset=us-ascii
| --text follows this line--
| Gabriel Dos Reis writes:
| > 	   pmatchWithSl(s,p,al) ==
| > 	     s=$EmptyMode => nil
| > 	     s=p => al
| > 	     v:= ASSOC(p,al) => s=rest v or al
| > 	     MEMQ(p,$PatternVariableList) => [[p,:s],:al]
| > 	     null atom p and null atom s and_
| > 		     (al':= pmatchWithSl(first s,first p,al)) and
| > 	       pmatchWithSl(rest s,rest p,al')
| 
| This function does not appear consistent.
| 
|    v:= ASSOC(p,al) => s=rest v or al

Good spot -- that escapted me.  

Let me try your suggestion and report later -- due to my set of safety to 3,
the build takes some time... 

| 
| This line can have the function return true instead of an alist,
| potentially spoiling the recursive calls and the subsequent binding to
| al'.  Possibly (not totally sure) it should read:
|         
|    v:= ASSOC(p,al) and s=rest v => al
| 
| Simply redefining pname and )co MONAD.spad as you suggested does not
| reveal the algebra failure you reported.  Is this occurring only upon
| a complete rebuild for you?

Yes, on complete build -- I would commit only if complete build is OK.

\start
Date: Sat, 11 Aug 2007 19:09:30 -0500
From: Tim Daly
To: Martin Rubey
Subject: ChangeLog on Silver

Martin,

And since you're so into "standards" I'm unaware of a GNU
(or any other project) run as a democracy. 

My anger will be dismissed as the complaints of "the one who lost"
but that will certainly miss the point. The format of the changelog
file is not a problem, the method of handling the voting is.

You've threatened and complained, shouted and screamed about how this
should be a democracy. I gave it considerable thought and had many
off-list discussions about the whole democracy idea. Now I see that it
is complete nonsense. Gaby decides, Gaby changes.  And yet, according
to your rules, there is supposed to be time for people to express
their opinion. I can't measure the time between the message post and
the change but it is not sufficient for objection or voting.  It seems
to me that it is up to you to enforce such rules. Yet you don't.

I'm angry because I wasted days of people's time off-list in discussion
of what is a reasonable response to your demands. The general consensus
was that if I don't give it a try then this will be viewed at "Tim's
Project". My counter-argument that every other project seems to have
a lead developer seemed like I was being stubborn, "sticking to
convention" (e.g. standards), and being "inflexible". 

Now, after wasting all of this time, I find you're doing nothing at
all to even attempt democracy. 

You want the authority but you don't live up to the responsibility.

\start
Date: 11 Aug 2007 19:41:20 -0500
From: Gabriel Dos Reis
To: Tim Daly
Subject: Re: ChangeLog on Silver

If you read my suggestions/amendments to Martin's proposal, you'll
see I suggested:

   * a set of reviewers who review other people's patch.
     Review works by sufficient consensus, not necessarily a voting
     system. 

     (+) A subset of those reviewers are "global" maintainers.

     The set of reviewers should be open so that we integrate new
     reviewers as they have developed enough knowledge of the system.

    
     The set of reviewers usually consists of component maintainers.
     Global maintainers would try to defer to component maintainers.

   * A release manager.  The release manager is NOT a benevolent
     dictator.  Rather, it is someone committed to making releases
     happen on regular basis.  The release manager ideally is also 
     a global mantainer, although that is not necessary.  He set up
     schedules and try to get people's act to make things happen.


   * A College (or Steering Committee) whose job is to make sure that
     the project is not over taken by an individual.  I truly believe
     we need that.  I've spoken to and received emails from some
     original Axiom developers who also promote the College view.

     The College's job is not to make technical decisions.  The
     College will be discussing and making decisions about political
     issues.  Any developer can at any time request the College to
     consider any matter of his/her importance.
     The College appoints maintainers and release managers.

     The College should not consist only of developers.  Users should
     be represented.  In general, people with either long term
     committement or interest in Axiom should be represented there.

     I suggested to keep the number of College members small.  I
     suggested 7 for concreteness.

\start
Date: 11 Aug 2007 19:47:48 -0500
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: A curious algebra failure

Gabriel Dos Reis writes:

| On Sat, 11 Aug 2007, Stephen Wilson wrote:
| 
| | From: Stephen Wilson
| | Date: 11 Aug 2007 19:52:56 -0400
| | In-Reply-To: <87odhd65wh.fsf@soliton.cs.tamu.edu>
| | Message-ID: <87d4xtr5lz.fsf@lattice.localdomain>
| | Lines: 26
| | User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.4
| | MIME-Version: 1.0
| | Content-Type: text/plain; charset=us-ascii
| | --text follows this line--
| | Gabriel Dos Reis writes:
| | > 	   pmatchWithSl(s,p,al) ==
| | > 	     s=$EmptyMode => nil
| | > 	     s=p => al
| | > 	     v:= ASSOC(p,al) => s=rest v or al
| | > 	     MEMQ(p,$PatternVariableList) => [[p,:s],:al]
| | > 	     null atom p and null atom s and_
| | > 		     (al':= pmatchWithSl(first s,first p,al)) and
| | > 	       pmatchWithSl(rest s,rest p,al')
| | 
| | This function does not appear consistent.
| | 
| |    v:= ASSOC(p,al) => s=rest v or al
| 
| Good spot -- that escapted me.  
| 
| Let me try your suggestion and report later -- due to my set of safety to 3,
| the build takes some time... 

Your suggestion is correct, but the build still fails at the same
point.  Looking at the call to expt(x,n) in the Spad code  I don't
immediatelt see why it should be well-formed.  Do you see why it is
OK? 

\start
Date: 11 Aug 2007 20:54:17 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

Gabriel Dos Reis writes:
> Your suggestion is correct, but the build still fails at the same
> point.  Looking at the call to expt(x,n) in the Spad code  I don't
> immediatelt see why it should be well-formed.  Do you see why it is
> OK? 

Given:

   "**": (%,PositiveInteger) -> %

and

   x:% ** n:PositiveInteger == expt(x,n)

we need  

   expt: (%, PositiveInteger) -> %

But that is exactly what we get as export when saying:

    `import RepeatedSquaring(%)'

Here, % certainly satisfies the conditions on the parameter type:

   SetCategory with "*": (%,%)->%


Myself, I do not see how this could not be well-formed.  What do you
see wrong with the expression?

\start
Date: Sat, 11 Aug 2007 19:56:12 -0500 (CDT)
From: Gabriel Dos Reis
To: list
Subject: common-lisp and GCL-2.6.8pre *features*

   Using GCL-2.6.8pre (CVS) included in Axiom distribution, I'm seeing
a curious interaction between *features* and  :common-lisp.  
Below is a session to reproduce the problem:

gdr@gauss:~> gcl
GCL (GNU Common Lisp)  2.6.8 CLtL1    Apr  7 2007 11:02:56
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License:  GPL due to GPL'ed components: (READLINE BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/

>(member :common-lisp *features*)

NIL

>(member :gcl *features*)

(:GCL :AKCL :COMMON :KCL)

>#-:common-lisp foo

Error: The variable FOO is unbound.
Fast links are on: do (si::use-fast-links nil) for debugging
Error signalled by EVAL.
Broken at EVAL.  Type :H for Help.

I would have expected the system NOT to try to evaluate foo.

\start
Date: Sat, 11 Aug 2007 20:00:28 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: A curious algebra failure

On Sat, 11 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > Your suggestion is correct, but the build still fails at the same
| > point.  Looking at the call to expt(x,n) in the Spad code  I don't
| > immediatelt see why it should be well-formed.  Do you see why it is
| > OK? 
| 
| Given:
| 
|    "**": (%,PositiveInteger) -> %
| 
| and
| 
|    x:% ** n:PositiveInteger == expt(x,n)
| 
| we need  
| 
|    expt: (%, PositiveInteger) -> %
| 
| But that is exactly what we get as export when saying:
| 
|     `import RepeatedSquaring(%)'


Yes, the import is supposed to bring expt() in scope.  And expt() is 
indeed brought in scope.

However, judging from the compiler's message it would appear that
RepeatedSquaring expects:

| Here, % certainly satisfies the conditions on the parameter type:
| 
|    SetCategory with "*": (%,%)->%

I don't think it does, in the sense of Spad.
I believe two unnamed categories define distinct categories irrespective of
their bodies. 

\start
Date: 11 Aug 2007 21:21:11 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

Gabriel Dos Reis writes:
> | Here, % certainly satisfies the conditions on the parameter type:
> | 
> |    SetCategory with "*": (%,%)->%
> 
> I don't think it does, in the sense of Spad.
> I believe two unnamed categories define distinct categories irrespective of
> their bodies. 

Are you saying that % is unnamed?  I can see that -- it's `principle'
category is unnamed, so to speak.

However, I have seen is kind of code in both Spad and Aldor a fair
bit.  I have always thought of `anonymous' category expressions
matching structurally as well as nominally.  I have always viewed the
lhs of a `with' as being the nominal part, the rhs the structural
part.  Of course that is just my interpretation -- I do not recall
reading a rule that either confirms nor refutes it.  I do not yet see
a difficulty with that point of view.

\start
Date: 11 Aug 2007 21:23:27 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: common-lisp and GCL-2.6.8pre *features*

Gabriel Dos Reis writes:
> >(member :common-lisp *features*)
> 
> NIL
> 
> >(member :gcl *features*)
> 
> (:GCL :AKCL :COMMON :KCL)
> 
> >#-:common-lisp foo
> 
> Error: The variable FOO is unbound.
> Fast links are on: do (si::use-fast-links nil) for debugging
> Error signalled by EVAL.
> Broken at EVAL.  Type :H for Help.
> 
> 
> 
> 
> I would have expected the system NOT to try to evaluate foo.

>From the hyperspec:

  #- is like #+ except that it skips the expression if the test succeeds; that is,

  #-test expression ==  #+(not test) expression


In other words, "#-:common-lisp foo"  means "evaluate foo iff
:common-lisp is not on *features*". 

\start
Date: Sat, 11 Aug 2007 20:27:26 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: A curious algebra failure

On Sat, 11 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| > | Here, % certainly satisfies the conditions on the parameter type:
| > | 
| > |    SetCategory with "*": (%,%)->%
| > 
| > I don't think it does, in the sense of Spad.
| > I believe two unnamed categories define distinct categories irrespective of
| > their bodies. 
| 
| Are you saying that % is unnamed?

`%' is not a category; it stands for the current domain.

I'm saying that the category

    SetCategory with "*": (%,%)->%

is unnamed.

I'm trying to find where I found that in the Axiom book, but no luck for the
moment.  Except the discussion in section 12.12 on Anonymous Categories.

\start
Date: 11 Aug 2007 20:42:12 -0500
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: common-lisp and GCL-2.6.8pre *features*

Stephen Wilson writes:

| Gabriel Dos Reis writes:
| > >(member :common-lisp *features*)
| > 
| > NIL
| > 
| > >(member :gcl *features*)
| > 
| > (:GCL :AKCL :COMMON :KCL)
| > 
| > >#-:common-lisp foo
| > 
| > Error: The variable FOO is unbound.
| > Fast links are on: do (si::use-fast-links nil) for debugging
| > Error signalled by EVAL.
| > Broken at EVAL.  Type :H for Help.
| > 
| > 
| > 
| > 
| > I would have expected the system NOT to try to evaluate foo.
| 
| >From the hyperspec:
| 
|   #- is like #+ except that it skips the expression if the test succeeds; that is,
| 
|   #-test expression ==  #+(not test) expression
| 
| 
| In other words, "#-:common-lisp foo"  means "evaluate foo iff
| :common-lisp is not on *features*". 

So, do you agree there is a bug in GCL here?

\start
Date: 11 Aug 2007 20:43:36 -0500
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: A curious algebra failure

Stephen Wilson writes:

[...]

| However, I have seen is kind of code in both Spad and Aldor a fair
| bit.  I have always thought of `anonymous' category expressions
| matching structurally as well as nominally.


OK, I got the reference I was looking for:  See on the discussion in
the Axiom book on Correctness, section 12.8.

\start
Date: 11 Aug 2007 21:42:16 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

Gabriel Dos Reis writes:

> On Sat, 11 Aug 2007, Stephen Wilson wrote:
> 
> | Gabriel Dos Reis writes:
> | > | Here, % certainly satisfies the conditions on the parameter type:
> | > | 
> | > |    SetCategory with "*": (%,%)->%
> | > 
> | > I don't think it does, in the sense of Spad.
> | > I believe two unnamed categories define distinct categories irrespective of
> | > their bodies. 
> | 
> | Are you saying that % is unnamed?
> 
> `%' is not a category; it stands for the current domain.
> 
> I'm saying that the category
> 
>     SetCategory with "*": (%,%)->%
> 
> is unnamed.

Right.  What I am saying is that in the type context

    S : SetCategory with "*": (%, %) -> %

when % denotes MONAD, the category of % (its `principle category' as I
called it, since in the general case it is anonymous), satisfies the
context.  Certainly MONAD has SetCategory and an export "*": (%, %) ->
%.  The nominal/structural typing rules (not that I have tried to
define them formally) are just my way of thinking about the issue.

If this interpretation does not hold, what kind of expression could
possibly satisfy the context S above?
 
> I'm trying to find where I found that in the Axiom book, but no luck for the
> moment.  Except the discussion in section 12.12 on Anonymous Categories.

As I said, I do not recall reading anything explicit on this point,
but I would be grateful if you can pull up a reference.  I might take
a look in the Aldor user guide and see if there is mention there.

\start
Date: 11 Aug 2007 21:45:40 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: common-lisp and GCL-2.6.8pre *features*

Gabriel Dos Reis writes:

> Stephen Wilson writes:
> 
> | Gabriel Dos Reis writes:
> | > >(member :common-lisp *features*)
> | > 
> | > NIL
> | > 
> | > >(member :gcl *features*)
> | > 
> | > (:GCL :AKCL :COMMON :KCL)
> | > 
> | > >#-:common-lisp foo
> | > 
> | > Error: The variable FOO is unbound.
> | > Fast links are on: do (si::use-fast-links nil) for debugging
> | > Error signalled by EVAL.
> | > Broken at EVAL.  Type :H for Help.
> | > 
> | > 
> | > 
> | > 
> | > I would have expected the system NOT to try to evaluate foo.
> | 
> | >From the hyperspec:
> | 
> |   #- is like #+ except that it skips the expression if the test succeeds; that is,
> | 
> |   #-test expression ==  #+(not test) expression
> | 
> | 
> | In other words, "#-:common-lisp foo"  means "evaluate foo iff
> | :common-lisp is not on *features*". 
> 
> So, do you agree there is a bug in GCL here?

No.  :common-lisp is (as you pointed out for gcl-2.6.8pre) _not_ on
*features*.  Thus:

   #-:common-lisp ==> #+(not :common-lisp) ==> #+T

Thus, 

  #-:common-lisp foo

is asking GCL to evaluate 'foo in this case. 

\start
Date: Sat, 11 Aug 2007 20:51:03 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: A curious algebra failure

On Sat, 11 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| 
| > On Sat, 11 Aug 2007, Stephen Wilson wrote:
| > 
| > | Gabriel Dos Reis writes:
| > | > | Here, % certainly satisfies the conditions on the parameter type:
| > | > | 
| > | > |    SetCategory with "*": (%,%)->%
| > | > 
| > | > I don't think it does, in the sense of Spad.
| > | > I believe two unnamed categories define distinct categories irrespective of
| > | > their bodies. 
| > | 
| > | Are you saying that % is unnamed?
| > 
| > `%' is not a category; it stands for the current domain.
| > 
| > I'm saying that the category
| > 
| >     SetCategory with "*": (%,%)->%
| > 
| > is unnamed.
| 
| Right.  What I am saying is that in the type context
| 
|     S : SetCategory with "*": (%, %) -> %
| 
| when % denotes MONAD, the category of % (its `principle category' as I
| called it, since in the general case it is anonymous), satisfies the
| context.  Certainly MONAD has SetCategory and an export "*": (%, %) ->
| %.  The nominal/structural typing rules (not that I have tried to
| define them formally) are just my way of thinking about the issue.

I think I understand what you're saying.  I'm not sure they match Spad typing
rules.  See the discussions in sections 12.8 and 12.12 of the Axiom book.
The short version is that 

    domains belong to categories by assertions.


| If this interpretation does not hold, what kind of expression could
| possibly satisfy the context S above?

That is the whole problem. :-)

As you suggested, I suspect it should have been written like

     if S has SetCategory and S has "*"

The trouble is that we don't want to test just for the name "*".  We
want to test for the signature
          
          "*":(%, %) -> %

I don't know how to write that in Spad -- Ralf?

\start
Date: Sat, 11 Aug 2007 20:55:19 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: common-lisp and GCL-2.6.8pre *features*

On Sat, 11 Aug 2007, Stephen Wilson wrote:

| Gabriel Dos Reis writes:
| 
| > Stephen Wilson writes:
| > 
| > | Gabriel Dos Reis writes:
| > | > >(member :common-lisp *features*)
| > | > 
| > | > NIL
| > | > 
| > | > >(member :gcl *features*)
| > | > 
| > | > (:GCL :AKCL :COMMON :KCL)
| > | > 
| > | > >#-:common-lisp foo
| > | > 
| > | > Error: The variable FOO is unbound.
| > | > Fast links are on: do (si::use-fast-links nil) for debugging
| > | > Error signalled by EVAL.
| > | > Broken at EVAL.  Type :H for Help.
| > | > 
| > | > 
| > | > 
| > | > 
| > | > I would have expected the system NOT to try to evaluate foo.
| > | 
| > | >From the hyperspec:
| > | 
| > |   #- is like #+ except that it skips the expression if the test succeeds; that is,
| > | 
| > |   #-test expression ==  #+(not test) expression
| > | 
| > | 
| > | In other words, "#-:common-lisp foo"  means "evaluate foo iff
| > | :common-lisp is not on *features*". 
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

| > So, do you agree there is a bug in GCL here?
| 
| No.  :common-lisp is (as you pointed out for gcl-2.6.8pre) _not_ on
| *features*. 

Hey, you said in the previous message

    In other words, "#-:common-lisp foo"  means "evaluate foo iff
    :common-lisp is not on *features*" 
                    ^^^

I tested that :common-lisp is NOT on *features*.  What am I missing?

\start
Date: Sat, 11 Aug 2007 20:56:48 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: [Gcl-devel] Re: common-lisp and GCL-2.6.8pre *features*

On Sat, 11 Aug 2007, Gabriel Dos Reis wrote:

| | > So, do you agree there is a bug in GCL here?
| | 
| | No.  :common-lisp is (as you pointed out for gcl-2.6.8pre) _not_ on
| | *features*. 
| 
| Hey, you said in the previous message
| 
|     In other words, "#-:common-lisp foo"  means "evaluate foo iff
|     :common-lisp is not on *features*" 
|                     ^^^
| 
| I tested that :common-lisp is NOT on *features*.  What am I missing?

I see what I'm missing.  Sorry for the noise.

\start
Date: 11 Aug 2007 22:53:04 -0400
From: Stephen Wilson
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

Gabriel Dos Reis writes:
[...]
> | Right.  What I am saying is that in the type context
> | 
> |     S : SetCategory with "*": (%, %) -> %
> | 
> | when % denotes MONAD, the category of % (its `principle category' as I
> | called it, since in the general case it is anonymous), satisfies the
> | context.  Certainly MONAD has SetCategory and an export "*": (%, %) ->
> | %.  The nominal/structural typing rules (not that I have tried to
> | define them formally) are just my way of thinking about the issue.
> 
> I think I understand what you're saying.  I'm not sure they match Spad typing
> rules.  See the discussions in sections 12.8 and 12.12 of the Axiom book.
> The short version is that 
> 
>     domains belong to categories by assertions.

Yes.  I agree with the sections you cited and in particular the quote
above.  The basic detail is that for some domain definition D and
category C:

   D() : Exp == Impl where
    Exp == C with
      foo : () -> %
    Impl == add ...

By assertion and assertion alone does D satisfy C.  It is not enough
to list the exports of C explicitly.  We agree on that, I think.

Now, C is not the most general category which D inhabits, which I
think we both agree on too.  In fact, any `add' expression could
inhabit many several Categories, we simply refine the possibilities
when we bind an `add' in a definition. Just for the sake of this
discussion, imagine if there were a categoryOf operator, then one
value for it to return is:

   categoryOf(D)  ==>  C with foo : () -> %

In other words, an anonymous category can capture both a nominal
assertion (the named categories on the lhs), and a structural
assertion (the lhs exports).  For example:

   C (S : with foo : () -> %) : Category == with ...

Here, S will match _any_ domain with an export `foo' of the
appropriate type.  Although it may not be explicitly documented, I do
think that this is the intent of the Spad language.
 
Similarly, anonymous `add' expressions should work in a comparable
way. Using C above, the following should be well typed:

   C( add foo(): % == ... )

This is using the very same type rules that would apply to a named
definition:

   D : C == add 
     foo(): % == ...

So I think we need this nominal/structural interpretation for `with'
expressions in order for the type system to make sense.


> | If this interpretation does not hold, what kind of expression could
> | possibly satisfy the context S above?
> 
> That is the whole problem. :-)
> 
> As you suggested, I suspect it should have been written like
> 
>      if S has SetCategory and S has "*"
> 
> The trouble is that we don't want to test just for the name "*".  We
> want to test for the signature
>           
>           "*":(%, %) -> %
> 
> I don't know how to write that in Spad -- Ralf?

In Aldor you can write the full `with' expression:

      if S has SetCategory with { *:(%, %) -> % }

I certainly think this would be good for Spad.  I think it effectively
captures the meaning of what anonymous categories denote.  

As a little aside, I am still thinking about `type patterns', so the
above `has' expression might we reducible to a function in that
context.  Imagine ML or Haskell style function definition by cases:

     fn (D : SetCategory with { *:(%, %) -> % }) => ...
      | (_ : _) => ...

In other words, I do not see `has' as primitive, just a syntactic
sugar.  Even run time predicates could be handled using the same
techniques as is common in ML style languages:

     fn (r : Ring) when prime? r => ...  

Well, thats a little far afield, but I thought it might be worth
mentioning.  Even if such expressions are not visible to the
programmer, it _might_ be a decent model for the compiler to use
internally.

\start
Date: 11 Aug 2007 22:55:59 -0400
From: Stephen Wilson
To: Stephen Wilson
Subject: Re: A curious algebra failure
Cc: Gabriel Dos Reis

Stephen Wilson writes:
> In other words, an anonymous category can capture both a nominal
> assertion (the named categories on the lhs), and a structural
> assertion (the lhs exports).  For example:
             ^^^^^^^^^^^^^^^

Sorry. That should be `the rhs exports'.

\start
Date: Sat, 11 Aug 2007 22:58:01 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

On 8/11/07, Gabriel Dos Reis wrote:
> On Sat, 11 Aug 2007, Stephen Wilson wrote:
>
> | Gabriel Dos Reis writes:
> |
> | > On Sat, 11 Aug 2007, Stephen Wilson wrote:
> | >
> | > | Gabriel Dos Reis writes:
> | > | > | Here, % certainly satisfies the conditions on the parameter type:
> | > | > |
> | > | > |    SetCategory with "*": (%,%)->%
> | > | >
> | > | > I don't think it does, in the sense of Spad.
> | > | > I believe two unnamed categories define distinct categories irrespective of
> | > | > their bodies.
> | > |

No, that is *not* correct. Unnamed categories are just values of type
Category. They are distinct only if the values are distinct. 'with' is
used to form a category-valued expression.

> | > | Are you saying that % is unnamed?
> | >
> | > `%' is not a category; it stands for the current domain.
> | >
> | > I'm saying that the category
> | >
> | >     SetCategory with "*": (%,%)->%
> | >
> | > is unnamed.
> |

That is correct.

> | Right.  What I am saying is that in the type context
> |
> |     S : SetCategory with "*": (%, %) -> %
> |
> | when % denotes MONAD, the category of % (its `principle category' as I
> | called it, since in the general case it is anonymous), satisfies the
> | context.  Certainly MONAD has SetCategory and an export "*": (%, %) ->
> | %.  The nominal/structural typing rules (not that I have tried to
> | define them formally) are just my way of thinking about the issue.
>
> I think I understand what you're saying.  I'm not sure they match Spad typing
> rules.  See the discussions in sections 12.8 and 12.12 of the Axiom book.
> The short version is that
>
>     domains belong to categories by assertions.
>
>
> | If this interpretation does not hold, what kind of expression could
> | possibly satisfy the context S above?
>
> That is the whole problem. :-)
>

This statement in the Axiom book should really say:

  "domains belong to *named* categories by assertions"

This does apply to anonymous categories.

> As you suggested, I suspect it should have been written like
>
>      if S has SetCategory and S has "*"
>

No, I don't think that is what Stephen is saying.

> The trouble is that we don't want to test just for the name "*".  We
> want to test for the signature
>
>           "*":(%, %) -> %
>

That is precisely what is meant by a domain satisfying a category
*value* (a so called "anonymous" category).

> I don't know how to write that in Spad -- Ralf?
>

I think that sometimes the best way to understand Spad is to look
backwards from the definition of Aldor. A much more rigorous and
consistent definition of Aldor concepts is given in the Aldor User
Guide (AUG) and in most cases these concepts map backwards to Spad
exactly as required.

In this case I would strongly recommend that you (re-)read Chapter 7
Types. Specifically take a look at Section 7.5 Subtypes for a
discussion of category-valued expressions versus named categories and
Section 7.7 Type Satisfaction. Also most of section 7.9 Categories
especially to understand the use of 'define' to refer to
category-valued constants (Note: define is not available in Spad).

Unfortunately www.aldor.org is down :-( again!! ). Perhaps you have a
copy of the pdf version of AUG? If not you can download a version of
it here:

http://www.ph.ed.ac.uk/~bj/paraldor/WWW/docs/documentation/axlugII.pdf

\start
Date: Sat, 11 Aug 2007 23:02:22 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

Correction:

On 8/11/07, I wrote:
>...
> This statement in the Axiom book should really say:
>
>   "domains belong to *named* categories by assertions"
>
> This does apply to anonymous categories.
>

I meant to write:

This does *not* apply to anonymous categories.

\start
Date: Sun, 12 Aug 2007 00:11:01 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: A curious algebra failure

On Sat, 11 Aug 2007, Bill Page wrote:

| On 8/11/07, Gabriel Dos Reis wrote:
| > On Sat, 11 Aug 2007, Stephen Wilson wrote:
| >
| > | Gabriel Dos Reis writes:
| > |
| > | > On Sat, 11 Aug 2007, Stephen Wilson wrote:
| > | >
| > | > | Gabriel Dos Reis writes:
| > | > | > | Here, % certainly satisfies the conditions on the parameter type:
| > | > | > |
| > | > | > |    SetCategory with "*": (%,%)->%
| > | > | >
| > | > | > I don't think it does, in the sense of Spad.
| > | > | > I believe two unnamed categories define distinct categories irrespective of
| > | > | > their bodies.
| > | > |
| 
| No, that is *not* correct. Unnamed categories are just values of type
| Category.

But, that is not what Axiom Book says, section 12.12, page 525:

   The part of a category to the right of a with is also regarded as 
   a category -- an "anonymous category". [...]
   [ rewriting packages with named categories skipped ]
   There is no reason, however, to give this list of exports a name since no
   other domain of package exports it.  In fact, it is rare for a package to
   export a named category.  [...]

This, to me, suggest that the semantics described and intended in the 
Axiom Book is that two unnamed categories always yields different categories
irrespective of their bodies.

That may nto be what we want or would like, but I believe that is what was
intended in the Axiom Book.
   

| They are distinct only if the values are distinct. 'with' is
| used to form a category-valued expression.

I don't get this.  Please, could you give more Spad examples of what you mean? 

| 
| > | > | Are you saying that % is unnamed?
| > | >
| > | > `%' is not a category; it stands for the current domain.
| > | >
| > | > I'm saying that the category
| > | >
| > | >     SetCategory with "*": (%,%)->%
| > | >
| > | > is unnamed.
| > |
| 
| That is correct.
| 
| > | Right.  What I am saying is that in the type context
| > |
| > |     S : SetCategory with "*": (%, %) -> %
| > |
| > | when % denotes MONAD, the category of % (its `principle category' as I
| > | called it, since in the general case it is anonymous), satisfies the
| > | context.  Certainly MONAD has SetCategory and an export "*": (%, %) ->
| > | %.  The nominal/structural typing rules (not that I have tried to
| > | define them formally) are just my way of thinking about the issue.
| >
| > I think I understand what you're saying.  I'm not sure they match Spad typing
| > rules.  See the discussions in sections 12.8 and 12.12 of the Axiom book.
| > The short version is that
| >
| >     domains belong to categories by assertions.
| >
| >
| > | If this interpretation does not hold, what kind of expression could
| > | possibly satisfy the context S above?
| >
| > That is the whole problem. :-)
| >
| 
| This statement in the Axiom book should really say:
| 
|   "domains belong to *named* categories by assertions"
| 
| This does apply to anonymous categories.

Well, there is what we *would like* the Axiom Book to say, and what it
intended to say and what is implemented.

| > As you suggested, I suspect it should have been written like
| >
| >      if S has SetCategory and S has "*"
| >
| 
| No, I don't think that is what Stephen is saying.
| 
| > The trouble is that we don't want to test just for the name "*".  We
| > want to test for the signature
| >
| >           "*":(%, %) -> %
| >
| 
| That is precisely what is meant by a domain satisfying a category
| *value* (a so called "anonymous" category).

Except that is not what is described in the Axiom Book.

| > I don't know how to write that in Spad -- Ralf?
| >
| 
| I think that sometimes the best way to understand Spad is to look
| backwards from the definition of Aldor. A much more rigorous and
| consistent definition of Aldor concepts is given in the Aldor User
| Guide (AUG) and in most cases these concepts map backwards to Spad
| exactly as required.

Yes, I understand that Aldor is an evolution of Spad that fixes many issues. 
The issue right now is what the actual semantics is, that we must distinguish 
from what we would like it to say.  The distinction is very important so that
we measure the impact of the changes that will result (for the Alegbra --
hopefully, we don't have many cases like this).  The Axiom Book went on
greater details in section 12.8 (correctness) explaining why they reject
structural conformance -- even partial.

I'm not saying that is a good thing.  I'm trying to draw the line between 
what the intended semantics are and what we would like them to be.

| In this case I would strongly recommend that you (re-)read Chapter 7
| Types. Specifically take a look at Section 7.5 Subtypes for a
| discussion of category-valued expressions versus named categories and
| Section 7.7 Type Satisfaction. Also most of section 7.9 Categories
| especially to understand the use of 'define' to refer to
| category-valued constants (Note: define is not available in Spad).

Yes, but here we are discussing Spad :-)

| Unfortunately www.aldor.org is down :-( again!! ). Perhaps you have a
| copy of the pdf version of AUG?

Yes, I do.

| If not you can download a version of
| it here:
| 
| http://www.ph.ed.ac.uk/~bj/paraldor/WWW/docs/documentation/axlugII.pdf

\start
Date: Sun, 12 Aug 2007 00:45:29 -0500 (CDT)
From: Gabriel Dos Reis
To: Stephen Wilson
Subject: Re: A curious algebra failure

On Sat, 11 Aug 2007, Stephen Wilson wrote:

| In other words, an anonymous category can capture both a nominal
| assertion (the named categories on the lhs), and a structural
| assertion (the lhs exports).  For example:
| 
|    C (S : with foo : () -> %) : Category == with ...
| 
| Here, S will match _any_ domain with an export `foo' of the
| appropriate type.  Although it may not be explicitly documented, I do
| think that this is the intent of the Spad language.

Do you see code in the compiler that supports that?

\start
Date: Sun, 12 Aug 2007 00:47:23 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: A curious algebra failure

On Sat, 11 Aug 2007, Bill Page wrote:

| Correction:
| 
| On 8/11/07, I wrote:
| >...
| > This statement in the Axiom book should really say:
| >
| >   "domains belong to *named* categories by assertions"
| >
| > This does apply to anonymous categories.
| >
| 
| I meant to write:
| 
| This does *not* apply to anonymous categories.

Yes, but they gave no indication that they do structural matching.
They gave examples and explanations of why they don't do it
-- even partially.  So, the semantics is still mystery...

\start
Date: 12 Aug 2007 09:40:29 +0200
From: Martin Rubey
To: Tim Daly, Gabriel Dos Reis,	Juergen Weiss, Bill Page
Subject: Re: ChangeLog on Silver

Tim, Gaby, *

I wonder why this is on list.  Did I make a mistake?

Tim Daly writes:

> > I felt quite bad when I saw Gaby's post announcing the ChangeLog format
> > change and a little while later Tim's reply:
> 
> Right. So the sequence went: Gaby's post, my objection, Gaby's change to
> trunk, Gaby's reply
> 
> So there really was no voting, no attempt at democracy, no effort your part
> to enforce the "democracy" you so badly wanted. Just silence.

true.  I tried to explain this in my post.  By the way, there has so far been
no decision to adopt my proposal.  Ralf recently sent me
http://producingoss.com, and I think it is indeed good advice, but I currently
do not have enough time and I do have enough other trouble.

> > Meanwhile I feel much better. There has been a vote.
> 
> Right. After the fact. You're happy that you didn't have to 
> step in and enforce your new "democracy" because the vote came
> down in your favor.

No it didn't.  Please reread my post:

> > I really didn't know what to do.  I somewhat liked Tim's format, but I
> > understand well, that it is not really common use.  More importantly, I
> > remember too well how I felt seeing the noweb change in trunk.

In any case I will never accept that from now on XXX decides.  

> My anger will be dismissed as the complaints of "the one who lost" but that
> will certainly miss the point. The format of the changelog file is not a
> problem, the method of handling the voting is.

And this is *exactly* the reason why I posted at all.  Otherwise I would have
kept silent.

-------------------------------------------------------------------------------

Gaby:

I did read your amendments, and I do believe that they are a good (very likely:
necessary) complement to democracy.  However, given our personalities (for
example: my personality), there will always be disagreement about certain
things.  The model I proposed has as intention to encourage people to keep
their branches synchronised with trunk.

This would be adressed also by the idea of a college:

>    * A College (or Steering Committee) whose job is to make sure that
>      the project is not over taken by an individual.  I truly believe
>      we need that.  I've spoken to and received emails from some
>      original Axiom developers who also promote the College view.
> 
>      The College's job is not to make technical decisions.  The
>      College will be discussing and making decisions about political
>      issues.  Any developer can at any time request the College to
>      consider any matter of his/her importance.
>      The College appoints maintainers and release managers.
> 
>      The College should not consist only of developers.  Users should
>      be represented.  In general, people with either long term
>      committement or interest in Axiom should be represented there.
> 
>      I suggested to keep the number of College members small.  I
>      suggested 7 for concreteness.

I thought that the idea of voting what goes into trunk was simpler to
implement, but I'm open to any model that avoids leaving people (also Tim) in
the dark.

How is the college formed?  How will the college decide internally?  Currently
there are not so many developers - are there more than ten?

Maybe you could add this to MathAction, maybe to the same page I set up.  Do
you think the two models are fundamentally incompatible?

\start
Date: 12 Aug 2007 09:55:02 +0200
From: Martin Rubey
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

Gabriel Dos Reis writes:

> As you suggested, I suspect it should have been written like
> 
>      if S has SetCategory and S has "*"
> 
> The trouble is that we don't want to test just for the name "*".  We
> want to test for the signature
>           
>           "*":(%, %) -> %
> 
> I don't know how to write that in Spad -- Ralf?

I do not know whether it is helpful, but I wrote code like

diffDSF: DIFFSPECSF
diffDSF(s, n) == 
-- I have to help the compiler here a little to choose the right signature...
    if SUP F has _*: (NonNegativeInteger, SUP F) -> SUP F
    then D(s, n)

I don't think that 

    if S has _*: (%, %) -> %

would work, but

    if S has _*: (S, S) -> S

should.

Warning: I didn't check whether this is what you want to fix your bug.

\start
Date: Sun, 12 Aug 2007 12:11:42 +0200
From: Juergen Weiss
To: Gabriel Dos Reis
Subject: RE: A curious algebra failure

The file patches.lisp in the scratchpad sources from 1990 contained the
following line:

(defun |pmatch| (s p) (|pmatchWithSl| s p '(ok))) ;assoc with atom at
eol

to override the definition in c-util.boot.

Seems that pmatchWithSl returns nil when a match
is not possible, empty assoc list != nil when no substitutions are
necessary
for a match and an assoc list with substitutions otherwise.

For example
  v:= ASSOC(p,al) => s=rest v or al
returns 't if (p,s) is in al.

So this function can never typecheck in ansi common lisp. The
usage seems to come from a time when alists could contain
atomic properties and associations as well.

By the way, I think the line must read

  v:= ASSOC(p,al) => s=rest v and al
                              ====

this makes much more sense logically and should typecheck with
the   pmatch(s,p) == pmatchWithSl(s,p,[nil])


Regards

Juergen Weiss

Juergen Weiss	  | Universitaet Mainz, Zentrum fuer Datenverarbeitung,
Juergen Weiss| 55099 Mainz, Tel: +49(6131)39-26361, FAX:
+49(6131)39-26407


> -----Original Message-----
> From: axiom-developer-bounces+weiss=uni-mainz.de@nongnu.org
>  On Behalf Of Gabriel Dos Reis
> Sent: Sunday, August 12, 2007 12:52 AM
> To: list
> Subject: A curious algebra failure
>
>
> Hi,
>
>   This issue pops up while looking at a type error in
> src/interp/c-util.boot.
>
>   1.  The type error
>
>      Consider the function pmatch() from c-util.boot
>
>          pmatch(s,p) == pmatchWithSl(s,p,"ok")
>
>      That function is essentially called by the compiler to check
>      whether an expression e in mode m is coercible to mode m', as
>      can be seen from coerceable() defined in compile.boot
>
>        coerceable(m,m',e) ==
> 	 m=m' => m
> 	 -- must find any free parameters in m
> 	 sl:= pmatch(m',m) => SUBLIS(sl,m')
> 	 coerce(["$fromCoerceable$",m,e],m') => m'
> 	 nil
>
>       Basically, the expression e of mode m is coercible to mode m' if
>          (a) m and m' are identical -- the identity conversion;
>   
>          (b) m and m' can be unified by instantiating variables in m
>               -- instantiatiion conversion, the case handled
> by pmatch;
>
>          (c) or by attempting the actual conversion and see what
>               happens -- the "speculative" call to coerce();
>         
>          (d) and that is all.
>        
>
>
>        So far, so good.
>
>        Now, let's look at the definition of pmatchWithSl() in
> c-util.boot:
>
> 	   pmatchWithSl(s,p,al) ==
> 	     s=$EmptyMode => nil
> 	     s=p => al
> 	     v:= ASSOC(p,al) => s=rest v or al
> 	     MEMQ(p,$PatternVariableList) => [[p,:s],:al]
> 	     null atom p and null atom s and_
> 		     (al':= pmatchWithSl(first s,first p,al)) and
> 	       pmatchWithSl(rest s,rest p,al')
>
>        Essentially, pmatchWithSl() computes a substitution that would
>        make the pattern p match the value s.  It uses a simply minded
>        unification algorithm, and is probably not efficient but that
>        is not of concern here.
>
>        A simple type inference shows that the third argument to
>        pmatchWithSl() must be an association list.  Therefore, the
>        current definition of pmatch() is ill-formed.
>
>
>    2.  The correct definition of pmatch
>
>        Now that we have established that the existing definition of
>        pmatch is incorrect, what should a correct definition look
>        like?  Well, the whole thing pmatch() computes is a `minimal'
>        substitution that makes p match s.  So, it should start with
>        the identity substituation (or null substitution) and updates
>        it as it goes through the unification process.  So the correct
>        definition is:
>
>          pmatch(s,p) == pmatchWithSl(s,p,[nil])
>
>        where [nil] stands for the identity substitution.
>
>
>    3.  The problem in Algebra bootstrap
>
>        After correction of pmatch(), I started a fresh build with
>        maximum safety turn on.  Everything proceeded well till
>        compilation of MONAD.spad where I see a failure with the
>        following message:
>
> --------------------------------------------------------------
> ----------
>    initializing NRLIB MONAD- for Monad&
>    compiling into NRLIB MONAD-
>    importing RepeatedSquaring S
>    compiling exported ** : (S,PositiveInteger) -> S
> ****** comp fails at level 1 with expression: ******
> error in function **
>
> (S)
> ****** level 1  ******
> $x:= S
> $m:= (Join (SetCategory) (CATEGORY domain (SIGNATURE * ($ $ $))))
> $f:=
> ((((|n| # #) (|x| # #) (* # # #) (** # # #) ...)))
> 
>    >> Apparent user error:
>    Cannot coerce S
>       of mode (Monad)
>       to mode (Join (SetCategory) (CATEGORY domain (SIGNATURE
> * ($ $ $))))
>
>
>
>
>         Looking at the definition of MONAD, reproduced below, I see no
>         reason to expect that the call to expt(x,n) should work. What
>         am I missing?
>
>
> Thanks,
>
> -- Gaby
>
> )abbrev category MONAD Monad
> ++ Authors: J. Grabmeier, R. Wisbauer
> ++ Date Created: 01 March 1991
> ++ Date Last Updated: 11 June 1991
> ++ Basic Operations: *, **
> ++ Related Constructors: SemiGroup, Monoid, MonadWithUnit
> ++ Also See:
> ++ AMS Classifications:
> ++ Keywords: Monad,  binary operation
> ++ Reference:
> ++  N. Jacobson: Structure and Representations of Jordan Algebras
> ++  AMS, Providence, 1968
> ++ Description:
> ++  Monad is the class of all multiplicative monads, i.e. sets
> ++  with a binary operation.
> Monad(): Category == SetCategory with
>     --operations
>       "*": (%,%) -> %
>         ++ a*b is the product of \spad{a} and b in a set with
>         ++ a binary operation.
>       rightPower: (%,PositiveInteger) -> %
>         ++ rightPower(a,n) returns the \spad{n}-th right
> power of \spad{a},
>         ++ i.e. \spad{rightPower(a,n) := rightPower(a,n-1) * a} and
>         ++ \spad{rightPower(a,1) := a}.
>       leftPower: (%,PositiveInteger) -> %
>         ++ leftPower(a,n) returns the \spad{n}-th left power
> of \spad{a},
>         ++ i.e. \spad{leftPower(a,n) := a * leftPower(a,n-1)} and
>         ++ \spad{leftPower(a,1) := a}.
>       "**": (%,PositiveInteger) -> %
>         ++ a**n returns the \spad{n}-th power of \spad{a},
>         ++ defined by repeated squaring.
>     add
>       import RepeatedSquaring(%)
>       x:% ** n:PositiveInteger == expt(x,n)
>       rightPower(a,n) ==
> --        one? n => a
>         (n = 1) => a
>         res := a
>         for i in 1..(n-1) repeat res := res * a
>         res
>       leftPower(a,n) ==
> --        one? n => a
>         (n = 1) => a
>         res := a
>         for i in 1..(n-1) repeat res := a * res
>         res

\start
Date: Sun, 12 Aug 2007 08:16:56 -0400
From: Bill Page
To: Juergen Weiss
Subject: Re: A curious algebra failure
Cc: Gabriel Dos Reis

On 8/12/07, Weiss, Juergen wrote:
>
> The file patches.lisp in the scratchpad sources from 1990 contained the
> following line:
>
> (defun |pmatch| (s p) (|pmatchWithSl| s p '(ok))) ;assoc with atom at
> eol
>
> to override the definition in c-util.boot.
>

This reminds me to ask/suggest that the contents of 'patches.lisp'
should be merged back onto the original sources that are being
patched. Surely this way of patching the Lisp code should be avoided
since it negates most advantages of source code control and makes the
actual function of significant parts of the code more obscure.

> Seems that pmatchWithSl returns nil when a match

\start
Date: Sun, 12 Aug 2007 09:17:18 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: A curious algebra failure

On 8/12/07, Gabriel Dos Reis wrote:
> On Sat, 11 Aug 2007, Bill Page wrote:
> | ...
> | Unnamed categories are just values of type Category.
>
> But, that is not what Axiom Book says, section 12.12, page 525:
>
>    The part of a category to the right of a with is also regarded as
>    a category -- an "anonymous category". [...]
>    [ rewriting packages with named categories skipped ]
>    There is no reason, however, to give this list of exports a name since no
>    other domain of package exports it.  In fact, it is rare for a package to
>    export a named category.  [...]
>
> This, to me, suggest that the semantics described and intended in the
> Axiom Book is that two unnamed categories always yields different categories
> irrespective of their bodies.
>

You must be reading between the lines :-) since I certainly can not
deduce that two unnamed categories are always distinct from the
quotation. In fact the opposite. The discussion of exporting a named
category here is rather gratuitous unless you assume that there is a
better reason for exporting "anonymous" categories than simple
convenience. The reason why most packages export anonymous categories
is precisely because of how named categories are interpreted:
categories with different names but identical structure are considered
distinct. This is important because Axiom wants to associate these
*names* with mathematical properties. In many cases the name must
carry the proper mathematical interpretation irrespective of whether
or not the categories have the same structure.

See the examples at:

http://wiki.axiom-developer.org/SandBoxCategories

But notice that these examples also illustrate what I think is an
error in the result of evaluating has for category-valued expressions
in Spad.

> That may not be what we want or would like, but I believe that is what was
> intended in the Axiom Book.
>

No can't be true, otherwise how would any of the Axiom library
actually work? (As Stephen has already pointed out.)

>
> | They are distinct only if the values are distinct. 'with' is
> | used to form a category-valued expression.
>
> I don't get this.  Please, could you give more Spad examples of what you mean?
>

See

http://wiki.axiom-developer.org/SandBoxCategories

\start
Date: Sun, 12 Aug 2007 08:26:18 -0500 (CDT)
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: ChangeLog on Silver
Cc: Bill Page

On Sun, 12 Aug 2007, Martin Rubey wrote:

| Gaby:
| 
| I did read your amendments, and I do believe that they are a good (very likely:
| necessary) complement to democracy.  However, given our personalities (for
| example: my personality), there will always be disagreement about certain
| things.  The model I proposed has as intention to encourage people to keep
| their branches synchronised with trunk.

I do not believe my proposed model will remove disagreements.  However, I
would like to take political issues to a different entity that just 
developers.  

| 
| This would be adressed also by the idea of a college:
| 
| >    * A College (or Steering Committee) whose job is to make sure that
| >      the project is not over taken by an individual.  I truly believe
| >      we need that.  I've spoken to and received emails from some
| >      original Axiom developers who also promote the College view.
| > 
| >      The College's job is not to make technical decisions.  The
| >      College will be discussing and making decisions about political
| >      issues.  Any developer can at any time request the College to
| >      consider any matter of his/her importance.
| >      The College appoints maintainers and release managers.
| > 
| >      The College should not consist only of developers.  Users should
| >      be represented.  In general, people with either long term
| >      committement or interest in Axiom should be represented there.
| > 
| >      I suggested to keep the number of College members small.  I
| >      suggested 7 for concreteness.
| 
| I thought that the idea of voting what goes into trunk was simpler to
| implement, but I'm open to any model that avoids leaving people (also Tim) in
| the dark.

Certainly, in my amendement, I see Tim or Bill as a Global maintainers, so I
don't see who he will be left in dark.  I aslo see people like Juergen Weiss,
Barry Trager, or you, as members of the College (assuming they are willing to).

| How is the college formed?

Initially, the College would be formed by proposal by people on this list
(assuming potential members accept the task) and everybody subscribes to
axiom-developer would vote.  From there on, the College would replace 
leaving members by vote.


| How will the college decide internally?

Large consensus or if necessary vote.

|  Currently
| there are not so many developers - are there more than ten?

I believe the College should no be the union of developers.  The union of
developers is the maintainers.

| Maybe you could add this to MathAction,

When I received your original proposal, I replied to MathAction with the
suggested amendment.  For some reasons, it does not show up.
Bill do you know why?

\start
Date: 12 Aug 2007 08:37:53 -0500
From: Gabriel Dos Reis
To: Martin Rubey
Subject: re: ChangeLog on Silver
Cc: Bill Page

Martin Rubey writes:

| Tim, Gaby, *
| 
| I wonder why this is on list.  Did I make a mistake?

No, you did not.

\start
Date: Sun, 12 Aug 2007 08:33:44 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: A curious algebra failure

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Gabriel Dos Reis wrote:
| > On Sat, 11 Aug 2007, Bill Page wrote:
| > | ...
| > | Unnamed categories are just values of type Category.
| >
| > But, that is not what Axiom Book says, section 12.12, page 525:
| >
| >    The part of a category to the right of a with is also regarded as
| >    a category -- an "anonymous category". [...]
| >    [ rewriting packages with named categories skipped ]
| >    There is no reason, however, to give this list of exports a name since no
| >    other domain of package exports it.  In fact, it is rare for a package to
| >    export a named category.  [...]
| >
| > This, to me, suggest that the semantics described and intended in the
| > Axiom Book is that two unnamed categories always yields different categories
| > irrespective of their bodies.
| >
| 
| You must be reading between the lines :-)

certainly, as there is no formal description of the semantics! :-)
Anything we can do is to guess, to read between the lines.

| since I certainly can not
| deduce that two unnamed categories are always distinct from the
| quotation. In fact the opposite. The discussion of exporting a named
| category here is rather gratuitous unless you assume that there is a
| better reason for exporting "anonymous" categories than simple
| convenience. The reason why most packages export anonymous categories
| is precisely because of how named categories are interpreted:
| categories with different names but identical structure are considered
| distinct. This is important because Axiom wants to associate these
| *names* with mathematical properties. In many cases the name must
| carry the proper mathematical interpretation irrespective of whether
| or not the categories have the same structure.
| 
| See the examples at:
| 
| http://wiki.axiom-developer.org/SandBoxCategories

Thanks.

| But notice that these examples also illustrate what I think is an
| error in the result of evaluating has for category-valued expressions
| in Spad.

How does the compiler behave when the error we are discussing is fixed?

I'm trying Juergen's suggested fix, which has different semantics than
that of Stephen.

\start
Date: 12 Aug 2007 08:40:16 -0500
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: A curious algebra failure

Martin Rubey writes:

| Gabriel Dos Reis writes:
| 
| > As you suggested, I suspect it should have been written like
| > 
| >      if S has SetCategory and S has "*"
| > 
| > The trouble is that we don't want to test just for the name "*".  We
| > want to test for the signature
| >           
| >           "*":(%, %) -> %
| > 
| > I don't know how to write that in Spad -- Ralf?
| 
| I do not know whether it is helpful, but I wrote code like
| 
| diffDSF: DIFFSPECSF
| diffDSF(s, n) == 
| -- I have to help the compiler here a little to choose the right signature...
|     if SUP F has _*: (NonNegativeInteger, SUP F) -> SUP F
|     then D(s, n)
| 
| I don't think that 
| 
|     if S has _*: (%, %) -> %
| 
| would work, but
| 
|     if S has _*: (S, S) -> S
| 
| should.
| 
| Warning: I didn't check whether this is what you want to fix your bug.

That might help.  Let me test Jurgen's fix, first.

\start
Date: Sun, 12 Aug 2007 09:37:22 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: ChangeLog on Silver
Cc: Bill Page

On 8/12/07, Gabriel Dos Reis wrote:
> On Sun, 12 Aug 2007, Martin Rubey wrote:
> ...
> | Maybe you could add this to MathAction,
>
> When I received your original proposal, I replied to MathAction with the
> suggested amendment.  For some reasons, it does not show up.
> Bill do you know why?
>

No, I don't know for sure. This is supposed to work but reasons of
spam prevention the Wiki will reject a reply if the email address of
the sender does not exactly match the email address of a subscriber
the the Wiki, i.e. you must be subscribed to the wiki in order for it
to append you reply to an existing page or create a new page. Also
make sure to keep the bracketed [...] contents in the subject line
since that is how it is supposed to tell to which page it should
append your comments.

If you are having trouble with this let me know, but if all else fails
you could always yous the browser interface rather than an email
reply. :-)

\start
Date: Sun, 12 Aug 2007 08:40:03 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: ChangeLog on Silver
Cc: Bill Page

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Gabriel Dos Reis wrote:
| > On Sun, 12 Aug 2007, Martin Rubey wrote:
| > ...
| > | Maybe you could add this to MathAction,
| >
| > When I received your original proposal, I replied to MathAction with the
| > suggested amendment.  For some reasons, it does not show up.
| > Bill do you know why?
| >
| 
| No, I don't know for sure. This is supposed to work but reasons of
| spam prevention the Wiki will reject a reply if the email address of
| the sender does not exactly match the email address of a subscriber
| the the Wiki, i.e. you must be subscribed to the wiki in order for it
| to append you reply to an existing page or create a new page. Also
| make sure to keep the bracketed [...] contents in the subject line
| since that is how it is supposed to tell to which page it should
| append your comments.

I receive emails from mathaction, so I thought I was subscribed.
Is it again a confusion with my two emails doing it?  Is there a way for you
to check which address is accepted, which is rejected?

| If you are having trouble with this let me know, but if all else fails
| you could always yous the browser interface rather than an email
| reply. :-)

Tim and I, despite our differences, share a lot of traits regarding emails 
and Emacs :-)

\start
Date: 12 Aug 2007 08:40:32 -0500
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: Re: A curious algebra failure

Juergen Weiss writes:

| Hi,
| 
| The file patches.lisp in the scratchpad sources from 1990 contained the
| following line:
| 
| (defun |pmatch| (s p) (|pmatchWithSl| s p '(ok))) ;assoc with atom at
| eol
| 
| to override the definition in c-util.boot.
| 
| Seems that pmatchWithSl returns nil when a match
| is not possible, empty assoc list != nil when no substitutions are
| necessary
| for a match and an assoc list with substitutions otherwise. 

Thanks for clarifying further the intended semantics.

| 
| For example
|   v:= ASSOC(p,al) => s=rest v or al
| returns 't if (p,s) is in al.
| 
| So this function can never typecheck in ansi common lisp. The
| usage seems to come from a time when alists could contain
| atomic properties and associations as well.

Indeed.

| By the way, I think the line must read
| 
|   v:= ASSOC(p,al) => s=rest v and al
|                               ====
| 
| this makes much more sense logically and should typecheck with 
| the   pmatch(s,p) == pmatchWithSl(s,p,[nil])


Yes, it typechecks; I just started a new build; I will report back.
I like your semantics description and suggested fix better.

\start
Date: Sun, 12 Aug 2007 08:42:29 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: A curious algebra failure

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Weiss, Juergen wrote:
| >
| > The file patches.lisp in the scratchpad sources from 1990 contained the
| > following line:
| >
| > (defun |pmatch| (s p) (|pmatchWithSl| s p '(ok))) ;assoc with atom at
| > eol
| >
| > to override the definition in c-util.boot.
| >
| 
| This reminds me to ask/suggest that the contents of 'patches.lisp'
| should be merged back onto the original sources that are being
| patched.

I fully agree with that.

\start
Date: Sun, 12 Aug 2007 09:44:38 -0400
From: Bill Page
To: Tim Daly
Subject: Re: Wiki

On 8/12/07, Tim Daly wrote:
> Bill,
>
> I have decided to recover the original Axiom project goals.  I'm in
> the process of changing things around so the axiom-developer.org site
> will reflect the project I started.
>
> You need to plan to rehost the wiki on a different server.
>
> Tim
>

Tim,

I felt I should Cc: the axiom-developer list since this decision will
affect most Axiom developers and users.

What can I say about your plan but: "As you wish, Sir." :-(

We have (rather, we had) a mirror of this wiki on a server at RISC.
This server is in the process of being rebuilt because of a hard disk
failure. We will need to determine if RISC wants to mirror your
revised axiom-developer.org site or continuing to run the old wiki.

Meanwhile the Sage project has also offered to mirror the current
Axiom wiki site but I have not done any work on that yet.

What is your timetable for the change?

\start
Date: Sun, 12 Aug 2007 09:48:40 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: ChangeLog on Silver
Cc: Bill Page

On 8/12/07, Gabriel Dos Reis wrote:
> ...
> I receive emails from mathaction, so I thought I was subscribed.
> Is it again a confusion with my two emails doing it?  Is there a way for you
> to check which address is accepted, which is rejected?
>
> | If you are having trouble with this let me know, but if all else fails
> | you could always yous the browser interface rather than an email
> | reply. :-)
>
> Tim and I, despite our differences, share a lot of traits regarding emails
> and Emacs :-)
>

The email address that you used to subscribe to the Axiom Wiki is:

  Gabriel Dos Reis

I can change it if you wish.

\start
Date: Sun, 12 Aug 2007 08:51:30 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: ChangeLog on Silver
Cc: Bill Page

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Gabriel Dos Reis wrote:
| > ...
| > I receive emails from mathaction, so I thought I was subscribed.
| > Is it again a confusion with my two emails doing it?  Is there a way for you
| > to check which address is accepted, which is rejected?
| >
| > | If you are having trouble with this let me know, but if all else fails
| > | you could always yous the browser interface rather than an email
| > | reply. :-)
| >
| > Tim and I, despite our differences, share a lot of traits regarding emails
| > and Emacs :-)
| >
| 
| The email address that you used to subscribe to the Axiom Wiki is:
| 
|   Gabriel Dos Reis

Aha!  Thanks.

| I can change it if you wish.

That address is fine.  I would just like to be able to send email
from my TAMU account, but not receive mathaction emails there, I suspect it is
the same setting as for the axiom-developer?

\start
Date: Sun, 12 Aug 2007 08:55:56 -0500
From: Tim Daly
To: Bill Page
Subject: Wiki

There is no hurry. Take the time you need.

\start
Date: Sun, 12 Aug 2007 09:57:26 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: ChangeLog on Silver
Cc: Bill Page

On 8/12/07, Gabriel Dos Reis wrote:
> On Sun, 12 Aug 2007, Bill Page wrote:
> |
> | The email address that you used to subscribe to the Axiom Wiki is:
> |
> |   Gabriel Dos Reis
>
> Aha!  Thanks.
>
> | I can change it if you wish.
>
> That address is fine.  I would just like to be able to send email
> from my TAMU account, but not receive mathaction emails there, I suspect it is
> the same setting as for the axiom-developer?
>

Unfortunately the Axiom Wiki is not integrated at all with the
axiom-developer email list. Without checking a little deeper, I do not
know immediately whether it is possible to have a "silent"
subscription to the Axiom Wiki that would let you post replies but not
receive email notices - but I doubt it. Maybe you can live with the
duplication of emails and just subscribe twice? (Normally the volume
of email is quite low.)

\start
Date: 12 Aug 2007 09:03:11 -0500
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: Re: A curious algebra failure

Gabriel Dos Reis writes:

[...]

| | By the way, I think the line must read
| | 
| |   v:= ASSOC(p,al) => s=rest v and al
| |                               ====
| | 
| | this makes much more sense logically and should typecheck with 
| | the   pmatch(s,p) == pmatchWithSl(s,p,[nil])
| 
| 
| Yes, it typechecks; I just started a new build; I will report back.
| I like your semantics description and suggested fix better.

It also fails.  But, I believe your suggested fix is the most correct.

\start
Date: Sun, 12 Aug 2007 09:00:33 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: ChangeLog on Silver
Cc: Bill Page

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Gabriel Dos Reis wrote:
| > On Sun, 12 Aug 2007, Bill Page wrote:
| > |
| > | The email address that you used to subscribe to the Axiom Wiki is:
| > |
| > |   Gabriel Dos Reis
| >
| > Aha!  Thanks.
| >
| > | I can change it if you wish.
| >
| > That address is fine.  I would just like to be able to send email
| > from my TAMU account, but not receive mathaction emails there, I suspect it is
| > the same setting as for the axiom-developer?
| >
| 
| Unfortunately the Axiom Wiki is not integrated at all with the
| axiom-developer email list. Without checking a little deeper, I do not
| know immediately whether it is possible to have a "silent"
| subscription to the Axiom Wiki that would let you post replies but not
| receive email notices - but I doubt it.

Thanks for checking!

| Maybe you can live with the
| duplication of emails and just subscribe twice? (Normally the volume
| of email is quite low.)

I have enough mails at my TAMU account that I would hesitate to add more
of mailing list traffic there.

Many thanks for your help; I'll figure out what I can do.

\start
Date: Sun, 12 Aug 2007 01:26:19 +0200
From: Ralf Hemmecke
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

On 08/10/2007 06:13 PM, Tim Daly wrote:
>> BTW, why do you think it is so essential that the underlying language of
>> Axiom must be LISP? 
> 
> I don't. In fact, we've had discussions about using Aldor all the way
> down.  I don't have the time to rewrite everything in Aldor.

But you have time to replace BOOT by LISP.

> But it already is in Lisp. Boot is just syntactic sugar for Lisp which limits
> what you can write and obscures the syntax.

So you don't need to use BOOT yourself. Write new functionality in LISP
or in whatever you like. Document BOOT.

> Writing Boot to generate Lisp is like writing Fortran to generate Aldor.

Hmm, I would rather believe it is like "writing Aldor to generate Fortran".

Or do you want to say that BOOT is in some sense "lower level" than 
LISP? Or are you speaking of expressibility? If BOOT allows include or 
call LISP routines then I would claim, the expressibility issue is a 
non-issue.

> If you are a Fortran programmer you won't see why that's a problem.

If a Fortran programmer uses Fortran to generate Aldor programs, I
believe that the output only uses a subset of Aldor and that
mathematical ideas that can easily be expressed in Aldor are invisible
in the fortran code as well as missing from the generated Aldor code.

> If you are an Aldor programmer you can't imagine why that isn't a problem.

I am an Aldor programmer and I don't see a problem with Fortran
programmers generating Aldor. That's not the point. I would simply guess
that it is much harder to program in fortran something as complex as
Aldor's LibAlgebra. I would even bet that the code would be much longer.
And not only the code. There would be more need to explain the tricks in
human readable form.

> But you can't make Fortran programmers into Aldor programmers.
> They have to want to learn.

Agreed. But I also fail to convince LISP programmers to "want to learn"
Aldor.

>> If I now start a branch and convert Axiom to Haskell,
>> or Assembler would you object?

> Nope. It's your time. If you want to rewrite 23 years worth of work
> into another language, go for it.

Thank you.

>> Would you be interested?

> Nope.

Can you believe that there are people who are not interested in a
LISP-only Axiom?

> The "human readable" language is English.

I haven't count, but there is quite a whole crowd of people who rather
speak Chinese than English. All they can do with an (english) literate
program is to read the source code. Let's hope they are fluent in LISP.

> I'm focused on getting the interpreter, compiler, and other internal
> machinery into a clean, uniform, literate form in one already existing
> language. My focus is on organizing and explaining what is already there.

Yes, go for it. But don't oppose to people who don't want to read
lengthy LISP code with or without documentation.

\start
Date: Sun, 12 Aug 2007 00:49:34 +0200
From: Ralf Hemmecke
To: Tim Daly
Subject: Re: bootstrap Meta/Boot

On 08/10/2007 05:17 PM, Tim Daly wrote:
> Tim wrote:
>>> Fortunately in the brave new world we seem to inhabit, there is no
>>> sticking place for your objection. You can create your own branch and
>>> thus recontruct Meta in Meta and Boot in Boot.
> 
> Ralf wrote:
>> And whoever wants to rewrite everything in LISP should create a new
>> branch and write Axiom in Common Lisp so that on the list
>>
>> http://wiki.axiom-developer.org/AxiomProgramming
>>
>> *only* LISP remains No BOOT, no SHOE, no SPAD.
> 
> In fact, I created a whole project with that almost that subgoal.
> The project is on sourceforge and savannah. The work has traditionally
> involved rewriting only in Common Lisp and Spad. I've been at it for
> years now.
> 
> Tim

OK. Why do you think it is a bad goal to move existing boot/shoe into 
something more spad-like? Also in that direction boot could be 
eliminated. You only prefer LISP because you are more fluent in it an 
because you seem to be able to read generated LISP code.

You have probably realised that not everyone agrees with removing BOOT 
in favour of its generated LISP parts. Removing BOOT might be a goal. 
The question is whether it should be replaced by LISP or SPAD.

Happy fighting. ;-)

\start
Date: Sun, 12 Aug 2007 11:29:09 -0400
From: Bill Page
To: Ralf Hemmecke
Subject: re: bootstrap Meta/Boot

On 8/11/07, Ralf Hemmecke wrote:
> On 08/10/2007 05:17 PM, Tim Daly wrote:
> > Tim wrote:
> >>> Fortunately in the brave new world we seem to inhabit, there is no
> >>> sticking place for your objection. You can create your own branch and
> >>> thus recontruct Meta in Meta and Boot in Boot.
> >
> > Ralf wrote:
> >> And whoever wants to rewrite everything in LISP should create a new
> >> branch and write Axiom in Common Lisp so that on the list
> >>
> >> http://wiki.axiom-developer.org/AxiomProgramming
> >>
> >> *only* LISP remains No BOOT, no SHOE, no SPAD.
> >
> > In fact, I created a whole project with that almost that subgoal.
> > The project is on sourceforge and savannah. The work has traditionally
> > involved rewriting only in Common Lisp and Spad. I've been at it for
> > years now.
> >
> > Tim
>
> OK. Why do you think it is a bad goal to move existing boot/shoe into
> something more spad-like? Also in that direction boot could be
> eliminated. You only prefer LISP because you are more fluent in it an
> because you seem to be able to read generated LISP code.
>
> You have probably realised that not everyone agrees with removing BOOT
> in favour of its generated LISP parts. Removing BOOT might be a goal.
> The question is whether it should be replaced by LISP or SPAD.
>
> Happy fighting. ;-)
>
> Ralf
>

Ralf,

I agree 100% with you. Removing BOOT *could* be a goal, but I
definitely would choose the SPAD option over LISP any day. In fact as
I understand it and as has been stated by some of the original Axiom
developers on this list, this was exactly the goal of the original
ScratchPad developers. Apparently Aldor was just another (big) step in
this direction.

\start
Date: Sun, 12 Aug 2007 08:50:12 -0700 (PDT)
From: Cliff Yapp
To: Bill Page, Ralf Hemmecke
Subject: re: bootstrap Meta/Boot

--- Bill Page wrote:

> Ralf,
> 
> I agree 100% with you. Removing BOOT *could* be a goal, but I
> definitely would choose the SPAD option over LISP any day. In fact as
> I understand it and as has been stated by some of the original Axiom
> developers on this list, this was exactly the goal of the original
> ScratchPad developers. Apparently Aldor was just another (big) step
> in this direction.

I don't understand why people are still arguing about this.  Some of us
clearly are choosing the lisp approach, and some of us are clearly
opposed to it - both sides to the point where they are willing to haul
their own freight, so to speak.  Code speaks louder than words.  In a
couple of days I hope to put up my first draft of asdf-literate on the
Axisp branch website.  Insofar as I am able, I will be doing my part to
help the Lisp camp.

Does anyone actually think further debate will achieve anything?  Tim's
original goal was to move in the Lisp direction.  He has stated this
from the beginning of the project, as I understand it.  Has this ever
been unclear?  We have had long debates about this without the Lisp
crowd being swayed away from their course.  If we are moving in
different directions, why are we wasting time trying to drag along
people who want to go in the other direction?

\start
Date: 12 Aug 2007 11:11:13 -0500
From: Gabriel Dos Reis
To: Cliff Yapp
Subject: re: bootstrap Meta/Boot

Cliff Yapp writes:

[...]

| Does anyone actually think further debate will achieve anything?

No.  In fact, this has become a moot point as of today.

\start
Date: Sun, 12 Aug 2007 18:38:27 +0200
From: Juergen Weiss
To: Gabriel Dos Reis
Subject: RE: A curious algebra failure

I just compiled some algebra (INTALG.spad) with tracing
for pmatch and pmatchWithSl. I do not know if this file
is exemplary - but I never got any non nil return values
with the old and the new version of the functions.

So any change to those functions will have only a small
effect at all.

I know that I have a document describing type equivalence
for Scratchpad II. Problem is I cannot find it. :-(.

Regards

Juergen Weiss

Juergen Weiss	  | Universitaet Mainz, Zentrum fuer Datenverarbeitung,
Juergen Weiss| 55099 Mainz, Tel: +49(6131)39-26361, FAX:
+49(6131)39-26407


> -----Original Message-----
> From: Gabriel Dos Reis [mailto:Gabriel Dos Reis]
> Sent: Sunday, August 12, 2007 4:03 PM
> To: Weiss, Juergen
> Cc: list
> Subject: Re: A curious algebra failure
>
> Gabriel Dos Reis writes:
>
> [...]
>
> | | By the way, I think the line must read
> | |
> | |   v:= ASSOC(p,al) => s=rest v and al
> | |                               ====
> | |
> | | this makes much more sense logically and should typecheck with
> | | the   pmatch(s,p) == pmatchWithSl(s,p,[nil])
> |
> |
> | Yes, it typechecks; I just started a new build; I will report back.
> | I like your semantics description and suggested fix better.
>
> It also fails.  But, I believe your suggested fix is the most correct.

\start
Date: Sun, 12 Aug 2007 11:41:47 -0500 (CDT)
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: RE: A curious algebra failure

On Sun, 12 Aug 2007, Weiss, Juergen wrote:

| I just compiled some algebra (INTALG.spad) with tracing
| for pmatch and pmatchWithSl. I do not know if this file
| is exemplary - but I never got any non nil return values
| with the old and the new version of the functions.
| 
| So any change to those functions will have only a small
| effect at all. 

OK, many thanks. 

I'll try to look for the break somewhere else.

| I know that I have a document describing type equivalence
| for Scratchpad II. Problem is I cannot find it. :-(.

I'm highly interested in that paper when you find it :-)

\start
Date: Sun, 12 Aug 2007 11:31:48 -0700
From: Ed Borasky
To: Cliff Yapp
Subject: re: bootstrap Meta/Boot

C Y wrote:
> --- Ed Borasky wrote:
> 
>> I may have that buried somewhere -- at one point I acquired just
>> about everything I could on Forth, and I never threw it away. What
>> was the title/author/date? A couple of other paths:
> 
> The papers, which I can't find:
> http://portal.acm.org/citation.cfm?id=59413.59435
> http://portal.acm.org/citation.cfm?id=59413.59429

I don't have these in print, but they are both from the Journal Of Forth
Applications Research (JFAR). It used to be in Rochester, NY, but
appears to have found a home on line at

http://dec.bournemouth.ac.uk/forth/jfar/index.html

Unfortunately, what's on line there for volume 5 is completely different
from what you are looking for. :(

Places you can try:

1. The University of Rochester in Rochester, NY. Their library probably
has copies, since it was there in 1988 when the papers were published.

2. The Forth Archive on Taygeta (http://www.taygeta.com/forth.html) ...
seems to be down/not responding at the moment :(

3. Mountain View Press (http://www.theforthsource.com) ... also seems to
be down

4. Forth Interest Group (http://www.forth.org) ... ditto down ... must
be something icky going on in the Bay Area Forth community -- they may
be sharing a server, although I thought Taygeta was in Monterey.

5. Forth, Inc. undoubtedly has copies in their library, since the head
of the company, Elizabeth Rather, was the second Forth programmer. :)

Or just ask on comp.lang.forth -- perhaps the original authors still
hang out there or someone there has a copy.

Incidentally, I "do" have Dick Pountain's "Object-Oriented Forth", which
is probably as good a reference for implementing other languages on a
Forth base as you're likely to find anywhere. If you're in the mood to
re-invent a wheel or two, I'd recommend starting there.


>> 1. I think the HP 28 / 48 / 49 series of calculators' RPL (Reverse
>> Polish Lisp) might be something to look at. I almost always
>> programmed it in the RPN form rather than the algebraic form,
>> although it supports both. In any case, it's a very elegant language.
> 
> Indeed.  Is there a language definition somewhere for those
> calculators?

I don't know for sure, but there are quite a few books on the HP-48,
especially assembly-language hacking. The 49 series has been completely
re-hosted -- they're not on the ancient 4-bit chip any more -- so they
might not be much use. The primary marketplace for HP and TI CAS-type
calculators these days seems to be for students to study for and use in
the SAT exams, not working mathematicians or engineers. Us folks are
assumed to have (or be able to build) better tools. :)

\start
Date: Sun, 12 Aug 2007 12:46:14 -0700
From: Ed Borasky
To: list
Subject: A plea for sanity, forks, Sage, Axiom, Fricas, Open-Axiom, Changelogs, etc.
Cc: William Stein, Gabriel Dos Reis

First of all, I'm "just a user" -- a working programmer/applied
mathematician (45 years and counting.) I've been doing this since
*before* ScratchPad. Perhaps some of you have heard of FORMAC? I was
working at IBM in Poughkeepsie, NY, when Jean Sammet and her colleagues
released it! And I was there when Aden Falkoff and Ken Iverson built
APL\360. So in terms of Tim Daly's "30-year horizon", I've got about 15
extra years. :)

Here's a quote from the Axiom "readme" (Silver Edition, downloaded with
"git" last night, successfully compiled, but crashed trying to do a plot):

"NAG agreed to release Axiom as free software. The basic motivation was
that Axiom represents something different from other programs in a lot
of ways. Primarily because of its foundation in mathematics the Axiom
system will potentially be useful 30 years from now.  In its current
state it represents about 30 years and 300 man-years of research
work. To strive to keep such a large collection of knowledge alive
seems a worthwhile goal.

"However, keeping Axiom alive means more than just taking the source
code and dumping it onto a public server. There are a lot of things
about the system that need to change if it is going to survive and
thrive for the next 30 years.

"The system is complex and difficult to build. There are few people who
know how it is structured and why it is structured that way. Somehow
it needs to be documented deeply so others can contribute.

"The mathematics is difficult. Unlike other free software you can't
just reach for the old saying ``read the source code''.  The source
code is plain, clear and about as close to the mathematical theory as
is practical. Unfortunately the mathematical theory is enshrined in
some research library where few people will have access. Somehow this
must change. The research work, the mathematics, the published papers,
and the source code have all got to be kept together for the next
generation to read, understand and modify.

"The mathematics is narrow and very focused. This was due to the fact
that, while Axiom is a great research platform, we only had a limited
number of visitors at IBM Research. So there is very little in the way
of, say, infinite group theory in Axiom. We can add it. Doing so will
show up shortcomings in the system.  For example, how do you represent
an infinite object? There are many possible representations and they
depend on your goals. The system will have to change, expand, and,
hopefully, become cleaner as more thought is applied. Scratchpad
changed continuously while it was being used for research and we
expect Axiom to do the same.

"The language (spad and/or aldor) is designed to let you write
algorithms that are very close to the mathematics. However, the
algorithms as presented in the current system have never been shown or
proven (an important distinction) to be correct.  It is vital that we
undertake the huge effort of verifying and validating the code. How
else can we trust the results and of what use is a system this complex
without trust? Somehow we have to extend the system to integrate
program proof techniques.  That is, we have to make computational
mathematics hold to the same standard as the rest of mathematics.

"All of which seems to integrate into a requirement for better
documentation. The key change which developers of Axiom will find with
this version is that the documentation is primary and the code is
secondary. Taking direction from Knuth and Dijkstra the system is now
in a literate programming style. The hope is that the next generation
of developers and users will be able to understand, maintain and
extend the system gracefully. And that eventually papers submitted to
journals (an Axiom Journal?) will be easily imported into the system
with their running code made available automatically.

"There is no guarantee that this attempt to change the culture of
computational mathematicians is going to succeed. But it is our firm
belief that current systems have reached a complexity plateau and we
need to find new techniques to push the envelope.

"In general, we need to consider changes to the system with a 30 year
horizon rather than the current write-ship-debug mentality of software
development. This is, after all, mathematics, the queen of the
sciences. It deserves all of the time, talent and attention we can
bring to bear on the subject."

Tim Daly -- September 3, 2002

OK ... that's Tim Daly's dream. Let's have a look at William Stein's dream.

"By far, the primary goal of SAGE is to create a viable high-quality
practical alternative to Magma, Maple, Mathematica, and Matlab as soon
as possible using existing open source components when practical."

As long as we're on the subject of dreams, if you're interested in (one
of) mine, you can read it at
http://viewvc.rubyforge.mmmultiworks.com/cgi/viewvc.cgi/Rameau/Rameau.pdf?revision=1.1&root=cougar

In short, then, I think we're all trying to do the same thing -- hand
some kind of usable legacy of what I think are three golden ages of
scientific computing:

* the late 1950s -- early 1960s,
* the 1980s, and
* the Gnu/Linux period of today

on to the next two or three generations. (As an aside, maybe it's four
golden ages -- Babbage did achieve some measure of success with his
difference engine, after all, as did Lewis Fry Richardson with a room
full of people integrating PDEs on mechanical desk calculators.)

But as Tim pointed out, there's a lot of work to do, and in the past few
weeks, I've seen an awful lot of complaining go by, *two* forks of Axiom
(or is it three??), and lots of arguments about how a large project
should be "managed" or "led" -- neither term seems particularly
appropriate for what I've seen from the point of view of a user.

So ... can we all just take a step back? Can we agree to "disagree
without being disagreeable?" Can we somehow build all of our dreams --
Axiom, Sage, Rameau, etc.? The way things stand now, I can't tell
whether the torch is being passed to shed light or to burn down a village.

"If we build them, they will come!"

And with that, I'm off to pursue another one of my dreams -- being
gainfully employed in scientific computing for 50 years. :)

\start
Date: Sun, 12 Aug 2007 15:51:21 -0500
From: Tim Daly
To: Ed Borasky
Subject: silver edition plot failure

> (Silver Edition, downloaded with "git" last night, successfully 
> compiled, but crashed trying to do a plot):

I'm concerned about this crash. Can you send me the exact line you
typed that caused the error?

I run a test suite on hyperdoc and graphics by hand to ensure that
they both work before I do a commit. I have the last 5 branch builds
available here and all the tests I run work. Clearly I'm missing
something. Sorry about that.

\start
Date: Sun, 12 Aug 2007 14:03:53 -0700 (PDT)
From: Cliff Yapp
To: Ed Borasky
Subject: re: bootstrap Meta/Boot

--- Ed Borasky wrote:
 
> I don't have these in print, but they are both from the Journal Of
> Forth Applications Research (JFAR). It used to be in Rochester, NY,
> but appears to have found a home on line at
> 
> http://dec.bournemouth.ac.uk/forth/jfar/index.html
>
> Unfortunately, what's on line there for volume 5 is completely
> different from what you are looking for. :(

Yep, that threw me.  Are there two JFARs?

> Places you can try:
> 
> 1. The University of Rochester in Rochester, NY. Their library
> probably has copies, since it was there in 1988 when the papers
> were published.

That's a thought.

> 2. The Forth Archive on Taygeta (http://www.taygeta.com/forth.html)
> ... seems to be down/not responding at the moment :(

Up now.  Sweet, thanks!

> 3. Mountain View Press (http://www.theforthsource.com) ... also seems
> to be down

Back up :).

> 4. Forth Interest Group (http://www.forth.org) ... ditto down ...
> must be something icky going on in the Bay Area Forth community --
> they may be sharing a server, although I thought Taygeta was in
> Monterey.

Looks like they're all functioning now.
 
> 5. Forth, Inc. undoubtedly has copies in their library, since the
> head of the company, Elizabeth Rather, was the second Forth 
> programmer. :)
> 
> Or just ask on comp.lang.forth -- perhaps the original authors still
> hang out there or someone there has a copy.

That's a good idea!  Thanks!

> Incidentally, I "do" have Dick Pountain's "Object-Oriented Forth",
> which is probably as good a reference for implementing other
> languages on a Forth base as you're likely to find anywhere. If
> you're in the mood to re-invent a wheel or two, I'd recommend
> starting there.

Thanks!  I see it's on Amazon for $35 - is that a good price?
 
> >> 1. I think the HP 28 / 48 / 49 series of calculators' RPL (Reverse
> >> Polish Lisp) might be something to look at. I almost always
> >> programmed it in the RPN form rather than the algebraic form,
> >> although it supports both. In any case, it's a very elegant
> language.
> > 
> > Indeed.  Is there a language definition somewhere for those
> > calculators?
> 
> I don't know for sure, but there are quite a few books on the HP-48,
> especially assembly-language hacking. The 49 series has been
> completely re-hosted -- they're not on the ancient 4-bit chip any
> more -- so they might not be much use. The primary marketplace for
> HP and TI CAS-type calculators these days seems to be for students
> to study for and use in the SAT exams, not working mathematicians or
> engineers. Us folks are assumed to have (or be able to build) better
> tools. :)

I dunno - despite the availability of CASs for years now, a lot of
folks see to be reluctant to give up their HP calculators ;-).  I
wonder why someone doesn't re-create the HP-48 - that seems to be a
sweet spot in calculator history.

\start
Date: Sun, 12 Aug 2007 17:51:11 -0400
From: William Sit
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

Bill Page and I have a discussion on "has" and "with" on

http://wiki.axiom-developer.org/SandBoxCategories

but the changes/emails seem not to have been sent out yet.

\start
Date: Sun, 12 Aug 2007 14:58:14 -0700
From: Ed Borasky
To: Tim Daly
Subject: Re: silver edition plot failure

Tim Daly wrote:
> Ed,
> 
>> (Silver Edition, downloaded with "git" last night, successfully 
>> compiled, but crashed trying to do a plot):
> 
> I'm concerned about this crash. Can you send me the exact line you
> typed that caused the error?
> 
> I run a test suite on hyperdoc and graphics by hand to ensure that
> they both work before I do a commit. I have the last 5 branch builds
> available here and all the tests I run work. Clearly I'm missing
> something. Sorry about that.

What I did was:

1. Download and build Axiom.
2. Start Axiom.
3. In Hyperdoc, go to the Draw menu, pick "A Parametrically Defined
Tube", "Continue", "Do It".

It crashed on some kind of permission problem -- it wasn't able to write
"gazonk0" dot something in /tmp. I just tried to reproduce it, and it
looks like it's working now. So it was probably some kind of environment
problem (Gentoo Linux, testing level, amd64 dual core with 4 GB.)

I've been having a number of other problems on this system recently -- I
got ambitious and tried to bring it up to GCC 4.2 and enough stuff broke
that I had to spend two days rebuilding everything back to GCC 4.1.2.

So I'm on the air now. I used to have a few things in Hyperdoc that
broke with permissions issues, but I haven't had a chance to do much
with Axiom until this weekend, and I assume they've been fixed. I pretty
much only use Hyperdoc at the moment.

I bought the paper book and have worked through some simple cases but
haven't had a chance to really use Axiom for real work, which in my case
is continuous and discrete time Markov, semi-Markov and generalized
stochastic Markov processes associated with computer and communications
systems modeling. Once I get my other big project going -- profiling the
Ruby interpreter -- I'll be getting back to the Markov stuff.

Most people are doing these things numerically, and almost all of the
usable codes are "academic licensed" -- freely interchangeable amongst
universities but expensive as all get-out in a commercial environment.
So I can't, as I noted on (I think) the Sage list, get something working
at home and take it into my workplace.

But this is really a mixed symbolic and numerical application, involving
matrices (sparse and huge at times), Laplace transforms, Kronecker
products, data structures, partial differential and integral equations,
and a few other things. To do it right, you need a very-high-level
mathematical language like Axiom, and you need "literate programming" or
"reproducible research" for the documentation.

\start
Date: Sun, 12 Aug 2007 18:00:40 -0400
From: Bill Page
To: William Sit
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

On 8/12/07, William Sit wrote:
> Bill Page and I have a discussion on "has" and "with" on
>
> http://wiki.axiom-developer.org/SandBoxCategories
>
> but the changes/emails seem not to have been sent out yet.
>

William,

I have been receiving the email notices of your changes because I was
subscribed directly to the 'SandBoxCategories' page but other people
who might be subscribed only to the Axiom Wiki as a whole will not
receive notices of changes to page with names having the "SandBox..."
prefix by default.

If you prefer, now that we have this page nearly finished we could
rename it to remove the SandBox prefix, then all subscribers would be
notified of any further changes.

\start
Date: Sun, 12 Aug 2007 17:02:18 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Sun, 12 Aug 2007, Bill Page wrote:

| If you prefer, now that we have this page nearly finished we could
| rename it to remove the SandBox prefix, then all subscribers would be
| notified of any further changes.

That would be great!

\start
Date: Sun, 12 Aug 2007 18:10:55 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

On 8/12/07, Gabriel Dos Reis wrote:
> On Sun, 12 Aug 2007, Bill Page wrote:
>
> | If you prefer, now that we have this page nearly finished we could
> | rename it to remove the SandBox prefix, then all subscribers would be
> | notified of any further changes.
>
> That would be great!
>

Ok, now please refer to the page:

http://wiki.axiom-developer.org/AnonymousCategories

\start
Date: Sun, 12 Aug 2007 17:16:06 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Gabriel Dos Reis wrote:
| > On Sun, 12 Aug 2007, Bill Page wrote:
| >
| > | If you prefer, now that we have this page nearly finished we could
| > | rename it to remove the SandBox prefix, then all subscribers would be
| > | notified of any further changes.
| >
| > That would be great!
| >
| 
| Ok, now please refer to the page:
| 
| http://wiki.axiom-developer.org/AnonymousCategories

\start
Date: Sun, 12 Aug 2007 15:23:36 -0700
From: Ed Borasky
To: Cliff Yapp
Subject: re: bootstrap Meta/Boot

C Y wrote:
>> Incidentally, I "do" have Dick Pountain's "Object-Oriented Forth",
>> which is probably as good a reference for implementing other
>> languages on a Forth base as you're likely to find anywhere. If
>> you're in the mood to re-invent a wheel or two, I'd recommend
>> starting there.
> 
> Thanks!  I see it's on Amazon for $35 - is that a good price?

New or used? If you're looking for used, try "addall.com" -- they hit
all of the used booksellers.


> I dunno - despite the availability of CASs for years now, a lot of
> folks see to be reluctant to give up their HP calculators ;-).  I
> wonder why someone doesn't re-create the HP-48 - that seems to be a
> sweet spot in calculator history.

As far as I know from a CAS perspective, the current HP-49 is upward
compatible at the RPL level from the 48, though not at the assembly
level. As far as re-creating the HP-48, I haven't heard anyone else ask
for that, but there *is* a mighty band of folks who would like to see
the HP-15C (scientific equivalent of the HP-12) re-created.

I sort of collect calculators -- I have a TI Voyage 200, TI 89 Platinum,
HP 49 and an HP-12 Platinum at the moment. Somewhere I have a TI SR-52
as well from long ago. The one I carry around in my pocket is the HP-12,
and the one I use at my desk is the HP-49. And both of the TIs have a
bug in their differentiator -- they get the derivative of 1/(1 - u^m)
wrt u as some ghastly expression involving natural logs and hyperbolic
sines, while Axiom (and everybody else) gives it as

               m - 1
            m u
   (1)  ---------------
          m 2     m
        (u )  - 2u  + 1
                                                     Type: Expression
Integer

wxMaxima:

(%i1) 1/(1-u^m);
(%o1) 1/(1-u^m)
(%i2) diff(%o1, u);
(%o2) (m*u^(m-1))/(1-u^m)^2

I can't do it on the HP-49 -- it's at work. But the last time I did it,
it got the same answer.

Just on the off chance you're wondering, "u" is utilization, "m" is the
number of processors, and the expression is the approximate relative
response time (stretch factor) for a processor-bound job. That is, if
one such job takes one second on a uniprocessor with zero utilization
(otherwise idle machine), a large collection of such jobs takes on the
average 1/(1-u^m) seconds each on an m-processor machine with a
utilization of u. And the derivative is of course simply how fast the
stretch factor grows as utilization increases.

Hopefully this won't be on the SAT if students use a TI calculator. ;)

\start
Date: Mon, 13 Aug 2007 00:35:46 +0200
From: Juergen Weiss
To: Gabriel Dos Reis, Bill Page
Subject: RE: "has" and "with" (was curious algebra failure)

I found the old document about type equivalence in Scratchpad. It's:
A New Algebra System, May, 29 th 1984, James H Davenport. I have only
found a paper version. Maybe someone has an online version.

It states that:
1. Two named types are only equivalent if the names are the same.
2. Anonymous types are equivalent when stucturally equivalent
3. An anonymous type is never equivalent to a named type.

So following 1.

t1 == List Term
t2 == List Term
x : t1
y : t2
y := x     

is not supposed to work,

but following 2.

x : List Term
y : List Term
y := x   

is ok,

and following 3.

t == List Term
x : List Term
y : t
y := x  

is not supposed to work as well

All examples are taken from the paper.

I am not sure how much of this design is preserved in the current
system. But without having had an intense look at the examples,
I got the impression, that they follow the rules above.

Regards

Juergen Weiss

Juergen Weiss	  | Universitaet Mainz, Zentrum fuer Datenverarbeitung,
Juergen Weiss| 55099 Mainz, Tel: +49(6131)39-26361, FAX:
+49(6131)39-26407


> -----Original Message-----
> From: axiom-developer-bounces+weiss=uni-mainz.de@nongnu.org
>  On Behalf Of Gabriel Dos Reis
> Sent: Monday, August 13, 2007 12:16 AM
> To: Bill Page
> Cc: list
> Subject: Re: "has" and "with" (was curious
> algebra failure)
>
> On Sun, 12 Aug 2007, Bill Page wrote:
>
> | On 8/12/07, Gabriel Dos Reis wrote:
> | > On Sun, 12 Aug 2007, Bill Page wrote:
> | >
> | > | If you prefer, now that we have this page nearly
> finished we could
> | > | rename it to remove the SandBox prefix, then all
> subscribers would be
> | > | notified of any further changes.
> | >
> | > That would be great!
> | >
> |
> | Ok, now please refer to the page:
> |
> | http://wiki.axiom-developer.org/AnonymousCategories

\start
Date: Sun, 12 Aug 2007 18:56:51 -0400
From: William Sit
To: Bill Page,William Sit
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

Ah, of course (SandBox), stupid me!
Thanks for "upgrading" the page.

Now I wonder if I should remove my wrong conjecture on 
"has" has higher precedence. What do you think (as a 
general principle, should wrong explanations be removed)?

William

On Sun, 12 Aug 2007 18:00:40 -0400
  Bill Page wrote:
>other people
>who might be subscribed only to the Axiom Wiki as a whole 
>will not
>receive notices of changes to page with names having the 
>"SandBox..."
>prefix by default.

\start
Date: Sun, 12 Aug 2007 18:13:16 -0500 (CDT)
From: Gabriel Dos Reis
To: Juergen Weiss
Subject: RE: "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, Weiss, Juergen wrote:

| I found the old document about type equivalence in Scratchpad. It's:
| A New Algebra System, May, 29 th 1984, James H Davenport. I have only
| found a paper version. Maybe someone has an online version.
| 
| It states that:
| 1. Two named types are only equivalent if the names are the same.
| 2. Anonymous types are equivalent when stucturally equivalent
| 3. An anonymous type is never equivalent to a named type.
| 
| So following 1.
| 
| t1 == List Term
| t2 == List Term
| x : t1
| y : t2
| y := x      
| 
| is not supposed to work,
| 
| but following 2.
| 
| x : List Term
| y : List Term
| y := x    
| 
| is ok,
| 
| and following 3.
| 
| t == List Term
| x : List Term
| y : t
| y := x   
| 
| is not supposed to work as well
| 
| All examples are taken from the paper.
| 
| I am not sure how much of this design is preserved in the current
| system. But without having had an intense look at the examples,
| I got the impression, that they follow the rules above.

Many thanks for digging up the archive.

I understand the above is about "type equivalence"; how about matching?
That is, which way do you think the checking of the  code in Monad should 
go according to that paper? 

\start
Date: Sun, 12 Aug 2007 19:18:36 -0400
From: Bill Page
To: William Sit
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

On 8/12/07, William Sit wrote:
>
> Ah, of course (SandBox), stupid me!
> Thanks for "upgrading" the page.
>

Don't worry. Editing and correcting it first as a SandBox page and
then renaming it is often the best way.

> Now I wonder if I should remove my wrong conjecture on
> "has" has higher precedence. What do you think (as a
> general principle, should wrong explanations be removed)?
>

Well, it's up to you but I would suggest maybe leave it a while in
case your thoughts about this trigger comments from other readers.
Later after readers have had a chance to make their own comments you
can "clean it up" if you like so that it represents the correct or at
least consensus opinion.

In general I would only remove "wrong explanations" if they could be
misleading and are not identified as such.

Thanks for your work on this!

\start
Date: Sun, 12 Aug 2007 19:43:51 -0400
From: William Sit
To: Juergen Weiss
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

The question is not so much whether the rules are followed as to *when* a
type (domain and category, perhaps even package) becomes named. Note that
the examples given in Davenport are for domains, not categories. Are there
differences in handling between named domains and named categories? unnamed
domains and unnamed categories?

(6) -> x:List Integer:=[1,2,3]

   (6)  [1,2,3]
--- assume that in (6), List Integer is unnamed.
                                                 Type: List Integer
(7) -> y:List Integer:=x

   (7)  [1,2,3]
--- so is (7)
                                                          Type: List
Integer
(8) -> t == List Integer
                                                                   Type:
Void
--- assume that (8) is named
(9) -> z:t:=x

   t is not a valid type.
--- what does this error message mean?
(9) -> t ==> List Integer
                                                                   Type:
Void
--- is (9) named or not? According to compiler output, a macro is
--- handled in the same way as a function definition. (see
--- http://wiki.axiom-developer.org/AnonymousCategories/diff )

(10) -> z:t:=x

   (10)  [1,2,3]
--- looks like (9) is unnamed?
                                                           Type: List
Integer
(11) -> s:=List Integer

   (11)  List Integer
---  (11) should be considered named?
                                                              Type: Domain
(12) -> w:s:=x

   (12)  [1,2,3]
--- but it works just like unnamed?

There is also the complication that the above is done via the interpreter.

William

"Weiss, Juergen" wrote:

> I found the old document about type equivalence in Scratchpad. It's:
> A New Algebra System, May, 29 th 1984, James H Davenport. I have only
> found a paper version. Maybe someone has an online version.
>
> It states that:
> 1. Two named types are only equivalent if the names are the same.
> 2. Anonymous types are equivalent when stucturally equivalent
> 3. An anonymous type is never equivalent to a named type.
>
> So following 1.
>
> t1 == List Term
> t2 == List Term
> x : t1
> y : t2
> y := x
>
> is not supposed to work,
>
> but following 2.
>
> x : List Term
> y : List Term
> y := x
>
> is ok,
>
> and following 3.
>
> t == List Term
> x : List Term
> y : t
> y := x
>
> is not supposed to work as well
>
> All examples are taken from the paper.
>
> I am not sure how much of this design is preserved in the current
> system. But without having had an intense look at the examples,
> I got the impression, that they follow the rules above.

\start
Date: Sun, 12 Aug 2007 20:26:05 -0400
From: Bill Page
To: William Sit
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

On 8/12/07, William Sit wrote:
> The question is not so much whether the rules are followed as to *when* a
> type (domain and category, perhaps even package) becomes named. Note
> that the examples given in Davenport are for domains, not categories. Are
> there differences in handling between named domains and named categories?
> unnamed domains and unnamed categories?

Of course in principle both domains and categories are supposed to be
treated equally as 'types' - at least in Aldor this is true.

>
> (6) -> x:List Integer:=[1,2,3]
>
>    (6)  [1,2,3]
> --- assume that in (6), List Integer is unnamed.
>                                                  Type: List Integer
> ...
> There is also the complication that the above is done via the interpreter.
>

I do not think it is possible to test this in the Axiom interpreter
because it's support of types as first class values is highly
deficient. But I took a try at this using Spad. See Juergen's examples
here:

http://wiki.axiom-developer.org/SandBoxCategories

I think this demonstrate that Davenport's rules are implemented in Spad.

\start
Date: Sun, 12 Aug 2007 19:28:34 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, William Sit wrote:
| > The question is not so much whether the rules are followed as to *when* a
| > type (domain and category, perhaps even package) becomes named. Note
| > that the examples given in Davenport are for domains, not categories. Are
| > there differences in handling between named domains and named categories?
| > unnamed domains and unnamed categories?
| 
| Of course in principle both domains and categories are supposed to be
| treated equally as 'types' - at least in Aldor this is true.
| 
| >
| > (6) -> x:List Integer:=[1,2,3]
| >
| >    (6)  [1,2,3]
| > --- assume that in (6), List Integer is unnamed.
| >                                                  Type: List Integer
| > ...
| > There is also the complication that the above is done via the interpreter.
| >
| 
| I do not think it is possible to test this in the Axiom interpreter
| because it's support of types as first class values is highly
| deficient. But I took a try at this using Spad. See Juergen's examples
| here:
| 
| http://wiki.axiom-developer.org/SandBoxCategories
| 
| I think this demonstrate that Davenport's rules are implemented in Spad.

So, how do you think the original example (Monad using expt$RepeatedSquare(%)) 
should behave according to those rules?

\start
Date: Sun, 12 Aug 2007 20:32:04 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

On 8/12/07, Gabriel Dos Reis wrote:
> On Sun, 12 Aug 2007, Bill Page wrote:
> | ...
> | http://wiki.axiom-developer.org/SandBoxCategories
> |
> | I think this demonstrate that Davenport's rules are implemented in Spad.
>
> So, how do you think the original example (Monad using expt$RepeatedSquare(%))
> should behave according to those rules?
>

It should be fine because of rule 2:

2. Anonymous types are equivalent when structurally equivalent

\start
Date: Sun, 12 Aug 2007 19:35:57 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Gabriel Dos Reis wrote:
| > On Sun, 12 Aug 2007, Bill Page wrote:
| > | ...
| > | http://wiki.axiom-developer.org/SandBoxCategories
| > |
| > | I think this demonstrate that Davenport's rules are implemented in Spad.
| >
| > So, how do you think the original example (Monad using expt$RepeatedSquare(%))
| > should behave according to those rules?
| >
| 
| It should be fine because of rule 2:
| 
| 2. Anonymous types are equivalent when structurally equivalent

The parameter S in RepeatedSquare(S) of the category

   SetCategory with "*": (%,%) -> %

but RepeatedSquare is being called with a domain of a named category (Monad).
Rule 2 says:

  2. Anonymous types are equivalent when stucturally equivalent

How would it apply?

\start
Date: Sun, 12 Aug 2007 21:14:51 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

On 8/12/07, Gabriel Dos Reis wrote:
> On Sun, 12 Aug 2007, Bill Page wrote:
> | ...
> | It should be fine because of rule 2:
> |
> | 2. Anonymous types are equivalent when structurally equivalent
>
> The parameter S in RepeatedSquare(S) of the category
>
>    SetCategory with "*": (%,%) -> %
>
> but RepeatedSquare is being called with a domain of a named category (Monad).
> Rule 2 says:
>
>   2. Anonymous types are equivalent when stucturally equivalent
>
> How would it apply?
>

Why do you think:

     import RepeatedSquaring(%)

is referring to a named category? Let it refer to the category-value,
not it's name.

\start
Date: Sun, 12 Aug 2007 20:19:47 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Sun, 12 Aug 2007, Bill Page wrote:

| On 8/12/07, Gabriel Dos Reis wrote:
| > On Sun, 12 Aug 2007, Bill Page wrote:
| > | ...
| > | It should be fine because of rule 2:
| > |
| > | 2. Anonymous types are equivalent when structurally equivalent
| >
| > The parameter S in RepeatedSquare(S) of the category
| >
| >    SetCategory with "*": (%,%) -> %
| >
| > but RepeatedSquare is being called with a domain of a named category (Monad).
| > Rule 2 says:
| >
| >   2. Anonymous types are equivalent when stucturally equivalent
| >
| > How would it apply?
| >
| 
| Why do you think:
| 
|      import RepeatedSquaring(%)
| 
| is referring to a named category?

I'm not saying that.  

I'm saying that the parameter S of the default package Monad& -- generated for
the default implementation of the category Monad -- is of the named category
Monad.  It is that parameter S which is  being used to instantiate
RepeatedSquaring.  However, RepeatedSquaring expects its (domain) argument to
be of the unnamed category 

   SetCategory with "*": (%,%) -> %

\start
Date: Sun, 12 Aug 2007 21:40:53 -0400
From: William Sit
To: Gabriel Dos Reis,Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Sun, 12 Aug 2007 20:19:47 -0500 (CDT)
  Gabriel Dos Reis wrote:
>On Sun, 12 Aug 2007, Bill Page wrote:
>
>| On 8/12/07, Gabriel Dos Reis wrote:
>| > On Sun, 12 Aug 2007, Bill Page wrote:
>| > | ...
>| > | It should be fine because of rule 2:
>| > |
>| > | 2. Anonymous types are equivalent when structurally 
>equivalent
>| >
>| > The parameter S in RepeatedSquare(S) of the category
>| >
>| >    SetCategory with "*": (%,%) -> %
>| >
>| > but RepeatedSquare is being called with a domain of a 
>named category (Monad).
>| > Rule 2 says:
>| >
>| >   2. Anonymous types are equivalent when stucturally 
>equivalent
>| >
>| > How would it apply?
>| >
>| 
>| Why do you think:
>| 
>|      import RepeatedSquaring(%)
>| 
>| is referring to a named category?
>
>I'm not saying that.  
>
>I'm saying that the parameter S of the default package 
>Monad& -- generated for
>the default implementation of the category Monad -- is of 
>the named category
>Monad.  It is that parameter S which is  being used to 
>instantiate
>RepeatedSquaring.  However, RepeatedSquaring expects its 
>(domain) argument to
>be of the unnamed category 
>
>    SetCategory with "*": (%,%) -> %
>
>-- Gaby

Isn't the problem whether 'Monad has SetCategory with 
"*":(%,%)->%' ? My answer would be yes. This should not be 
related to equivalence of categories or domains. We 
already have seen examples that Integer has with 
_*:(Integer, Integer)->Integer. Here, we are not saying 
'Monad is SetCategory with "*":(%,%)->%'.

\start
Date: Sun, 12 Aug 2007 20:48:29 -0500 (CDT)
From: Gabriel Dos Reis
To: William Sit
Subject: Re: "has" and "with" (was curious algebra failure)

On Sun, 12 Aug 2007, William Sit wrote:

| On Sun, 12 Aug 2007 20:19:47 -0500 (CDT)
|  Gabriel Dos Reis wrote:
| >On Sun, 12 Aug 2007, Bill Page wrote:
| >
| > | On 8/12/07, Gabriel Dos Reis wrote:
| > | > On Sun, 12 Aug 2007, Bill Page wrote:
| > | > | ...
| > | > | It should be fine because of rule 2:
| > | > |
| > | > | 2. Anonymous types are equivalent when structurally 
| >equivalent
| > | >
| > | > The parameter S in RepeatedSquare(S) of the category
| > | >
| > | >    SetCategory with "*": (%,%) -> %
| > | >
| > | > but RepeatedSquare is being called with a domain of a 
| >named category (Monad).
| > | > Rule 2 says:
| > | >
| > | >   2. Anonymous types are equivalent when stucturally 
| >equivalent
| > | >
| > | > How would it apply?
| > | >
| > | 
| > | Why do you think:
| > | 
| > |      import RepeatedSquaring(%)
| > | 
| > | is referring to a named category?
| >
| >I'm not saying that.  
| >I'm saying that the parameter S of the default package Monad& -- generated
| >for
| >the default implementation of the category Monad -- is of the named category
| >Monad.  It is that parameter S which is  being used to instantiate
| >RepeatedSquaring.  However, RepeatedSquaring expects its (domain) argument to
| >be of the unnamed category 
| >    SetCategory with "*": (%,%) -> %
| >
| >-- Gaby
| 
| Isn't the problem whether 'Monad has SetCategory with "*":(%,%)->%' ?

If the question is formulated in terms of "has", then I think the answer
is unambiguously "yes".

But, is that the way the compiler is intended or does the matching of
actual arguments with formal parameters?

It seems to me that the compiler asks the question in terms of coercible,
instead of "has".

\start
Date: Mon, 13 Aug 2007 00:50:50 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

Gaby,

On 8/12/07, you wrote:
> On Sun, 12 Aug 2007, William Sit wrote:
>
> | Isn't the problem whether 'Monad has SetCategory with
> | "*":(%,%)->%' ? My answer would be yes. This should not be
> | related to equivalence of categories or domains. We
> | already have seen examples that Integer has with
> | _*:(Integer, Integer)->Integer. Here, we are not saying
> | 'Monad is SetCategory with "*":(%,%)->%'.
>

Sorry for my confusion. In fact I agree with William. This is not
directly related to type equivalence. We need something more general
than type equivalence. We need to know when one category is a
subcategory of another. The type equivalence rules to which Juergen
referred must be applied to the parts of the category expressions in
order to determine this relationship.

You wrote:

> > I'm saying that the parameter S of the default package
> > Monad& -- generated for the default implementation of the
> > category Monad -- is of the named category Monad.  It is
> > that parameter S which is being used to instantiate
> >RepeatedSquaring.  However, RepeatedSquaring expects its
> >(domain) argument to be of the unnamed category
> >
> >    SetCategory with "*": (%,%) -> %

Your statement of the problem is a little confusing to me since the
parameter S is the parameter of RepeatedSquaring. But as you say, it's
type is given by the unnamed category above. You are concerned because
what is being passed to RepeatedSquaring is a domain of type category
named Monad. But clearly a domain of type Monad is also is a member of

   SetCategory with "*": (%,%) -> %

since Monad is a subcategory of this category - any domain that "has"
Monad will necessarily provide all of the exports required by
RepeatedSquaring. RepeatedSquaring requires it's (domain) argument to
be of type that is a subcategory of this unnamed category.

In other words the compiler must check that Monad is a subcategory of
the type of parameter S. To do this it can observe that:

   Monad has SetCategory

(this requires rule 1) and that

 Monad has with "*": (%,%) -> %

(this requires rule 2). Originally I thought you were mostly concerned
about these anonymous parts of the category.

> If the question is formulated in terms of "has", then I think the answer
> is unambiguously "yes".
>
> But, is that the way the compiler is intended or does the matching of
> actual arguments with formal parameters?
>

Of course the compiler must be able to check type correctness at
compile-time while "has" is evaluated at run-time but they are closely
related.

When you call a function like

  f:Integer->Integer

you must pass it a member (object) of the domain Integer. Objects are
members of only one domain.

When you call a package, e.g. RepeatedSquaring you just pass it a
member (domain) of the category

  SetCategory with "*": (%,%) -> %

Unlike objects, domains can be members of many different categories
but certainly any domain that is a member of Monad will also be a
member of this category.

The type of a domain is the smallest category that contains all the
categories of which this domain is a member. Equivalently, a domain of
type category X is a member of all the subcategories of X.

> It seems to me that the compiler asks the question in terms of coercible,
> instead of "has".
>

Perhaps by "coercible" what you mean is just forgetting the extra
structure of the subcategory - just like PositiveInteger is a
subdomain of Integer and coercion of a PostiveInteger to Integer is
"natural" because there is a function which injects every
PositiveInteger into Integer. In the Axiom interpreter was can call
the function +$Integer with an object of type PositiveInteger because
such a coercion exists and the interpreter invokes it automatically.

Similarly is might be possible to say that we can call
RepeatedSquaring with a domain of type Monad because there is a
"coercion" (a forgetful functor) that can inject domains of type Monad
into domains of category

  SetCategory with "*": (%,%) -> %

In fact we can do that simply by striking out those parts of the
category expression for Monad that are not equivalent to any
corresponding part of the above unnamed category. If what we have left
is identical to this category, then we know monad is such a
subcategory.

I guess that is the kind of coercion that is being referred to in the
error message you quoted in your first email in this thread:

>> Apparent user error:
  Cannot coerce S
     of mode (Monad)
     to mode (Join (SetCategory) (CATEGORY domain (SIGNATURE * ($ $ $))))

------

It seems to me that the mode we should expect here is not Monad but
rather it's category-value in which case the coercion is obvious.

\start
Date: 13 Aug 2007 00:28:49 -0500
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

Bill Page writes:

[...]

| > > I'm saying that the parameter S of the default package
| > > Monad& -- generated for the default implementation of the
| > > category Monad -- is of the named category Monad.  It is
| > > that parameter S which is being used to instantiate
| > >RepeatedSquaring.  However, RepeatedSquaring expects its
| > >(domain) argument to be of the unnamed category
| > >
| > >    SetCategory with "*": (%,%) -> %
| 
| Your statement of the problem is a little confusing to me since the
| parameter S is the parameter of RepeatedSquaring. But as you say, it's
| type is given by the unnamed category above. You are concerned because
| what is being passed to RepeatedSquaring is a domain of type category
| named Monad. But clearly a domain of type Monad is also is a member of
| 
|    SetCategory with "*": (%,%) -> %
| 
| since Monad is a subcategory of this category - any domain that "has"
| Monad will necessarily provide all of the exports required by
| RepeatedSquaring. RepeatedSquaring requires it's (domain) argument to
| be of type that is a subcategory of this unnamed category.

Bill, it is getting late so I'll try to give a longer reply later.
I just wanted to say one thing:  We should distinguish the notion of
"being of a member of T" from "being coercible to T" -- as the Spad
language does.  Argument passing in function calls follows the
semantics of  "being coercible to the type of formal parameter".  

\start
Date: Mon, 13 Aug 2007 02:06:33 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

On 13 Aug 2007 00:28:49 -0500, you wrote:
> Bill Page writes:
>
> [...]
>
> | > > I'm saying that the parameter S of the default package
> | > > Monad& -- generated for the default implementation of the
> | > > category Monad -- is of the named category Monad.  It is
> | > > that parameter S which is being used to instantiate
> | > >RepeatedSquaring.  However, RepeatedSquaring expects its
> | > >(domain) argument to be of the unnamed category
> | > >
> | > >    SetCategory with "*": (%,%) -> %
> |
> | Your statement of the problem is a little confusing to me since the
> | parameter S is the parameter of RepeatedSquaring. But as you say, it's
> | type is given by the unnamed category above. You are concerned because
> | what is being passed to RepeatedSquaring is a domain of type category
> | named Monad. But clearly a domain of type Monad is also is a member of
> |
> |    SetCategory with "*": (%,%) -> %
> |
> | since Monad is a subcategory of this category - any domain that "has"
> | Monad will necessarily provide all of the exports required by
> | RepeatedSquaring. RepeatedSquaring requires it's (domain) argument to
> | be of type that is a subcategory of this unnamed category.
>
> Bill, it is getting late so I'll try to give a longer reply later.
> I just wanted to say one thing:  We should distinguish the notion of
> "being of a member of T" from "being coercible to T" -- as the Spad
> language does.  Argument passing in function calls follows the
> semantics of  "being coercible to the type of formal parameter".
>

I was trying to use the terminology in Section 12.5 Membership, of the
Axiom book on category hierarchies and also section 7.6 Type
Conversion, of the Aldor User Guide on the sub-type relation. In
general coercion (or conversion) is used to mean something a little
more "mathematical" in Axiom. In fact 'CoercibleTo' is a category
constructor in Axiom.  For example one might say that Integer is
coercible to Float but that is not the kind of conversion
automatically considered by the Spad compiler.

I look forward to reading your longer reply.

In Spad there is also the subdomain construction that is used to
define PositiveInteger and NonNegativeInteger from Integer. Subdomain
automatically provides "coercible to" the parent domain. This is
something that Spad has that was never implemented in Aldor. We had
some discussions about this a few year ago on this list. I was not
convinced that the concept of subdomain is a dispensible part of the
Spad language - even though it is not currently widely used in the
Axiom library code. I general I want subdomains (and sub-object
classifiers) for the same reason as I want records (products) and
unions (co-products), because this is a step toward a more categorical
semantics for the language.

\start
Date: Mon, 13 Aug 2007 03:38:36 -0400
From: William Sit
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

Gabriel Dos Reis wrote:

> On Sun, 12 Aug 2007, William Sit wrote:
>
> | Isn't the problem whether 'Monad has SetCategory with "*":(%,%)->%' ?
>
> If the question is formulated in terms of "has", then I think the answer
> is unambiguously "yes".
>
> But, is that the way the compiler is intended or does the matching of
> actual arguments with formal parameters?
>
> It seems to me that the compiler asks the question in terms of coercible,
> instead of "has".
>
> -- Gaby

I believe for category parameters, the compiler checks whether the
supplied domain "has" the category, and for domain parameters, the
compiler checks whether the object belongs to the domain, NOT whether
the object is "coercible" to it. I believe coercion is not always
automatic in Spad (but is in the interpreter, even when a domain does
not explicitly have CoercibleTo the target --- see examples in
http://wiki.axiom-developer.org/SandBoxCategories).  The Spad
programmer has to explicitly call a coerce function (and if that does
not exist, define the domain to be CoercibleTo the target domain and
define and call coerce) before passing the object to the routine or
constructor.

Matching of actual arguments with formal parameters does not mean "is"
but means "belongs to". In this sense, if the formal parameter is a
category (or a Join of categories), the actual parameter need to be a
domain in that category (or all of the categories listed in Join); if
the formal parameter is a domain, the actual parameter need to be an
object in that domain.  The question of category equivalence comes in
only when the two formal arguments have the same defined
structures. Then the question of whether a domain "belongs" to the
categories specified depends on how the domain is constructed. If the
formal argument is named, then the domain must be explicitly declared
to belong to that named category to be a valid argument. If the formal
argument is unnamed, or rather, has unnamed components (in the sense
that 'SetCategory with ...' is 'Join(SetCategory, with ...)', where
'SetCategory' is named, and 'with ...' is unnamed), then the unnamed
category may be satisfied if the domain structurally belongs to the
unamed category (there need not be, and cannot be, an explicit
declaration, except in the sense of exported functions).

Similarly, the question of domain equivalence comes in only when two
formal arugments have the same defined structures. Then the question
of whether an object "belongs" to the domain specified depends on
whether the formal argument is named or not. If named, the object must
have been declared to be (and assigned a value from) the said formal
domain argument. If unnamed, the object must also have been declared
to be (and assigned a value from) the said formal domain
argument. Actually, I am not sure if there is such a thing as an
unnamed domain. In Davenport's example, to me, 'List Integer' is
certainly a named domain from domain constructor List. Of course, if
you declare t:SetCategory == List Integer, or t:= List Integer, then
you have renamed the domain and t would not be the same domain as List
Integer for the purpose of compiling Spad. Again, see

http://wiki.axiom-developer.org/SandBoxCategories

for examples.

\start
Date: Mon, 13 Aug 2007 04:15:05 -0400
From: William Sit
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

I think I understand the objection raised by Gaby. In matching Monad to
SetCategory with ..., Axiom is applying a forgetful functor that, given a
monad, forgets all of its operations except those featured in SetCategory with
....   In this sense, applying a forgetful functor is a form of automatic
coercion on the level of categories.  Gaby is correct in saying that strictly
speaking, the forgetful functor should also not be automatic, just like the
usual coercion between domains. In fact, how one forgets the structure of a
ring to the structure of a Monad would be ambiguous, since there are two
possible ways. For more complicated algebraic structures (like Hopf algebra,
differential algebra) if it is possible to specify precisely the forgetful
functor, it would allow us to have only one Monoid structure instead of an
AbelianMonoid and a Monoid (and many others distinguished by different names
for the monoid operation).

Gaby, is that a fair statement?

You may be interested in this old 1986 article by Kamal Abdali et al., on An
Object Oriented Approach to Algebra System Design:

http://portal.acm.org/ft_gateway.cfm?id=32444&type=pdf&coll=GUIDE&dl=ACM

One of the stated features of Views is:

"Views do not depend on operation names. That is, locally (i.e. in their
domains) two different Rings may have different names for their 'additon
operation', but, when viewed as Rings, their addition operation is accessed by
the same identifier."

To allow for such a goal, the compiler will have to be redesigned, as well as
most of the algebra code.


William

Bill Page wrote:

> Gaby,
>
> On 13 Aug 2007 00:28:49 -0500, you wrote:
> > Bill Page writes:
> >
> > [...]
> >
> > | > > I'm saying that the parameter S of the default package
> > | > > Monad& -- generated for the default implementation of the
> > | > > category Monad -- is of the named category Monad.  It is
> > | > > that parameter S which is being used to instantiate
> > | > >RepeatedSquaring.  However, RepeatedSquaring expects its
> > | > >(domain) argument to be of the unnamed category
> > | > >
> > | > >    SetCategory with "*": (%,%) -> %
> > |
> > | Your statement of the problem is a little confusing to me since the
> > | parameter S is the parameter of RepeatedSquaring. But as you say, it's
> > | type is given by the unnamed category above. You are concerned because
> > | what is being passed to RepeatedSquaring is a domain of type category
> > | named Monad. But clearly a domain of type Monad is also is a member of
> > |
> > |    SetCategory with "*": (%,%) -> %
> > |
> > | since Monad is a subcategory of this category - any domain that "has"
> > | Monad will necessarily provide all of the exports required by
> > | RepeatedSquaring. RepeatedSquaring requires it's (domain) argument to
> > | be of type that is a subcategory of this unnamed category.
> >
> > Bill, it is getting late so I'll try to give a longer reply later.
> > I just wanted to say one thing:  We should distinguish the notion of
> > "being of a member of T" from "being coercible to T" -- as the Spad
> > language does.  Argument passing in function calls follows the
> > semantics of  "being coercible to the type of formal parameter".
> >
>
> I was trying to use the terminology in Section 12.5 Membership, of the
> Axiom book on category hierarchies and also section 7.6 Type
> Conversion, of the Aldor User Guide on the sub-type relation. In
> general coercion (or conversion) is used to mean something a little
> more "mathematical" in Axiom. In fact 'CoercibleTo' is a category
> constructor in Axiom.  For example one might say that Integer is
> coercible to Float but that is not the kind of conversion
> automatically considered by the Spad compiler.
>
> I look forward to reading your longer reply.
>
> In Spad there is also the subdomain construction that is used to
> define PositiveInteger and NonNegativeInteger from Integer. Subdomain
> automatically provides "coercible to" the parent domain. This is
> something that Spad has that was never implemented in Aldor. We had
> some discussions about this a few year ago on this list. I was not
> convinced that the concept of subdomain is a dispensible part of the
> Spad language - even though it is not currently widely used in the
> Axiom library code. I general I want subdomains (and sub-object
> classifiers) for the same reason as I want records (products) and
> unions (co-products), because this is a step toward a more categorical
> semantics for the language.

\start
Date: Mon, 13 Aug 2007 10:35:23 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

You have added the Aldor version of the test code to

> | http://wiki.axiom-developer.org/AnonymousCategories

For test3()

     -- QQ is a category-valued constant
     define QQ:Category == with { +:(Integer,Integer)->Integer }
     ttest3():Boolean ==
       Integer has QQ

you say:  -- should be true

I don't agree with that. QQ is a (named) category (which you also could 
have defined outside. Domains belong to categories by assertion. You did 
not say

   extend Integer: QQ == add;

and QQ was not known before, so the aldor compiler is right to produce 
code that returns false.


I have some more comments on this thread.

A with B is (or should be) completely equivalent to:

    with {A; B}

(see Aldor User Guide). And perhaps that is also a hint to the 
named/unamed problem. What appears inside with will be recorded 
internally. Take the following file:

---BEGIN aaa.as
#include "aldor"
define QQ: Category == with {
	PrimitiveType;
	foo: MachineInteger -> ();
}
---END aaa.as

and say

aldor -fasy -laldor aaa.as

What you will get out, looks like

---BEGIN aaa.asy
((|Declare|
     qq
     (|Define|
       (|Declare| (|Label| qq ()) |Category|)
       (|With|
         |PrimitiveType|
         (|Declare|
           |foo|
           (|Apply| -> |MachineInteger| (|Comma|))
           ((|symeNameCode| . 314869119) (|symeTypeCode| . 626472089)))))
     ((|symeNameCode| . 51496308)
       (|symeTypeCode| . 624244337)
       (|catExports|
         (|Declare|
           =
           (|Apply| -> (|Comma| % %) |Boolean|)
           ((|symeNameCode| . 200102) (|symeTypeCode| . 21900315)))
         (|Declare|
           ~=
           (|Apply| -> (|Comma| % %) |Boolean|)
           ((|default| . 1)
             (|symeNameCode| . 51509389)
             (|symeTypeCode| . 21900315)))
         (|Declare|
           %%
           |PrimitiveType|
           ((|default| . 1)
             (|symeNameCode| . 51482908)
             (|symeTypeCode| . 34294859)))
         (|Declare|
           |foo|
           (|Apply| -> |MachineInteger| (|Comma|))
           ((|symeNameCode| . 314869119) (|symeTypeCode| . 626472089)))
         (|Declare|
           %%
           qq
           ((|default| . 1)
             (|symeNameCode| . 51482908)
             (|symeTypeCode| . 1066491663)))))))
(|Sequence|)
---END aaa.asy

Look in particular, inside (|catExports| ...). In addition to all 
exported functions you also find the exported symbol |PrimitiveType|. 
And you also find qq there.

What I believe "has" does, is to look inside the |catExports| and checks 
whether the symbol is there. If you say

   A has QQ

then it is enough to find QQ among the exports. For

   A has with {QQ; foo: () -> (); bar: Integer -> ()}

it has to find QQ and the foo and bar functions with the right signature.

I believe the "define" keyword in the current Aldor compiler has no 
effect. You can compile with and without it and the resulting C code is 
equal to the last bit. (At least in the cases that I have tested.)

Aldor does not allow

   A has "*"
   A has *

or anything else of the form

   A has B

where B is not of type Category. That seems to be different in Axiom, 
but I havent yet felt that this is insufficient.

\start
Date: Mon, 13 Aug 2007 10:39:39 +0200
From: Ralf Hemmecke
To: Juergen Weiss
Subject: Re: "has" and "with" (was curious algebra failure)

---BEGIN aaa.as
#include "aldor"
#include "aldorio"

main(): () == {
	import from Integer;
	T1 == List Integer;
	T2 == List Integer;
	t1: T1 := [1];
	t2: T2 := t1;
	stdout << "t1 = " << t1 << newline;
	stdout << "t2 = " << t2 << newline;

#if DoesntWork
	N1: ListType Integer == List Integer;
	N2: ListType Integer == List Integer;
	n1: N1 := [1];
	n2: N2 := n1;
	stdout << "n1 = " << n1 << newline;
	stdout << "n2 = " << n2 << newline;
#endif
}
main();
---END aaa.as

woodpecker:~/scratch>aldor -laldor -DDoesntWork -fx aaa.as
"aaa.as", line 17:         n2: N2 := n1;
                    ..................^
[L17 C19] #1 (Error) There is no suitable interpretation for the 
expression n1
   The context requires an expression of type N2.
      The possible types of the right hand side (`n1') are:
           -- N1

If you remove "-DDoesntWork" the code compiles and runs fine.
In Aldor T1 and T2 are identical. Constant assignment does not define a 
new type. That is different if you add the type (as is done for N1 and 
N2). The compiler introduces two new domains N1 and N2 which are like 
but different from List Integer.

Maybe that is confusing, but that's the way it is. (And it is sometimes 
useful.)

Ralf

On 08/13/2007 12:35 AM, Weiss, Juergen wrote:
> I found the old document about type equivalence in Scratchpad. It's:
> A New Algebra System, May, 29 th 1984, James H Davenport. I have only
> found a paper version. Maybe someone has an online version.
> 
> It states that:
> 1. Two named types are only equivalent if the names are the same.
> 2. Anonymous types are equivalent when stucturally equivalent
> 3. An anonymous type is never equivalent to a named type.
> 
> So following 1.
> 
> t1 == List Term
> t2 == List Term
> x : t1
> y : t2
> y := x      
> 
> is not supposed to work,
> 
> but following 2.
> 
> x : List Term
> y : List Term
> y := x    
> 
> is ok,
> 
> and following 3.
> 
> t == List Term
> x : List Term
> y : t
> y := x   
> 
> is not supposed to work as well
> 
> All examples are taken from the paper.
> 
> I am not sure how much of this design is preserved in the current
> system. But without having had an intense look at the examples,
> I got the impression, that they follow the rules above.
> 
> Regards
> 
> Juergen Weiss
> 
> Juergen Weiss	  | Universitaet Mainz, Zentrum fuer Datenverarbeitung,
> Juergen Weiss| 55099 Mainz, Tel: +49(6131)39-26361, FAX:
> +49(6131)39-26407
>  
> 
>> -----Original Message-----
>> From: axiom-developer-bounces+weiss=uni-mainz.de@nongnu.org 
>>  On Behalf Of Gabriel Dos Reis
>> Sent: Monday, August 13, 2007 12:16 AM
>> To: Bill Page
>> Cc: list
>> Subject: Re: "has" and "with" (was curious 
>> algebra failure)
>>
>> On Sun, 12 Aug 2007, Bill Page wrote:
>>
>> | On 8/12/07, Gabriel Dos Reis wrote:
>> | > On Sun, 12 Aug 2007, Bill Page wrote:
>> | >
>> | > | If you prefer, now that we have this page nearly 
>> finished we could
>> | > | rename it to remove the SandBox prefix, then all 
>> subscribers would be
>> | > | notified of any further changes.
>> | >
>> | > That would be great!
>> | >
>> | 
>> | Ok, now please refer to the page:
>> | 
>> | http://wiki.axiom-developer.org/AnonymousCategories

\start
Date: Mon, 13 Aug 2007 19:27:03 +1000
From: Alasdair McAndrew
To: list
Subject: A bug in windows Axiom

I'm using Axiom with some cryptography students; at this very early stage we
are having fun with very simple ciphers (Vigenere, Hill, etc), so we need to
transfer from a string to a list of integers.

Here is how to reproduce the bug: on windows Axiom, enter the following tiny
function:

str2lst(str)==map(x +-> ord(x)-65,members(str))

Now try to use it:

str2lst("ABCD")

Axiom will crash (apparently it creates an error log, but I don't know where
to find this log).  Help or advice would be very welcome!

FWIW, the command map(x +-> ord(x)-65,members(str)) returns [0,1,2,3] as it
should.

\start
Date: 13 Aug 2007 11:46:35 +0200
From: Martin Rubey
To: Alasdair McAndrew
Subject: Re: A bug in windows Axiom

Alasdair McAndrew writes:

> I'm using Axiom with some cryptography students; at this very early stage we
> are having fun with very simple ciphers (Vigenere, Hill, etc), so we need to
> transfer from a string to a list of integers.
> 
> Here is how to reproduce the bug: on windows Axiom, enter the following tiny
> function:
> 
> str2lst(str)==map(x +-> ord(x)-65,members(str))

I do not have windows, but maybe declaring the types helps:

str2lst(str: String): List Integer==map(x +-> ord(x)-65,members(str))

apart from that: 

* which version of axiom are you using (if you do not know, maybe the banner at
  startup contains some information) ?

* maybe issueing

  )set break break

  before invoking str2lst, and 

  :bt

  works on windows, too? Then one of the gurus might be able to help?

\start
Date: Mon, 13 Aug 2007 13:36:53 +0200
From: Ralf Hemmecke
To: Bill Page
Subject: "has" and "with" and bug
Cc: Gabriel Dos Reis

>>> I'm saying that the parameter S of the default package
>>> Monad& -- generated for the default implementation of the
>>> category Monad -- is of the named category Monad.

Sorry, I am too lazy to go back where all began. But let me quote that 
piece of code here.

Monad(): Category == SetCategory with
       "*": (%,%) -> %
       "**": (%,PositiveInteger) -> %
       ...
     add
       import RepeatedSquaring(%)
       x:% ** n:PositiveInteger == expt(x,n)
       ...

RepeatedSquaring(S): Exports == Implementation where
    S: SetCategory with "*":(%,%)->%
    Exports == with
      expt: (S,PositiveInteger) -> S
    Implementation == add ...

First. % in RepeatedSquaring(%) can in general not be Monad.
Why? One should be able to pass the "add" part alone as an anonymous 
domain to a function.

AUG Chp. 8.10:

   An add expression also introduces a binding for the constant %, which
   is a reference to the domain formed by the add expression.

So let's do something in Aldor. "add" has to be replaced by "default", 
but this way it does not demonstrate what I wanted to show.

Let's compile and run the program below.

woodpecker:~/scratch>aldor -laldor -grun aaa.as
has with {foo: ()->()} = T
has with {bar: ()->()} = T
has with {rhx: ()->()} = T
has with {foo: ()->()} = T
has with {bar: ()->()} = T
has with {rhx: ()->()} = T
MDom has rhx? T

Ooops. I must say that is surprising. MDom exports foo, bar, ans, but 
not rhx.

So my preferred output would have been:
has with {foo: ()->()} = T
has with {bar: ()->()} = T
has with {rhx: ()->()} = T
has with {foo: ()->()} = T
has with {bar: ()->()} = T
has with {rhx: ()->()} = F
MDom has rhx? F

blahrhx()$Blah(%) should give T, because (I believe) the whole add part 
is passed to Blah and that is an anonymous domain with exports

                                                                  (*)
   foo: ()->()
   bar: ()->()
   rhx: ()->()
   ans: (...)->()

AUG Chp. 7.8:

   The type of the expression A add B is C with { x1: T1; ...; xn: Tn }
   where C is the type of A, and x1,...,xn are the symbols defined
   (using ==) in B, whose types are T1,...,Tn, respectively.

So that is another place where the Aldor compiler does not behave 
according to specification.

Also try to copy the add part of MDom and pass it as an anonymous domain 
argument to ans$MDom. That does not compile, since for some reason the 
compiler thinks that the type of that "add {...}" thing is Type instead 
of the category with exports given in (*).

In general, (as Bill already pointed out), "has" tests for "subcategory".

As a function "has" is of type

   has: (Type, Category) -> Boolean

where the first argument is actually restricted to domains/packages.
See AUG.pdf page 96 "Has expressions".

In Aldor you cannot say

   Monoid has with {1: %}

since Monoid is of type Category (though also of type Type).

----------------------------------------------------------------------
aldor -gloop
%1 >> #include "aldor"
%2 >> #include "aldorinterp"
%3 >> PrimitiveType
   () @ Category ==  with
         =: (%, %) -> Boolean
         ~=: (%, %) -> Boolean
         default ((a: %) ~= (b: %)): Boolean == ..
                                            Comp: 0 msec, Interp: 0 msec
%4 >> PrimitiveType has with {=:(%,%)->Boolean}
       ^
[L14 C1] #1 (Error) No meaning for identifier `PrimitiveType'.
%5 >> #quit
-----------------------------------------------------------------------------

Gaby, if you implement those stuff in SPAD, please don't apply some 
automatic coercion. This whole stuff is about type satisfaction.
I am sure you know about AUG.pdf Chp. 7.5 "Subtypes", Chp. 7.7 "Type 
satisfaction".

All the best

Ralf



---BEGIN aaa.as
#include "aldor"
#include "aldorio"

Blah(S: with {foo:()->()}): with {
     blahfoo: ()->Boolean;
     blahbar: ()->Boolean;
     blahrhx: ()->Boolean;
} == add {
   blahfoo(): Boolean == S has with {foo: ()->()};
   blahbar(): Boolean == S has with {bar: ()->()};
   blahrhx(): Boolean == S has with {rhx: ()->()};
}

MMM: Category == with {
   foo: () -> ();
   bar: () -> ();
}

MDom: MMM with {
   ans: (with {foo:()->(); bar:()->()}) -> ();
} == add {
   foo(): () == {
     stdout << "has with {foo: ()->()} = " << blahfoo()$Blah(%) << newline;
     stdout << "has with {bar: ()->()} = " << blahbar()$Blah(%) << newline;
     stdout << "has with {rhx: ()->()} = " << blahrhx()$Blah(%) << newline;
   }
   bar(): () == {}
   rhx(): () == {}
   ans(S: with {foo:()->(); bar: ()->()}): () == {
     stdout << "has with {foo: ()->()} = " << blahfoo()$Blah(S) << newline;
     stdout << "has with {bar: ()->()} = " << blahbar()$Blah(S) << newline;
     stdout << "has with {rhx: ()->()} = " << blahrhx()$Blah(S) << newline;
   }
}

main(): () == {
   foo()$MDom;
   ans(MDom)$MDom;
   stdout << "MDom has rhx? " << (MDom has with {rhx: ()->()}) << newline;
}
main();
---END aaa.as

\start
Date: Mon, 13 Aug 2007 13:51:08 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

> | Isn't the problem whether 'Monad has SetCategory with "*":(%,%)->%' ?

> If the question is formulated in terms of "has", then I think the answer
> is unambiguously "yes".

Gaby, if you are going to implement "yes", then we should keep in mind 
that the Aldor compiler currently does not allow categories as the first 
argument of "has" and the AUG.pdf p.96 "Has expressions" is clear about 
this.

I must say, I am in favour of relaxing that to allow also categories as 
the first argument. The reason is a conditional export in the definition 
of List in LibAldor.

   l: List(PrimitiveType) := [Integer, String]

should be OK (PrimitiveType is the category that only exports
   =: (%, %) -> %
). But internally List makes conditional tests of the form

List(T:Type): ListType T == add {
   ...
   if T has PrimitiveType then {
     removeAll(t:T, l:%):% == {...}
     ...
   }
}

So giving a category as an argument to the List constructor results in a 
segmentation fault at runtime. The compiler does not catch that case at 
compile time.

In fact, I believe one should be able to distinguish domains from 
categories. Impossible currently with Aldor.

> It seems to me that the compiler asks the question in terms of coercible,
> instead of "has".

Oh, that would surprise me even in SPAD. Where should the "coerce" 
function come from?

\start
Date: Mon, 13 Aug 2007 13:59:20 +0200
From: Ralf Hemmecke
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

> In Spad there is also the subdomain construction that is used to
> define PositiveInteger and NonNegativeInteger from Integer. Subdomain
> automatically provides "coercible to" the parent domain. This is
> something that Spad has that was never implemented in Aldor.

Bill, that should be on our list for the Aldor-Meeting.

\start
Date: Mon, 13 Aug 2007 09:08:40 -0400
From: Bill Page
To: Alasdair McAndrew
Subject: Re: A bug in windows Axiom

On 8/13/07, Alasdair McAndrew wrote:
>
> I'm using Axiom with some cryptography students; at this very early stage we
> are having fun with very simple ciphers (Vigenere, Hill, etc), so we need to
> transfer from a string to a list of integers.
>
>  Here is how to reproduce the bug: on windows Axiom, enter the following
> tiny function:
>
> str2lst(str)==map(x +-> ord(x)-65,members(str))
>
> Now try to use it:
>
> str2lst("ABCD")
>
> Axiom will crash (apparently it creates an error log, but I don't know where
> to find this log).  Help or advice would be very welcome!
>

The current installer program for Axiom on Windows installs an older
version of Axiom in which the

  )set function compile on

bug was not yet fixed (refer to IssueTracker on the wiki). You should
try issuing this command before the function definition. This cures
most problems with functions in this older version of Axiom.

I tried your function definition using a version of Axiom on windows
compiled from the FriCAS sources and it works fine. Compiling Axiom on
Windows using the build-improvements or wh-sandbox branches should
also work fine. If you need some help doing that, just ask or see the
page

http://wiki.axiom-developer.org/BuildAxiom

on the wiki.

\start
Date: Mon, 13 Aug 2007 16:19:46 +0200
From: Ralf Hemmecke
To: Franz Lehner
Subject: Re: aldor stream oddities

On 08/11/2007 08:55 PM, Franz Lehner wrote:
>
>> Now, in Axiom we should have a problem with saying that S is an
>> additive group.
> That's true. All axioms are satisfied, except uniqueness of inverses an=
d
> the neutral element. What should it be? A FuzzyAbelianGroup?

Well, the problem is that we don't deal with classical mathematics, we
deal with constructive mathematics. So let's assume that

   T := UnivariateTaylorSeries(Integer,x,0)

is a Ring. Then I can form F := Fraction T.

Then F is a field. And I can form polynomials that take F as a
coefficient domain. Now I can take several such polynomials in Axiom and =

compute a Gr=F6bner basis for them. You will be surprised that this is no=
t
what you would expect. Testing whether a coefficient is zero is used
quite a lot in Buchberger's algorithm. The algorithm is implemented in a =

generic form and works over any coefficient field. Unfortunately, the
algorithm cannot tell you that it computed the wrong result since you
promised to give a field as input but in fact, gave something for which

>> (4) -> zero?(t-t)
>>    (4)  false
>>            Type: Boolean

holds. So how do you ensure correctness of results then? Would you like
to put all the burden onto the user?

We must be very careful here. And I only addressed that problem. The
library should be very carefully designed. At the moment it contains a
lot of flaws.

>> The category Ring is reserved for structures with complete equality
>> testing.
> Is this the plan for Axiom too?

I don't know. I am not the only person who decides this. But I would
vote for yes.

> What will happen to ExpressionField? I recall there are undecidable
> problems in the latter as well.

All I say, is that the library must be rethought.

> Here is a proposal (in SPAD) for a recursive stream generator which
> looks at all previous elements, not just the last one. It could probabl=
y
> be done with the existing generate(S->S,S), but this one looks more
> natural.

You should take a look at the definition of Stream in LibAldor or also at=

http://www.risc.uni-linz.ac.at/people/hemmecke/AldorCombinat/combinatse12=
=2Ehtml#x58-9900012

\start
Date: 13 Aug 2007 09:33:38 -0500
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

--=-=-=

Ralf Hemmecke writes:

| > | Isn't the problem whether 'Monad has SetCategory with "*":(%,%)->%' ?
| 
| > If the question is formulated in terms of "has", then I think the answer
| > is unambiguously "yes".
| 
| Gaby, if you are going to implement "yes", then we should keep in mind 
| that the Aldor compiler currently does not allow categories as the first 
| argument of "has" and the AUG.pdf p.96 "Has expressions" is clear about 
| this.


Hi,

  Thanks for all who are looking tinto this with me.
I just woke up, going through mails.  I'll be trying to answer
what I believe the easy parts first, then get into the deeper ones at
the end.  Please bear with me.

  
Ralf --

  For the moment, I'm not implementing any new functionality.  I'm
just trying to collect the rules as used at the moment, checking with
all of you here to see whether they match your understanding as well.

[...]

| > It seems to me that the compiler asks the question in terms of coercible,
| > instead of "has".
| 
| Oh, that would surprise me even in SPAD. Where should the "coerce" 
| function come from?

The Spad compiler tries to treat category constructors, domain
constructors, package constructors, and function calls as uniformly as
possible.  What I mean by that is that it applies the principle:

   When calling a function, collect candidates, filter them by
   applying the criteria that the arguments match the parameter types.
   And select the best match if possible.

And that irrespective of whether the arguments are value expressions
or domain expressions.

By "matching" here, I don't necessarily mean only `pattern matching'.
Rather I mean `coercible'.  For example an expression of type Integer
is coercible to Float because Float exports the following function

     coerce : Integer -> % 

Similarly, an expression of type PositiveInteger is coercible to
Integer bcause PositiveInteger is a subdomain of Integer.  Similarly, 
a domain expression of type C1 is coercible to C2 if C2 appears 
in the list of named categories extended by C1.

The exact rules are implemented by the function coerce() defined in
compiler.boot.  They are split into three categories:

    (1) easy coercion -- ceorceEasy
    (2) subset coercion -- coerceSubset
    (3) hard coercion -- coerceHard


I attached to this message the gzipped trace of coerceEasy,
coerceSubset and coerceHard when compiling "**" for Monad&.
All three functions are called with two arguments

  a. a triplet for the current expression,
  b. the target mode.

A triplet for an expression e is:

     (i) the expression e
    (ii) the assumed mode m of e
   (iii) the environment in which e is assumed to have mode m

-- Gaby


--=-=-=

[encoded data, 14476 characters]
5Nn/AxEHpt/isAMA
--=-=-=--

\start
Date: Mon, 13 Aug 2007 16:55:12 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

> The Spad compiler tries to treat category constructors, domain
> constructors, package constructors, and function calls as uniformly as
> possible.  What I mean by that is that it applies the principle:
> 
>    When calling a function, collect candidates, filter them by
>    applying the criteria that the arguments match the parameter types.
>    And select the best match if possible.

Oh, I hope that will change. The compiler should *never* have a choice 
left. Either after filtering there remains *exactly* one possibility or 
the compiler should complain.

> And that irrespective of whether the arguments are value expressions
> or domain expressions.

> By "matching" here, I don't necessarily mean only `pattern matching'.
> Rather I mean `coercible'.  For example an expression of type Integer
> is coercible to Float because Float exports the following function
> 
>      coerce : Integer -> % 

That is exactly what Aldor does *not* do. It never applies "coerce" if 
one doesn't explicitly call for it. At the moment I find Aldor much 
better in this respect. You should consider that some people might 
implement a function that is not a nice "coerce" (although their 
function carries this name).

Just suppose in the context where there is an integer that must be 
coerced into something of MyDomain. I have written a possible coercion 
function in MyDomain that could be used for that task by the SPAD 
compiler. But what I actually want was to call another function. I had 
just forgotten to write it into the source code. Then the compiler 
happily inserts "coerce" and I don't see (don't get a warning) that my 
code is actually not as I wanted it to be. Yes it means more typing, but 
that is not a big burden if you see from the code what is happening.

Remember that in Axiom you can coerce anything to anything. Just write a 
function "coerce" with the corresponding types. So if I add a function

   coerce: Float -> Integer

probably a lot will go wrong and nobody will easily find the error if 
the compiler does not give an error or at least warn.

I understand that the idea of automatic coercion is a good one at an 
interactive level, but at the library I don't want to have it.

I am quite interested how other people feel about automatic coercion.
(You should read Doye's thesis before you answer.
http://portal.axiom-developer.org/refs/articles/doye-aldor-phd.pdf)

If these coercion paths are always unique then I am certainly for it, 
but I somehow think that there is still a lot of research to be done on it.

\start
Date: Mon, 13 Aug 2007 11:18:25 -0400
From: William Sit
To: Ralf Hemmecke
Subject: Re: "has" and "with" and bug
Cc: Gabriel Dos Reis

Ralf Hemmecke wrote:

> Let's compile and run the program below.
>
> woodpecker:~/scratch>aldor -laldor -grun aaa.as
> has with {foo: ()->()} = T
> has with {bar: ()->()} = T
> has with {rhx: ()->()} = T
> has with {foo: ()->()} = T
> has with {bar: ()->()} = T
> has with {rhx: ()->()} = T
> MDom has rhx? T
>
> Ooops. I must say that is surprising. MDom exports foo, bar, ans, but
> not rhx.

Why does that surprise you? Even though rhx is not exported,
it is recorded as part of |catExports|, because according to your
quote from AUG:

> AUG Chp. 7.8:
>
>    The type of the expression A add B is C with { x1: T1; ...; xn: Tn }
>    where C is the type of A, and x1,...,xn are the symbols defined
>    (using ==) in B, whose types are T1,...,Tn, respectively.

This means all local functions (defined in B, but not declared in the with clause
explicitly) are now declared in a with clause??

and on Mon, 13 Aug 2007 10:35:23 +0200, you wrote:

> A with B is (or should be) completely equivalent to:
>
>     with {A; B}
>
> (see Aldor User Guide). And perhaps that is also a hint to the
> named/unamed problem. What appears inside with will be recorded
> internally. [...]

So rhx is recorded as part of |catExports|? Can you check the compiled code?

> What I believe "has" does, is to look inside the |catExports| and checks
> whether the symbol is there.

So MDom has rhx? T seems to me to be according to AUG.

\start
Date: Mon, 13 Aug 2007 17:27:04 +0200
From: Juergen Weiss
To: Ralf Hemmecke, Gabriel Dos Reis
Subject: RE: [Aldor-l] "has" and "with" (was curious algebrafailure)

I don't think that the compiler automatically applies the
coerce functions. Haven't checked to substantiate that
claim though.

> -----Original Message-----
>
> > The Spad compiler tries to treat category constructors, domain
> > constructors, package constructors, and function calls as
> uniformly as
> > possible.  What I mean by that is that it applies the principle:
> >
> >    When calling a function, collect candidates, filter them by
> >    applying the criteria that the arguments match the
> parameter types.
> >    And select the best match if possible.
>
> Oh, I hope that will change. The compiler should *never* have
> a choice
> left. Either after filtering there remains *exactly* one
> possibility or
> the compiler should complain.
>
> > And that irrespective of whether the arguments are value expressions
> > or domain expressions.
>
> > By "matching" here, I don't necessarily mean only `pattern
> matching'.
> > Rather I mean `coercible'.  For example an expression of
> type Integer
> > is coercible to Float because Float exports the following function
> >
> >      coerce : Integer -> %
>
> That is exactly what Aldor does *not* do. It never applies
> "coerce" if
> one doesn't explicitly call for it. At the moment I find Aldor much
> better in this respect. You should consider that some people might
> implement a function that is not a nice "coerce" (although their
> function carries this name).
>
> Just suppose in the context where there is an integer that must be
> coerced into something of MyDomain. I have written a possible
> coercion
> function in MyDomain that could be used for that task by the SPAD
> compiler. But what I actually want was to call another
> function. I had
> just forgotten to write it into the source code. Then the compiler
> happily inserts "coerce" and I don't see (don't get a
> warning) that my
> code is actually not as I wanted it to be. Yes it means more
> typing, but
> that is not a big burden if you see from the code what is happening.
>
> Remember that in Axiom you can coerce anything to anything.
> Just write a
> function "coerce" with the corresponding types. So if I add a function
>
>    coerce: Float -> Integer
>
> probably a lot will go wrong and nobody will easily find the error if
> the compiler does not give an error or at least warn.
>
> I understand that the idea of automatic coercion is a good one at an
> interactive level, but at the library I don't want to have it.
>
> I am quite interested how other people feel about automatic coercion.
> (You should read Doye's thesis before you answer.
> http://portal.axiom-developer.org/refs/articles/doye-aldor-phd.pdf)
>
> If these coercion paths are always unique then I am certainly for it,
> but I somehow think that there is still a lot of research to
> be done on it.

\start
Date: Mon, 13 Aug 2007 11:28:16 -0400
From: Bill Page
To: Ralf Hemmecke
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

On 8/13/07, Ralf Hemmecke wrote:
> > The Spad compiler tries to treat category constructors, domain
> > constructors, package constructors, and function calls as uniformly as
> > possible.  What I mean by that is that it applies the principle:
> >
> >    When calling a function, collect candidates, filter them by
> >    applying the criteria that the arguments match the parameter types.
> >    And select the best match if possible.
>
> Oh, I hope that will change. The compiler should *never* have a choice
> left. Either after filtering there remains *exactly* one possibility or
> the compiler should complain.
>

I agree. Certainly that is what the Aldor compiler does.

> > And that irrespective of whether the arguments are value expressions
> > or domain expressions.
>
> > By "matching" here, I don't necessarily mean only `pattern matching'.
> > Rather I mean `coercible'.  For example an expression of type Integer
> > is coercible to Float because Float exports the following function
> >
> >      coerce : Integer -> %
>
> That is exactly what Aldor does *not* do. It never applies "coerce" if
> one doesn't explicitly call for it. At the moment I find Aldor much
> better in this respect. You should consider that some people might
> implement a function that is not a nice "coerce" (although their
> function carries this name).
>

I agree. I think Spad tries much to hard to do coercions. It does not
try as hard as the Axiom interpreter but still it is possible for Spad
to automatically do things that are quite unexpected for the
programmer and sometimes invisibly wrong. This is one more reason why
I prefer to write "Spad" code first in Aldor and then back port it to
Spad.

> Just suppose in the context where there is an integer that must be
> coerced into something of MyDomain. I have written a possible coercion
> function in MyDomain that could be used for that task by the SPAD
> compiler. But what I actually want was to call another function. I had
> just forgotten to write it into the source code. Then the compiler
> happily inserts "coerce" and I don't see (don't get a warning) that my
> code is actually not as I wanted it to be. Yes it means more typing, but
> that is not a big burden if you see from the code what is happening.
>
> > Similarly, an expression of type PositiveInteger is coercible to
> > Integer bcause PositiveInteger is a subdomain of Integer.  Similarly,
> > a domain expression of type C1 is coercible to C2 if C2 appears
> > in the list of named categories extended by C1.
> >
> > The exact rules are implemented by the function coerce() defined in
> > compiler.boot.  They are split into three categories:
> >
> >   (1) easy coercion -- ceorceEasy
> >   (2) subset coercion -- coerceSubset
> >   (3) hard coercion -- coerceHard

I think coercions from subdomain to domain and from subcategory to
category (presumably (2) above) are of a different kind than coercions
provided by the programmer. These are guaranteed to be correct by the
nature of what we mean by these subtypes. That is why we need the
concept of subdomain to be be "builtin" to the language instead of
pasted on externally via an exported coerce operation.

> Remember that in Axiom you can coerce anything to anything. Just write a
> function "coerce" with the corresponding types. So if I add a function
>
>    coerce: Float -> Integer
>
> probably a lot will go wrong and nobody will easily find the error if
> the compiler does not give an error or at least warn.
>
> I understand that the idea of automatic coercion is a good one at an
> interactive level, but at the library I don't want to have it.
>

I think what we need at the library level is support for coercions
that are a natural consequence of the way we define the types, e.g.
via subtypes. There are also several other similar types of coercions
that arise because of the universal categorical properties of types
like Cross, Record and Union. In the AUG these are referred to as
"courtesy conversions" but I think their presence is more a matter of
necessity than convenience.

> I am quite interested how other people feel about automatic coercion.
> (You should read Doye's thesis before you answer.
> http://portal.axiom-developer.org/refs/articles/doye-aldor-phd.pdf)
>
> If these coercion paths are always unique then I am certainly for it,
> but I somehow think that there is still a lot of research to be done on it.
>

I think that is especially true at the level of the Axiom interpreter.
Here the automatic coercions are one of the things that most violates
the "principle of least surprise" for new users. At the level of Spad
(and Aldor) programming however, I think these things can and should
be defined more carefully and in the most expressive manner possible
that is consistent with an underlying categorical semantics.

\start
Date: Mon, 13 Aug 2007 10:42:26 -0500 (CDT)
From: Gabriel Dos Reis
To: William Sit
Subject: Re: "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, William Sit wrote:

| 
| 
| Gabriel Dos Reis wrote:
| 
| > On Sun, 12 Aug 2007, William Sit wrote:
| >
| > | Isn't the problem whether 'Monad has SetCategory with "*":(%,%)->%' ?
| >
| > If the question is formulated in terms of "has", then I think the answer
| > is unambiguously "yes".
| >
| > But, is that the way the compiler is intended or does the matching of
| > actual arguments with formal parameters?
| >
| > It seems to me that the compiler asks the question in terms of coercible,
| > instead of "has".
| >
| > -- Gaby
| 
| I believe for category parameters, the compiler checks whether the supplied domain
| "has" the category, and for domain parameters, the compiler checks whether the
| object belongs to the domain, NOT whether the object is "coercible" to it.

Here is what is happenning when I trace the following functions:

  coerceEasy coerceSubset coerceHard coerceable compImport compExpression
  compForm compForm1


When compiling the default definition of ** for Monad, the compiler
notices that expt comes from RepeatedSquare(S), where S is the
parameter of type Monad to Monad&.  If compiles all arguments x and n fine.
Then it has to compile the package RepeatedSquare(S) -- as if it were
a function call, since all instantiations are function calls.  To achieve 
that it asks the question whether S (of type Monad) is coercible to

   SetCategory with "*": (%, %) -> %

And the definition of coercible does not permit to return "yes".

\start
Date: Mon, 13 Aug 2007 17:48:17 +0200
From: Ralf Hemmecke
To: William Sit, axiom-dev <list>
Subject: Re: "has" and "with" and bug

On 08/13/2007 05:18 PM, William Sit wrote:
> Ralf Hemmecke wrote:
> 
>> Let's compile and run the program below.
>>
>> woodpecker:~/scratch>aldor -laldor -grun aaa.as
>> has with {foo: ()->()} = T
>> has with {bar: ()->()} = T
>> has with {rhx: ()->()} = T
>> has with {foo: ()->()} = T
>> has with {bar: ()->()} = T
>> has with {rhx: ()->()} = T
>> MDom has rhx? T
>>
>> Ooops. I must say that is surprising. MDom exports foo, bar, ans, but
>> not rhx.
> 
> Why does that surprise you? Even though rhx is not exported,
> it is recorded as part of |catExports|, because according to your
> quote from AUG:
> 
>> AUG Chp. 7.8:
>>
>>    The type of the expression A add B is C with { x1: T1; ...; xn: Tn }
>>    where C is the type of A, and x1,...,xn are the symbols defined
>>    (using ==) in B, whose types are T1,...,Tn, respectively.

OK, but MDom is different. I defined

MDom: MMM with {
   ans: (with {foo:()->(); bar:()->()}) -> ();
} == add { ... }

And this construction says that the type of MDom is

   MMM with {ans: (...) -> ()}

where

MMM: Category == with {
   foo: () -> ();
   bar: () -> ();
}

Do you see "rhx" there? So MDom does not export rhx. It simply does not 
matter what "add {...}" exports. The type of the "add {...}" 
construction must implement foo, bar, and ans, that would be enough.

In the file I gave, the type of "add {...}" exports rhx, MDom doesn't.

\start
Date: Mon, 13 Aug 2007 10:49:16 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, Bill Page wrote:

[...]

| > > Similarly, an expression of type PositiveInteger is coercible to
| > > Integer bcause PositiveInteger is a subdomain of Integer.  Similarly,
| > > a domain expression of type C1 is coercible to C2 if C2 appears
| > > in the list of named categories extended by C1.
| > >
| > > The exact rules are implemented by the function coerce() defined in
| > > compiler.boot.  They are split into three categories:
| > >
| > >   (1) easy coercion -- ceorceEasy
| > >   (2) subset coercion -- coerceSubset
| > >   (3) hard coercion -- coerceHard
| 
| I think coercions from subdomain to domain and from subcategory to
| category (presumably (2) above) are of a different kind than coercions
| provided by the programmer. These are guaranteed to be correct by the
| nature of what we mean by these subtypes. That is why we need the
| concept of subdomain to be be "builtin" to the language instead of
| pasted on externally via an exported coerce operation.

So, what are discussing now?  To change the existing semantics?


If we believe that we should treat values and types uniformely, I'm not
sure we should start with the principle that coercions from subdomain
to domain and from subcategory to category are different.  If we want
uniformity, we should have a single rule.

As for coercions, I'm not so sure I agree that they vilate the
principle of least surprise.

\start
Date: Mon, 13 Aug 2007 12:20:59 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

On 8/13/07, Gabriel Dos Reis wrote:
> ...
> When compiling the default definition of ** for Monad, the compiler
> notices that expt comes from RepeatedSquare(S), where S is the
> parameter of type Monad to Monad&.

This use of S is confusing to me. The spad code says:

   import RepeatedSquaring(%)

The S that I see is the *formal* parameter of RepeatedSquaring. It's type is

    SetCategory with "*": (%, %) -> %

as defined in repsqr.spad. But in Monad the parameter % in

   import RepeatedSquaring(%)

refers to some domain (currently unknown) that has type Monad.

How can I reconcile that with your statements about S above? Is the
"S" to which you refer some kind of dummy?

> If compiles all arguments x and n fine.
> Then it has to compile the package RepeatedSquare(S) -- as if it were
> a function call, since all instantiations are function calls.  To achieve
> that it asks the question whether S (of type Monad) is coercible to
>
>    SetCategory with "*": (%, %) -> %
>
> And the definition of coercible does not permit to return "yes".
>

But certainly it must return "yes" in an unmodified version of the
Spad compiler or (perhaps)  what needs to be coercible is not S of
type Monad but rather the dummy %. It's type is the category-value of
Monad:

  SetCategory with
       "*": (%,%) -> %
       rightPower: (%,PositiveInteger) -> %
       leftPower: (%,PositiveInteger) -> %
       "**": (%,PositiveInteger) -> %

which certainly is coercible to

   SetCategory with "*": (%, %) -> %

----------

Is it possible to trace how coerce is called in an unmodified Spad
compiler that compiles Monad without an error message?

\start
Date: Mon, 13 Aug 2007 12:24:52 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

On 8/13/07, Gabriel Dos Reis wrote:
> On Mon, 13 Aug 2007, Bill Page wrote:
>
> [...]
>
> | > > Similarly, an expression of type PositiveInteger is coercible to
> | > > Integer bcause PositiveInteger is a subdomain of Integer.  Similarly,
> | > > a domain expression of type C1 is coercible to C2 if C2 appears
> | > > in the list of named categories extended by C1.
> | > >
> | > > The exact rules are implemented by the function coerce() defined in
> | > > compiler.boot.  They are split into three categories:
> | > >
> | > >   (1) easy coercion -- ceorceEasy
> | > >   (2) subset coercion -- coerceSubset
> | > >   (3) hard coercion -- coerceHard
> |
> | I think coercions from subdomain to domain and from subcategory to
> | category (presumably (2) above) are of a different kind than coercions
> | provided by the programmer. These are guaranteed to be correct by the
> | nature of what we mean by these subtypes. That is why we need the
> | concept of subdomain to be be "builtin" to the language instead of
> | pasted on externally via an exported coerce operation.
>
> So, what are discussing now?  To change the existing semantics?
>

No. subdomain is already part of Spad. Spad implements things this way
but Aldor does not. If I am discussing changing anything it would be
Aldor not Spad.

>
> If we believe that we should treat values and types uniformely, I'm not
> sure we should start with the principle that coercions from subdomain
> to domain and from subcategory to category are different.  If we want
> uniformity, we should have a single rule.
>

I agree, however these coercions do arise from fundamentally different
properties of domains and categories.

> As for coercions, I'm not so sure I agree that they violate the
> principle of least surprise.
>

There are many easy examples of this when you use the Axiom interpreter.

\start
Date: Mon, 13 Aug 2007 11:29:32 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, Bill Page wrote:

| On 8/13/07, Gabriel Dos Reis wrote:
| > ...
| > When compiling the default definition of ** for Monad, the compiler
| > notices that expt comes from RepeatedSquare(S), where S is the
| > parameter of type Monad to Monad&.
| 
| This use of S is confusing to me.

OK, see the message I'll be sending out in a moment.

| The spad code says:
| 
|    import RepeatedSquaring(%)
| 
| The S that I see is the *formal* parameter of RepeatedSquaring. It's type is
| 
|     SetCategory with "*": (%, %) -> %
| 
| as defined in repsqr.spad. But in Monad the parameter % in
| 
|    import RepeatedSquaring(%)
| 
| refers to some domain (currently unknown) that has type Monad.

I see what you mean.  Let me cut-n-paste part of the other message I'm
composing 

   2.  When one defines a category with default implementation, like
       Monad, the compiler extracts the "purely categorial" part of
       Monad, e.g. the exports; then it implicitly creates a package
       Monad& with an implicit parameter S of type Monad.  E.g., it is
       as if the code was written:

       )abbrev package MONAD- Monad&
       Monad&(S: Monad): Public == Private where
         Public ==> with
           "**" : (S, PositiveInteger) -> S

         Private ==> add
           import RepeatedSquare(S)
           x ** n == expt(x, n)


| How can I reconcile that with your statements about S above? Is the
| "S" to which you refer some kind of dummy?

does the above help?


Are you confused by the uses of "x" in the below?

    f(x : Integer): Float == 
       cos(x)$Float

    
    g(x: Float): Float ==
      f(x :: Integer)



| > If compiles all arguments x and n fine.
| > Then it has to compile the package RepeatedSquare(S) -- as if it were
| > a function call, since all instantiations are function calls.  To achieve
| > that it asks the question whether S (of type Monad) is coercible to
| >
| >    SetCategory with "*": (%, %) -> %
| >
| > And the definition of coercible does not permit to return "yes".
| >
| 
| But certainly it must return "yes" in an unmodified version of the
| Spad compiler or (perhaps)  what needs to be coercible is not S of
| type Monad but rather the dummy %. It's type is the category-value of
| Monad:
| 
|   SetCategory with
|        "*": (%,%) -> %
|        rightPower: (%,PositiveInteger) -> %
|        leftPower: (%,PositiveInteger) -> %
|        "**": (%,PositiveInteger) -> %
| 
| which certainly is coercible to
| 
|    SetCategory with "*": (%, %) -> %
| 
| ----------
| 
| Is it possible to trace how coerce is called in an unmodified Spad
| compiler that compiles Monad without an error message?

Oh yes, one gets tons of s-expressions.  I already posted a snipped
of 4000+ line.  I can post more if you want, but not to the list.

\start
Date: 13 Aug 2007 00:39:45 -0500
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

Bill Page writes:

| Gaby,
| 
| On 8/12/07, you wrote:
| > On Sun, 12 Aug 2007, William Sit wrote:
| >
| > | Isn't the problem whether 'Monad has SetCategory with
| > | "*":(%,%)->%' ? My answer would be yes. This should not be
| > | related to equivalence of categories or domains. We
| > | already have seen examples that Integer has with
| > | _*:(Integer, Integer)->Integer. Here, we are not saying
| > | 'Monad is SetCategory with "*":(%,%)->%'.
| >
| 
| Sorry for my confusion. In fact I agree with William. This is not
| directly related to type equivalence. We need something more general
| than type equivalence. We need to know when one category is a
| subcategory of another. The type equivalence rules to which Juergen
| referred must be applied to the parts of the category expressions in
| order to determine this relationship.
| 
| You wrote:
| 
| > > I'm saying that the parameter S of the default package
| > > Monad& -- generated for the default implementation of the
| > > category Monad -- is of the named category Monad.  It is
| > > that parameter S which is being used to instantiate
| > >RepeatedSquaring.  However, RepeatedSquaring expects its
| > >(domain) argument to be of the unnamed category
| > >
| > >    SetCategory with "*": (%,%) -> %
| 
| Your statement of the problem is a little confusing to me since the
| parameter S is the parameter of RepeatedSquaring. But as you say, it's
| type is given by the unnamed category above. You are concerned because
| what is being passed to RepeatedSquaring is a domain of type category
| named Monad. But clearly a domain of type Monad is also is a member of
| 
|    SetCategory with "*": (%,%) -> %
| 
| since Monad is a subcategory of this category - any domain that "has"
| Monad will necessarily provide all of the exports required by
| RepeatedSquaring. RepeatedSquaring requires it's (domain) argument to
| be of type that is a subcategory of this unnamed category.

A few obversations:

    1.  When a function is called, the compiler/interpreter determines
        whether the arguments used to call the function are coercible
        to the type of the formal parameters of the function, when it
        was declared.

       What that means concretely is that when we declare a function
       like

         foo: Double -> Double


       and we attempt foo(4), the compiler/interperter does not start
       looking whether the value 4 "has" sin, cos, and many operations 
       that hold for Doubles.  Rather, it determins whether the value
       4 can be converted the type Double, if yes, it applies that
       conversion and generate call to foo() with the result of the
       of the conversion as argument.

       That looks intuitive enough.  And I suspect we all agree.

   2.  When one defines a category with default implementation, like 
       Monad, the compiler extracts the "purely categorial" part of
       Monad, e.g. the exports; then it implicitly creates a package
       Monad& with an implicit parameter S of type Monad.  E.g., it is
       as if the code was written:

       )abbrev package MONAD- Monad&
       Monad&(S: Monad): Public == Private where
         Public ==> with
           "**" : (S, PositiveInteger) -> S
 
         Private ==> add
           import RepeatedSquare(S)
           x ** n == expt(x, n)


       Now the compiler goes on typecheking the defnition x ** n.
       It sees the use of expt() and find out that the only expt() in
       scope if the one from RepeatedSquare(S).  Then it tries
       to instantiate that package -- just like a function call.
       From there, it applies the usual rules:  Can I coerce S of
       type Monad to the expected argument type of RepeatedSquare()?
       They answer comes out as "no".  Hence the error.


Is that less confusing?

\start
Date: Mon, 13 Aug 2007 11:46:49 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, Bill Page wrote:

| Is it possible to trace how coerce is called in an unmodified Spad
| compiler that compiles Monad without an error message?

Bill, sorry, I misread this part of your message.
I'm starting a new build without the correction applied
to the compiler.

\start
Date: Mon, 13 Aug 2007 13:04:42 -0400
From: Bill Page
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

On 13 Aug 2007 00:39:45 -0500, Gabriel Dos Reis wrote:
> ...
>    2.  When one defines a category with default implementation, like
>        Monad, the compiler extracts the "purely categorial" part of
>        Monad, e.g. the exports; then it implicitly creates a package
>        Monad& with an implicit parameter S of type Monad.  E.g., it is
>        as if the code was written:
>
>        )abbrev package MONAD- Monad&
>        Monad&(S: Monad): Public == Private where
>          Public ==> with
>            "**" : (S, PositiveInteger) -> S
>
>          Private ==> add
>            import RepeatedSquare(S)
>            x ** n == expt(x, n)
>
>
>        Now the compiler goes on typecheking the defnition x ** n.
>        It sees the use of expt() and find out that the only expt() in
>        scope if the one from RepeatedSquare(S).  Then it tries
>        to instantiate that package -- just like a function call.
>        From there, it applies the usual rules:  Can I coerce S of
>        type Monad to the expected argument type of RepeatedSquare()?
>        They answer comes out as "no".  Hence the error.
>
> Is that less confusing?
>

Yes, thank you! But of course that is how packages and domains in Spad
are normally written and this package does in fact compile just fine
in Spad. See:

http://wiki.axiom-developer.org/SandBoxMonad

as it should.

The question of coercing Monad to

   SetCategory with "*": (%, %) -> %

must be yes. I guess the question still is how? and why? does it work.

\start
Date: 13 Aug 2007 11:50:19 -0500
From: Gabriel Dos Reis
To: William Sit
Subject: Re: "has" and "with" (was curious algebra failure)

William Sit writes:

| I think I understand the objection raised by Gaby. In matching Monad to
| SetCategory with ..., Axiom is applying a forgetful functor that, given a
| monad, forgets all of its operations except those featured in SetCategory with
| ....   In this sense, applying a forgetful functor is a form of automatic
| coercion on the level of categories.  Gaby is correct in saying that strictly
| speaking, the forgetful functor should also not be automatic, just like the
| usual coercion between domains. In fact, how one forgets the structure of a
| ring to the structure of a Monad would be ambiguous, since there are two
| possible ways. For more complicated algebraic structures (like Hopf algebra,
| differential algebra) if it is possible to specify precisely the forgetful
| functor, it would allow us to have only one Monoid structure instead of an
| AbelianMonoid and a Monoid (and many others distinguished by different names
| for the monoid operation).
| 
| Gaby, is that a fair statement?

Yes, that is close.

| You may be interested in this old 1986 article by Kamal Abdali et al., on An
| Object Oriented Approach to Algebra System Design:
| 
| http://portal.acm.org/ft_gateway.cfm?id=32444&type=pdf&coll=GUIDE&dl=ACM
| 
| One of the stated features of Views is:
| 
| "Views do not depend on operation names. That is, locally (i.e. in their
| domains) two different Rings may have different names for their 'additon
| operation', but, when viewed as Rings, their addition operation is accessed by
| the same identifier."

Thanks; I had a copy, but I did not get back to it.

\start
Date: Mon, 13 Aug 2007 12:06:16 -0500 (CDT)
From: Gabriel Dos Reis
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, Bill Page wrote:

| On 13 Aug 2007 00:39:45 -0500, Gabriel Dos Reis wrote:
| > ...
| >    2.  When one defines a category with default implementation, like
| >        Monad, the compiler extracts the "purely categorial" part of
| >        Monad, e.g. the exports; then it implicitly creates a package
| >        Monad& with an implicit parameter S of type Monad.  E.g., it is
| >        as if the code was written:
| >
| >        )abbrev package MONAD- Monad&
| >        Monad&(S: Monad): Public == Private where
| >          Public ==> with
| >            "**" : (S, PositiveInteger) -> S
| >
| >          Private ==> add
| >            import RepeatedSquare(S)
| >            x ** n == expt(x, n)
| >
| >
| >        Now the compiler goes on typecheking the defnition x ** n.
| >        It sees the use of expt() and find out that the only expt() in
| >        scope if the one from RepeatedSquare(S).  Then it tries
| >        to instantiate that package -- just like a function call.
| >        From there, it applies the usual rules:  Can I coerce S of
| >        type Monad to the expected argument type of RepeatedSquare()?
| >        They answer comes out as "no".  Hence the error.
| >
| > Is that less confusing?
| >
| 
| Yes, thank you! But of course that is how packages and domains in Spad
| are normally written and this package does in fact compile just fine
| in Spad. See:
| 
| http://wiki.axiom-developer.org/SandBoxMonad
| 
| as it should.
| 
| The question of coercing Monad to
| 
|    SetCategory with "*": (%, %) -> %
| 
| must be yes. 

A question is "why must it be `yes'"?

| I guess the question still is how? and why? does it work.

Indeed.

\start
Date: Mon, 13 Aug 2007 19:37:54 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with" (was curious algebra failure)

>     1.  When a function is called, the compiler/interpreter determines
>         whether the arguments used to call the function are coercible
>         to the type of the formal parameters of the function, when it
>         was declared.
> 
>        What that means concretely is that when we declare a function
>        like
> 
>          foo: Double -> Double
> 
> 
>        and we attempt foo(4), the compiler/interperter does not start
>        looking whether the value 4 "has" sin, cos, and many operations 
>        that hold for Doubles.  Rather, it determins whether the value
>        4 can be converted the type Double, if yes, it applies that
>        conversion and generate call to foo() with the result of the
>        of the conversion as argument.
> 
>        That looks intuitive enough.  And I suspect we all agree.

In Aldor that is different. When the compiler sees 4 that is just 
something of type Literal. If it sees foo(4) and foo: Double->Double is 
the only foo in scope, the compiler tries to match the type of 4 with 
Double. The only thing it is allowed to do is to call a function that 
converts 4 to Double, i.e. a function

   Literal -> Double

Now in Aldor there are several functions of this kind.

   float:   Literal -> %
   integer: Literal -> %
   string:  Liteal -> %

Double might actually export and implement the first two of them.
And the rules are simple for the compiler.

If a literal looks like a string, i.e. of the form "...", then apply 
"string".
If a literal looks like a float, then apply "float".
If a literal looks like an integer, then apply "integer".

There is no guessing. If none of float, integer, string with an 
appropriate type is in scope, then throw an error.


>    2.  When one defines a category with default implementation, like 
>        Monad, the compiler extracts the "purely categorial" part of
>        Monad, e.g. the exports; then it implicitly creates a package
>        Monad& with an implicit parameter S of type Monad.  E.g., it is
>        as if the code was written:
> 
>        )abbrev package MONAD- Monad&
>        Monad&(S: Monad): Public == Private where
>          Public ==> with
>            "**" : (S, PositiveInteger) -> S
>  
>          Private ==> add
>            import RepeatedSquare(S)
>            x ** n == expt(x, n)

Again, that is not the case for "default" in Aldor.

If you define yet another function inside "default {...}", then this 
belongs to the exports of the category although it is not declared as a 
signature.

define Foo: Category == with {
   default { foo(): () == {} }
}

exports

   foo: () -> ()

>        Now the compiler goes on typecheking the defnition x ** n.
>        It sees the use of expt() and find out that the only expt() in
>        scope if the one from RepeatedSquare(S).  Then it tries
>        to instantiate that package -- just like a function call.
>        From there, it applies the usual rules:  Can I coerce S of
>        type Monad to the expected argument type of RepeatedSquare()?
>        They answer comes out as "no".  Hence the error.

Well, of course the answer should be "yes". But that should be found out 
by taking the exports of S (which happens to be Monad). Then the 
compiler should check whether Monad exports SetCategory and *:(%,%)->% 
(which is what S in RepeatedSquaring requires). If that is fulfilled 
then everything is fine. No coercion necessary.

\start
Date: Mon, 13 Aug 2007 12:49:31 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, Ralf Hemmecke wrote:

| >     1.  When a function is called, the compiler/interpreter determines
| >         whether the arguments used to call the function are coercible
| >         to the type of the formal parameters of the function, when it
| >         was declared.
| > 
| >        What that means concretely is that when we declare a function
| >        like
| > 
| >          foo: Double -> Double
| > 
| > 
| >        and we attempt foo(4), the compiler/interperter does not start
| >        looking whether the value 4 "has" sin, cos, and many operations that
| >        hold for Doubles.  Rather, it determins whether the value
| >        4 can be converted the type Double, if yes, it applies that
| >        conversion and generate call to foo() with the result of the
| >        of the conversion as argument.
| > 
| >        That looks intuitive enough.  And I suspect we all agree.
| 
| In Aldor that is different. When the compiler sees 4 that is just something of
| type Literal. If it sees foo(4) and foo: Double->Double is the only foo in
| scope, the compiler tries to match the type of 4 with Double. The only thing
| it is allowed to do is to call a function that converts 4 to Double, i.e. a
| function
| 
|   Literal -> Double
| 
| Now in Aldor there are several functions of this kind.
| 
|   float:   Literal -> %
|   integer: Literal -> %
|   string:  Liteal -> %
| 
| Double might actually export and implement the first two of them.
| And the rules are simple for the compiler.
| 
| If a literal looks like a string, i.e. of the form "...", then apply "string".
| If a literal looks like a float, then apply "float".
| If a literal looks like an integer, then apply "integer".

maybe the use of the literal 4 was a distraction from the main topic.  

What I way saying is that when the compiler sees a call to foo
with an expression of type integer, and foo is the only one in scope...

[...]

| >        Now the compiler goes on typecheking the defnition x ** n.
| >        It sees the use of expt() and find out that the only expt() in
| >        scope if the one from RepeatedSquare(S).  Then it tries
| >        to instantiate that package -- just like a function call.
| >        From there, it applies the usual rules:  Can I coerce S of
| >        type Monad to the expected argument type of RepeatedSquare()?
| >        They answer comes out as "no".  Hence the error.
| 
| Well, of course the answer should be "yes".

It is not clear to me why the answer should *of course" be "yes".

| But that should be found out by
| taking the exports of S (which happens to be Monad). Then the compiler should
| check whether Monad exports SetCategory and *:(%,%)->% (which is what S in
| RepeatedSquaring requires). If that is fulfilled then everything is fine. No
| coercion necessary.

That is a another model of translation; I'm sure it is uniform in the sense
that it treats value expression and domain expression in the same way.


Please, note I'm not being argumentative.  I'm trying to understand
all perspective -- that is why I would like to understand the "obviousness"
of each point of view.  I underdstand the coercion well enough and  I believe
I can prove that that system is sound.

\start
Date: Mon, 13 Aug 2007 12:54:59 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with" and bug

On Mon, 13 Aug 2007, Ralf Hemmecke wrote:

| > > > I'm saying that the parameter S of the default package
| > > > Monad& -- generated for the default implementation of the
| > > > category Monad -- is of the named category Monad.
| 
| Sorry, I am too lazy to go back where all began. But let me quote that piece
| of code here.
| 
| Monad(): Category == SetCategory with
|       "*": (%,%) -> %
|       "**": (%,PositiveInteger) -> %
|       ...
|     add
|       import RepeatedSquaring(%)
|       x:% ** n:PositiveInteger == expt(x,n)
|       ...
| 

One question is why the compiler does not error out at the import
line.  It turns out that the compiler does something akin to macro
substitution without typeck checking or very minimal typecheck.  See the
function compImport.

\start
Date: Mon, 13 Aug 2007 19:57:07 +0200 (CEST)
From: Franz Lehner
To: list
Subject: Another strange coercion

Hello,

> There are many easy examples of this when you use the Axiom interpreter.
Perhaps the following is related:

Trying to implement free products of monoids
FreeProductMonoid(M1:Monoid,M2:Monoid)
(see attachment, not very elegant, but I don't know how to avoid "mixed 
lists" otherwise). I am stuck at the following problem: 
There are two converters

coerce:M1 -> %
coerce:M2 -> %

but somehow always the first converter is called,
in the order where they are found in the source file,
leading to strange results:


(1) -> Z2:=CyclicGroup(2,'a)

    (1)  CyclicGroup(2,a)
                                                        Type: Domain
(2) -> Z3:=CyclicGroup(3,'b)

    (2)  CyclicGroup(3,b)
                                                        Type: Domain
(3) -> G:=FreeProductMonoid(Z2,Z3)

    (3)  FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))
                                                        Type: Domain
(4) -> a1:=a::Z2

    (4)  a
                                                        Type: CyclicGroup(2,a)
(5) -> b1:=b::Z3

    (5)  b
                                                        Type: CyclicGroup(3,b)
(6) -> a2:=a1::G

    (6)  a
                    Type: FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))
(7) -> b2:=b1::G

    (7)  a
                    Type: FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))

(8) -> b2a:= (b1^2) ::G

          2
    (8)  a
                    Type: FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))


(9) -> b2a * 1::G

    (9)  1

(10) -> b::Z2

    >> System error:
    wrong symbol


Especially (8) is pretty strange. (9) shows that indeed b made it 
into M1 and is the identity element. (10) shows that coercion in 
CyclicGroup filters out the wrong symbols as it should.
What am I missing? Somehow the interpreter is confused by two almost equal 
signatures (both M1 and M2 are Monoids). Is this forbidden?
Renaming the converters to coerce1 and coerce2 makes it work.

regards
Franz
--461446550-1814718225-1187025159=:29316

[encoded data, 5063 characters]

--461446550-1814718225-1187025159=:29316

I2luY2x1ZGUgImF4aW9tIg0KDQpDeWNsaWNHcm91cChuOlBvc2l0aXZlSW50
ZWdlcixnOlN5bWJvbCk6IEdyb3VwIHdpdGggew0KICAgICAgICAxOiAlOw0K
ICAgICAgICANCiAgICAgICAgY29lcmNlIDogJSAtPiBPdXRwdXRGb3JtOw0K
ICAgICAgICANCiAgICAgICAgb25lPzogJSAtPiBCb29sZWFuOw0KICAgICAg
ICANCiAgICAgICAgY29lcmNlOlN5bWJvbCAtPiAlOw0KDQogICAgICAgIGdl
bnJ0cjogJTsNCg0KfSA9PSBhZGQgew0KICAgICAgICBSZXAgPT0gSW50ZWdl
cjsNCg0KICAgICAgICBpbXBvcnQgZnJvbSBJbnRlZ2VyOw0KICAgICAgICAx
OiUgPT0gcGVyIDA7DQoNCiAgICAgICAgZ2VucnRyOiAlID09IHBlciAoMUBJ
bnRlZ2VyKTsNCiAgICAgICAgDQogICAgICAgIGNvZXJjZSh4OiUpOk91dHB1
dEZvcm0gPT0gIHsNCiAgICAgICAgICAgICAgICB6ZXJvPyByZXAgeCA9PiBv
dXRwdXRGb3JtKDFASW50ZWdlcik7IA0KICAgICAgICAgICAgICAgIHogd2hl
cmUge2ltcG9ydCBmcm9tIEZyYWN0aW9uIFBvbHlub21pYWwgSW50ZWdlcjsg
aW1wb3J0IGZyb20gUG9seW5vbWlhbCBJbnRlZ2VyOw0KICAgICAgICAgICAg
ICAgICAgICAgICAgejpPdXRwdXRGb3JtIDo9ICgoZzo6UG9seW5vbWlhbCBJ
bnRlZ2VyKTo6RnJhY3Rpb24gUG9seW5vbWlhbCBJbnRlZ2VyXihyZXAgeCkp
OjpPdXRwdXRGb3JtOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgfTsN
Cg0KDQogICAgICAgIGNvZXJjZSh4OlN5bWJvbCk6JSA9PSAgew0KICAgICAg
ICAgICAgICAgIHggfj0gZyA9PiBlcnJvciAid3Jvbmcgc3ltYm9sIjsNCiAg
ICAgICAgICAgICAgICBwZXIgKDFASW50ZWdlcik7DQogICAgICAgIH0NCiAg
ICAgICAgDQogICAgICAgIA0KICAgICAgICAoeDolKSAqICh5OiUpOiAlID09
IHBlciBhZGRtb2QocmVwIHgscmVwIHksbjo6SW50ZWdlcik7DQogICAgICAg
IA0KICAgICAgICAoeDolKSA9ICh5OiUpOiBCb29sZWFuID09IHJlcCB4ID0g
cmVwIHk7DQogICAgICAgIA0KICAgICAgICBvbmU/KHg6JSk6Qm9vbGVhbiA9
PSB6ZXJvPyByZXAgeDsNCg0KICAgICAgICBpbnYoeDolKTolID09IHsgb25l
PyB4ID0+IDE7IHBlciggbjo6SW50ZWdlciAtIHJlcCB4KX07DQogICAgICAg
IA0KfQ0K

--461446550-1814718225-1187025159=:29316--

\start
Date: Mon, 13 Aug 2007 12:59:35 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

On Mon, 13 Aug 2007, Ralf Hemmecke wrote:

| > The Spad compiler tries to treat category constructors, domain
| > constructors, package constructors, and function calls as uniformly as
| > possible.  What I mean by that is that it applies the principle:
| > 
| >    When calling a function, collect candidates, filter them by
| >    applying the criteria that the arguments match the parameter types.
| >    And select the best match if possible.
| 
| Oh, I hope that will change. The compiler should *never* have a choice left.
| Either after filtering there remains *exactly* one possibility or the compiler
| should complain.

I believe that is what the Spad compiler does.  


| > And that irrespective of whether the arguments are value expressions
| > or domain expressions.
| 
| > By "matching" here, I don't necessarily mean only `pattern matching'.
| > Rather I mean `coercible'.  For example an expression of type Integer
| > is coercible to Float because Float exports the following function
| > 
| >      coerce : Integer -> % 
| 
| That is exactly what Aldor does *not* do. It never applies "coerce" if one
| doesn't explicitly call for it. At the moment I find Aldor much better in this
| respect. You should consider that some people might implement a function that
| is not a nice "coerce" (although their function carries this name).

I don't think there is anything we can do about that.  We can't police
people that name coerce a function that does pretend.  Sometimes that is
bad, sometimes that is good.

\start
Date: Mon, 13 Aug 2007 14:36:56 -0400
From: Bill Page
To: Ralf Hemmecke
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

On 8/13/07, Ralf Hemmecke wrote:
>
> You have added the Aldor version of the test code to
>
> > | http://wiki.axiom-developer.org/AnonymousCategories
>
> For test3()
>
>      -- QQ is a category-valued constant
>      define QQ:Category == with { +:(Integer,Integer)->Integer }
>      ttest3():Boolean ==
>        Integer has QQ
>
> you say:  -- should be true
>
> I don't agree with that. QQ is a (named) category (which you also could
> have defined outside. Domains belong to categories by assertion. You did
> not say
>
>    extend Integer: QQ == add;
>
> and QQ was not known before, so the aldor compiler is right to produce
> code that returns false.
>

Ok. How do tell Aldor that I do not care about the name I am only
interested in the anonymous body of a given category definition? I
thought I understood this, but I guess not. The discussion of the
'define' keyword in the AUG lead me to believe that that was what was
implied by it's use.

If I pass a category as a parameter to a constructor, e.g.

  define D: Category == with
     f: % -> %

  C(X:Category):Category == with
    if Integer has X then
      ...

  A:C(D)

does X represent the named category (D) or just it's category-value
(with f: %-> %)? Does the meaning of X change if we omitted the
'define' keyword?

Can you explain to me how I can use this? Or what to read? :-)

\start
Date: Tue, 14 Aug 2007 11:27:15 +1000
From: Alasdair McAndrew
To: Bill Page
Subject: Re: A bug in windows Axiom

Thanks, that worked fine!

Now - I don't want to have to go through the arduous business of downloading
masses of stuff before I can compile Axiom on Windows (and neither do my
students).  All I want is one simple installation file: download, install
and that's it.  Do you know if the current Windows binary will ever be
upgraded?

Thanks,
Alasdair

On 8/13/07, Bill Page wrote:
>
> On 8/13/07, Alasdair McAndrew wrote:
> >
> > I'm using Axiom with some cryptography students; at this very early
> stage we
> > are having fun with very simple ciphers (Vigenere, Hill, etc), so we
> need to
> > transfer from a string to a list of integers.
> >
> >  Here is how to reproduce the bug: on windows Axiom, enter the following
> > tiny function:
> >
> > str2lst(str)==map(x +-> ord(x)-65,members(str))
> >
> > Now try to use it:
> >
> > str2lst("ABCD")
> >
> > Axiom will crash (apparently it creates an error log, but I don't know
> where
> > to find this log).  Help or advice would be very welcome!
> >
>
> The current installer program for Axiom on Windows installs an older
> version of Axiom in which the
>
>   )set function compile on
>
> bug was not yet fixed (refer to IssueTracker on the wiki). You should
> try issuing this command before the function definition. This cures
> most problems with functions in this older version of Axiom.
>
> I tried your function definition using a version of Axiom on windows
> compiled from the FriCAS sources and it works fine. Compiling Axiom on
> Windows using the build-improvements or wh-sandbox branches should
> also work fine. If you need some help doing that, just ask or see the
> page
>
> http://wiki.axiom-developer.org/BuildAxiom
>
> on the wiki.
>
> Regards,
> Bill Page.
>

\start
Date: Mon, 13 Aug 2007 22:06:55 -0400
From: Bill Page
To: Alasdair McAndrew
Subject: Re: A bug in windows Axiom

On 8/13/07, Alasdair McAndrew wrote:

On 8/13/07, Bill Page wrote:
> ...
> The current installer program for Axiom on Windows installs an older
> version of Axiom in which the
> > version of Axiom in which the
> >
> > )set function compile on
> >
> > bug was not yet fixed (refer to IssueTracker on the wiki). You should
> > try issuing this command before the function definition. This cures
> > most problems with functions in this older version of Axiom.
>
> Thanks, that worked fine!
>

You are welcome.

> Now - I don't want to have to go through the arduous business of
> downloading masses of stuff before I can compile Axiom on Windows
> (and neither do my students).  All I want is one simple installation file:
> download, install and that's it.  Do you know if the current Windows
> binary will ever be upgraded?
>

Of course it will. This is an entirely volunteer-supported project. It
will happen when someone is convinced that it is the next most
important thing to do.  :-)  There have been many important fixes and
changes since the old binary was created.

In the mean time I think you can make this change yourself without
re-compiling Axiom - just a little surgery:

1) Start Axiom normally

2) Issue the command:

  )set function compile on

3) Save a new working copy of the system

  )lisp (si:save-system "AXIOMsys")

4) A new AXIOMsys.exe file will be created in the default directory.
   Just copy this file to

   C:\Program Files\axiom\mnt\windows\bin

   over-writing the existing AXIOMsys.exe file.

5) The next time you start Axiom check that this option is now
    set using

    )set function compile

   You will see that 'on' is the new default.

Let me know if you have any trouble with this.

\start
Date: Tue, 14 Aug 2007 12:27:28 +0200
From: Ralf Hemmecke
To: Bill Page
Subject: Re: "has" and "with" (was curious algebra failure)
Cc: Gabriel Dos Reis

> Ok. How do tell Aldor that I do not care about the name I am only
> interested in the anonymous body of a given category definition? I
> thought I understood this, but I guess not. The discussion of the
> 'define' keyword in the AUG lead me to believe that that was what was
> implied by it's use.

> If I pass a category as a parameter to a constructor, e.g.
> 
>   define D: Category == with
>      f: % -> %
> 
>   C(X:Category):Category == with
>     if Integer has X then
>       ...
> 
>   A:C(D)

> does X represent the named category (D) or just it's category-value
> (with f: %-> %)? Does the meaning of X change if we omitted the
> 'define' keyword?

> Can you explain to me how I can use this? Or what to read? :-)

Oh, I would nearly have said, you got me. But here is how you can do it.
Anyway, your are right, that "define" needs some more clarification.

woodpecker:~/scratch>aldor -grun -laldor aaa.as
Nil
Nil
-1
-2

woodpecker:~/scratch>aldor -grun -laldor -DNAMED aaa.as
"aaa.as", line 27:   stdout << (foo(d)::Integer) << newline;
                    .............^
[L27 C14] #1 (Error) There are no suitable meanings for the operator `foo'.


Add "-fasy" to the command line and investigate the .asy file. You will 
see that indeed D will be tested in the "if" statement of Cat if you say

Dom: Cat D == add ...

I am not sure whether that makes you happy, but I haven't used such a 
construction before (category in an argument + conditional in terms of 
that category).

Ralf

PS: Don't ask me why the compiler spits out the two "Nil"s (at compile 
time). Anybody from Aldor.org knows?


---BEGIN aaa.as
#include "aldor"
#include "aldorio"
macro SIG == with {-: % -> %}
define D: Category == SIG;
Cat(X: Category): Category == with {
   if Integer has X then {foo: % -> %}
   new: Integer -> %;
   coerce: % -> Integer;
}
#if NAMED
Dom: Cat D == add {
#else
Dom: Cat SIG == add {
#endif
   Rep == Integer;
   import from Rep;
   new(i: Integer): % == per i;
   coerce(x: %): Integer == -rep(x);
   foo(x: %): % == per(2*rep(x));
}
main():() == {
   import from Integer, Dom;
   d: Dom := new 1;
   stdout << (d::Integer) << newline;
   stdout << (foo(d)::Integer) << newline;
}
main();
---END aaa.as

\start
Date: Tue, 14 Aug 2007 12:41:46 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

> | > Rather I mean `coercible'.  For example an expression of type Integer
> | > is coercible to Float because Float exports the following function
> | > 
> | >      coerce : Integer -> % 
> | 
> | That is exactly what Aldor does *not* do. It never applies "coerce" if one
> | doesn't explicitly call for it. At the moment I find Aldor much better in this
> | respect. You should consider that some people might implement a function that
> | is not a nice "coerce" (although their function carries this name).
> 
> I don't think there is anything we can do about that.  We can't police
> people that name coerce a function that does pretend.  Sometimes that is
> bad, sometimes that is good.

I've stated my concerns. What else can I do?

I was happy that automatic coercion went away when I switched from Axiom 
to Aldor. I don't want to go back.

Yet another reason against auto coercion.
There might be a situation when coerce: A->B is needed and none is in 
scope but there were coercions available such that A->X->B or A->Y->B.
We all want that both compositions yield the same result. Now let's 
suppose we enforce that (at least in the documentation). There is still 
the issue of efficiency. The path over X might be more costly than the 
path over Y. Which one does the compiler choose and how can you see that 
from the source code?

I like this extra bit of redundancy in the code. It is good for people 
who are not the authors. (And it probably makes compilation faster.)

\start
Date: Tue, 14 Aug 2007 06:00:05 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

On Tue, 14 Aug 2007, Ralf Hemmecke wrote:

| > | > Rather I mean `coercible'.  For example an expression of type Integer
| > | > is coercible to Float because Float exports the following function
| > | > 
| > | >      coerce : Integer -> % 
| > | 
| > | That is exactly what Aldor does *not* do. It never applies "coerce" if one
| > | doesn't explicitly call for it. At the moment I find Aldor much better in
| > | this
| > | respect. You should consider that some people might implement a function
| > | that
| > | is not a nice "coerce" (although their function carries this name).
| > 
| > I don't think there is anything we can do about that.  We can't police
| > people that name coerce a function that does pretend.  Sometimes that is
| > bad, sometimes that is good.
| 
| I've stated my concerns. What else can I do?
| 
| I was happy that automatic coercion went away when I switched from Axiom to
| Aldor. I don't want to go back.

Notice that if coercions are required to be explicitly spelled out,
people writing non-"nice" coerces will still get away.  

I'm not saying all coercions are good.

However, I'm not at all convinced that requiring everything single
coercion to be written explicitly is either a necessary or a sufficien
condition for correctness.  This debate is not new to me -- remember I come
from C++ world?  I'm familiar with most of the arguments you've developed.

Notice also that in Aldor, I believe you still have coercions between
types.

| Yet another reason against auto coercion.
| There might be a situation when coerce: A->B is needed and none is in scope
| but there were coercions available such that A->X->B or A->Y->B.

If both are in scope, I would say the compiler should report ambiguity.
Furthermore, in a "sane" environment, they should all be semantically
equivalent.  But, there is nothing we can do for that.

| We all want that both compositions yield the same result. Now let's suppose we
| enforce that (at least in the documentation). There is still the issue of
| efficiency. The path over X might be more costly than the path over Y. Which
| one does the compiler choose and how can you see that from the source code?

As I said above, this is a case where given those 'syntactic' equal choicese
(syntactic, because the compiler has no idea of the runtime properties), the
compiler should report ambiguity.

| I like this extra bit of redundancy in the code. It is good for people who are
| not the authors. (And it probably makes compilation faster.)

Are you sure the coercion step is a performance bottleneck for real
applications?

\start
Date: 14 Aug 2007 13:48:30 +0200
From: Martin Rubey
To: Gabriel Dos Reis
Subject: Re: [Aldor-l] "has" and "with" (was curious algebra failure)

My personal preference is:

* no automatic coercion in the compiler

* automatic coercion (as intelligent as possible, possibly even several steps,
  i.e., assuming that all coercion paths yield the same result, although this
  will sometimes not be true in reality) in the interpreter

When writing library code, the extra pain to write down the coercion is really
worth the effort.  The combinat experience was much more pleasant than the
Guess experience, in this particular point.

Using the Aldor interpreter however is a pain for me.

DISCLAIMER: personal, subjective opinion.  Still I hope they will be taken into
account.

\start
Date: Tue, 14 Aug 2007 18:05:23 +0200
From: Ralf Hemmecke
To: Franz Lehner
Subject: Re: Another strange coercion

This is a multi-part message in MIME format.
--------------050602020605080809040402

Please find attached a little modification of your code.
Unfortunately, I am still unable to use "embed1".

(4) -> Z2:=CyclicGroup(2,'a)
    (4)  CyclicGroup(2,a)
                           Type: Domain
(5) -> Z3:=CyclicGroup(3,'b)
    (5)  CyclicGroup(3,b)
                           Type: Domain
(6) -> G:=FreeProductMonoid(Z2,Z3)
(6) ->
    (6)  FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))
                           Type: Domain
(7) -> a:Z2 := generator()
          1
    (7)  a
                           Type: CyclicGroup(2,a)
(8) -> b:Z3 := generator()
          1
    (8)  b
                           Type: CyclicGroup(3,b)
(9) -> ga:G := embed1 a
(9) -> ga:G := embed1(a)$G
(9) ->

    >> System error:
    The function NIL is undefined.

I currently have no idea why that is.

If you always ensure that M1 and M2 are different when 
FreeProductMonoid(M1,M2) is called, then having just

         coerce(m: M1): % == per [[m, 1]];
         coerce(m: M2): % == per [[1, m]];

should be fine. But coercion in FreeProductMonoid(M,M) cannot work for 
obvious reasons.

BTW, I would be really happy if the Aldor/SPAD compiler was able to warn 
if there is a collaps in function signatures for equal parameter domains.

Franz, your original question was for a strange coercion. That "coerce" 
should be removed completely from the code (I have done so). There was 
only one value for which it would succeed.

Ralf


--------------050602020605080809040402
 name="free.as"
 filename="free.as"

#include "axiom"
define FreeProductCategory(M1: Monoid, M2: Monoid):Category == with {
        embed1: M1 -> %;
        embed2: M2 -> %;
        length:% -> Integer;
}

---rhx: "+++" Documentation must come before the identifier they refer to.

+++ FreeProductMonoid(M1,M2) ist the free product of the
+++ monoids M1 and M2
+++ where the neutral elements are identified
+++ Representation by two lists of factors:
+++ factors1 = [a1,a2,a3,...,am] and factors2 = [b1,b2,b3,...,bm]
+++ corresponds to the element a1*b1*a2*b2*a3*b3*...*am*bm
+++ a1 and bm are possibly the neutral element
+++ the neutral element is represented by [[1@M1] [1@M2]]
FreeProductMonoid(
    M1: Monoid,
    M2: Monoid
): Join(FreeProductCategory(M1, M2), Monoid) == add {
	Pair == Record(m1: M1, m2: M2);
        Rep == List Pair;
	import from Pair, Rep;
	m1(p: Pair): M1 == p.m1;
	m2(p: Pair): M2 == p.m2;

        1: % == per [];
        one?(x: %): Boolean == empty? rep x;
        embed1(m: M1): % == per [[m, 1]];
        embed2(m: M2): % == per [[1, m]];
        (x: %) = (y: %): Boolean == rep x = rep y;
	local coerce(p: Pair): OutputForm == {
		one? m1 p => (m2 p)::OutputForm;
		one? m2 p => (m1 p)::OutputForm;
		(m1 p)::OutputForm * (m2 p)::OutputForm;
	}
        coerce(x: %): OutputForm == {
                one? x => outputForm(1$Integer);
		import from Symbol, List OutputForm;
                infix("*"::Symbol::OutputForm, [p::OutputForm for p in rep x]);
        }
        (x: %) * (y: %): % == {
		one? x => y;
		one? y => x;
		xx := reverse rep x;
		yy := rep y;
		px := first xx;
		py := first yy;
		if one? m1 py then {
			yy := cons([m1 px, m2 px * m2 py], rest yy);
			xx := rest xx;
		} else if one? m2 px then {
			yy := cons([m1 px * m1 py, m2 py], rest yy);
			xx := rest xx;
		}
		for p in xx repeat yy := cons(p, yy);
                per yy;
        }

        length(x: %): Integer == {
		one? x => 0;
		xx: Rep := rep x;
		--rhx: I have no idea how to convert NNI to INT.
		n: Integer := (#xx)*(1$Integer);
                if one? m1 first xx then n := n-1;
                if one? m2 last  xx then n := n-1;
                n;
        }        
}


--------------050602020605080809040402
 name="cyclic.as"
 filename="cyclic.as"

#include "axiom"
CyclicGroup(n: PositiveInteger, g: Symbol): Group with {
        1: %;
        coerce : % -> OutputForm;
        one?: % -> Boolean;
--        genrtr: %;
--rhx: Never abbreviate!!! In Aldor you could use 
	generator: () -> %;
--rhx: but unfortunately AXIOM cannot work with it. :-(
--	gen: () -> %;
} == add {
        Rep == Integer;
        import from Integer;
        1: % == per 0;
        generator(): % == per 1;
        coerce(x: %): OutputForm == {
                one? x => (1$Integer)::OutputForm;
                g :: OutputForm ** (rep x)::OutputForm;
        };
        (x:%) * (y:%): % == per addmod(rep x,rep y,n::Integer);
        (x:%) = (y:%): Boolean == rep x = rep y;
        one?(x: %): Boolean == zero? rep x;
        inv(x: %): % == {
		one? x => 1;
		per(n::Integer - rep x)
	}
}

--------------050602020605080809040402--

\start
Date: Tue, 14 Aug 2007 15:39:32 -0400
From: William Sit
To: Martin Rubey
Subject: Re: [Aldor-l] "has" and "with" (was curious algebrafailure)
Cc: Gabriel Dos Reis

Martin Rubey wrote:

> My personal preference is:
>
> * no automatic coercion in the compiler

In principle, I agree with this. The source of library code should be
unambiguous (in addition to well-documented).  In practice, it would
be nice if there is some help, such as spitting out possible coercion
paths when explicit coercions (there being no other type under this
policy) are not specified or ambiguous due to identical signatures
(hence, a similar help should be given for package calls). My Spad
experience has been that, conservatively estimating, over 70% of
coding time is on coercions and perhaps 10% of time to find and
specify the package calls. So any type of assistance, whether you call
it automatic or not, will be much appreciated.

> * automatic coercion (as intelligent as possible, possibly even several steps,
>   i.e., assuming that all coercion paths yield the same result, although this
>   will sometimes not be true in reality) in the interpreter

I don't believe there should be two different strategies (or standards
if you will), one for compiler and one for interpreter. If people find
automatic coercion in the interpreter convenient and useful say 90% of
the time, that saves time in developing code. (There are plenty of
empirical evidence: the popularity of Maple and Mathematica in casual
as well as serious computations.) Having a different strategy is the
cause of all the "pain" when a fully tested interpreter code is turned
into Spad because it would not be accepted by the compiler (that is
where the over 70% of time of code development is spent). I would
prefer the compiler also "preprocesses" source code, perhaps reporting
(much like ")set mess bot on" in the Axiom interpreter) its choices
and ideally, in a supporting editor, allows the programmer to decide
to accept or not. The Axiom language should be one, not two.  We learn
through repetitions. This will significantly lower the slopes of the
learning curve.

For diehard users, there is no prohibition for them to explicitly call
coercions or packages.

The problem of different paths of coercions between two given domains
has to be dealt with separately, from a general policy to enforce
commutativity of diagrams (in the sense of Category Theory). It is not
just a problem on coercion maps. A database of commutative diagrams
need to be maintained. It is a very important part of constructive
algebra (which is partly based on algorithms for universal objects).

> When writing library code, the extra pain to write down the coercion is really
> worth the effort.  The combinat experience was much more pleasant than the
> Guess experience, in this particular point.

No, "pain" should not be the norm (and definitely, not "extra pain"),
but rather the metric. Intuitively, positive experience can only be
assured when there is less pain.

> Using the Aldor interpreter however is a pain for me.

For me, translating Spad code accepted by the Axiom interpreter into
Spad code accepted by the compiler is a pain. Either require explicit
coercions and calls in both the compiler and interpreter, or provide
the SAME verifiable/selectable assistance in both cases.

\start
Date: Tue, 14 Aug 2007 17:10:07 -0400
From: Bill Page
To: William Sit
Subject: Re: [Aldor-l] "has" and "with" (was curious algebrafailure)
Cc: Gabriel Dos Reis

On 8/14/07, William Sit wrote:
> ...
> For me, translating Spad code accepted by the Axiom interpreter into Spad code
> accepted by the compiler is a pain. Either require explicit coercions and calls in
> both the compiler and interpreter, or provide the SAME verifiable/selectable
> assistance in both cases.
>

I am inclined to agree. To me this means both, making coercions is
Spad more explicit (Like Aldor with only a few well know and
frequently used automatic coercions), and creating a version of the
Axiom interpreter that is equally strict. That said, of course a
strick interpreter might be viewed by some as more painful for the
user, so then there would be even more reason to create an alternate
single-typed (not type-free!) user interface language like BNatural.

\start
Date: Tue, 14 Aug 2007 19:21:56 -0700 (PDT)
From: Cliff Yapp
To: list
Subject: ASDF-Literate v0.1

With many thanks to Steve for his unfailing support, good advice, and
endless patience I would like to announce that we have a beta version
of ASDF-Literate working - the Another System Definition Facility
utility commonly used for easy handling of libraries in modern Lisp
systems.

There are still a fair number of kinks to be worked out and the
documentation needs a good going over, but I am able to use asdf to
tangle, weave, compile, load and latex pamphlet files in defsystem
definitions.  This version uses the new Axweb tool and defines a lisp
replacement for the document command.

Primary TODO:

1.  Make :depends-on function as expected.
2.  Additional robustness testing
3.  Add worked example to documentation.

Currently it is functioning on sbcl and the latest ANSI gcl.  It uses
two external packages - ASDF (of course) and MD5 (a.k.a cl-md5).

Those interested can see the current beta files at:

http://portal.axiom-developer.org/Members/starseeker/asdfliterate/asdf-literate.lisp.pamphlet/download
http://portal.axiom-developer.org/Members/starseeker/clexttex/cl-exttex.lisp.pamphlet/download

\start
Date: Wed, 15 Aug 2007 00:42:31 -0400
From: Bill Page
To: list
Subject: Re: Lisp in Small Pieces

I guess the pieces were'nt small enough. :-)

Now what am I going to do with a $10 CAD certificate? I always buy
from amazon.com!

Maybe if we all pooled our certificates we could buy someone like
Cliff a used copy. ;-)

Cheers,
Bill Page.

On 8/15/07, Amazon.ca Customer Service <order-update@amazon.ca> wrote:
> (Vous trouverez la version francaise de ce courriel au bas de la
> page.)
>
> Greetings from Amazon.ca.
>
> We regret to inform you that an error caused the following item(s) to
> be displayed at an incorrect price:
>
> ------------------------------------------------------------------
> Lisp in Small Pieces
> ------------------------------------------------------------------
>
> In accordance with our posted policies on pricing, we're unable to
> offer items that have an incorrectly posted price.  Therefore, we have
> cancelled this item from your order.
>
> We realize we can't make up for the inconvenience and disappointment
> caused by this error, however, we'd like to offer you a $10 gift
> certificate that you may use toward a future order at
> Amazon.ca. Details for using the gift certificate are listed below.
> ...
>=========================================================================
>
> Cher Internaute,
>
> A votre attention de la part d'Amazon.ca.

\start
Date: Wed, 15 Aug 2007 05:54:39 -0700 (PDT)
From: Cliff Yapp
To: Bill Page
Subject: Re: Lisp in Small Pieces

--- Bill Page wrote:

> Well,
> 
> I guess the pieces were'nt small enough. :-)

Heh.  Or there were too many of them - when you're outselling Harry
Potter with a Lisp book you know one of two things - either the AI
winter just definitively ended or something's up with the pricing ;-).
 
> Now what am I going to do with a $10 CAD certificate? I always buy
> from amazon.com!
> 
> Maybe if we all pooled our certificates we could buy someone like
> Cliff a used copy. ;-)

:-).  I'd actually suggest Steve for it if he needs a copy, or maybe
Bill you could use some new book on web programming?  

\start
Date: Thu, 16 Aug 2007 01:35:08 +0200
From: Ralf Hemmecke
To: Bill Page
Subject: Re: [Aldor-l] "has" and "with" (was curious algebrafailure)
Cc: Gabriel Dos Reis

On 08/14/2007 11:10 PM, Bill Page wrote:
> On 8/14/07, William Sit wrote:
>> ...
>> For me, translating Spad code accepted by the Axiom interpreter into Spad code
>> accepted by the compiler is a pain. Either require explicit coercions and calls in
>> both the compiler and interpreter, or provide the SAME verifiable/selectable
>> assistance in both cases.

William, you should really try to experience how it is to program in 
Aldor. Sure you will feel some pain in the beginning, but that will not 
last long. You will love the clarity.

> I am inclined to agree. To me this means both, making coercions is
> Spad more explicit (Like Aldor with only a few well know and
> frequently used automatic coercions), and creating a version of the
> Axiom interpreter that is equally strict. That said, of course a
> strick interpreter might be viewed by some as more painful for the
> user, so then there would be even more reason to create an alternate
> single-typed (not type-free!) user interface language like BNatural.

Right, that would be my path, too. Interpreter and compiler language are 
identical and identically strict. No auto-coercions.

But what is now called "Axiom Interpreter" is not that what I meant 
here. I rather used "interpreter" in the sense of PASCAL interpreter vs. 
PASCAL compiler.

The Axiom Interpreter should be replaced by something like BNatural. But 
here again, it will happen that programs that are written using 
BNatural, cannot easily be translated into pure library code suitable 
for the compiler, since BNatural would be designed to do a lot of 
guessing in order to assist the user. If in BNatural you use something 
like "Expression Integer" you would not want to use that for an actual 
library code. Library code should be clean and make the experiments and 
experiences that are gained with BNatural into clear algorithms over 
well defined domains.

Note that when you switch from "experiment" (=BNatural framework) to 
writing it down in a library, you have to come up with a good 
documentation anyway. Of course, I would not like to see a documentation 
of *your experimental code*, I would only accept if you tell me the 
theorems, definitions, motivations, etc. And if you do that, sure you 
rewrite your original BNatural experiment. You cannot expect that it 
will be painless to implement library code from fuzzy experimental code. 
(Experimental) Code that "just works" is not enough.

\start
Date: 16 Aug 2007 09:01:11 +0200
From: Martin Rubey
To: William Sit
Subject: Re: [Aldor-l] "has" and "with" (was curious algebrafailure)
Cc: Ralf Hemmecke, Gabriel Dos Reis

I do not know yet what Bnatural is.  But if the axiom interpreter does not
provide automatic coercions and type guessing, you might as well throw it
away.  As Ralf already pointed out, no matter what language you use for
scripting - be it Bnatural (whatever that is) or the current axiom scripting
language - it will never be straightforward to move a script into the library.

In fact, I do not even understand why this is a problem: libraries will, in
most cases be designed quite differently from scripts (if the latter are
"designed" at all).

I have used Aldor, SPAD, the Aldor interpreter and the axiom interpreter quite
intensively, and found the combination Aldor + axiom interpreter formidable.

What I found most impressive is that the axiom interpreter is designed well
enough to work seamlessly with new packages.  A simple example: I have written
operations

   [4] (List Fraction Integer,List GuessOption) -> List Record(function
            : Expression Integer,order: NonNegativeInteger)
            from GuessInteger
   [6] Symbol -> ((List Fraction Integer,List GuessOption) -> List 
            Record(function: Expression Integer,order: NonNegativeInteger))
            from GuessInteger
            if Fraction Integer has RETRACT SYMBOL and Integer has 
            RETRACT SYMBOL
   [10] (List Fraction Polynomial Integer,List GuessOption) -> List 
            Record(function: Expression Integer,order: NonNegativeInteger)
            from GuessPolynomial
   [12] Symbol -> ((List Fraction Polynomial Integer,List GuessOption)
             -> List Record(function: Expression Integer,order: 
            NonNegativeInteger))
            from GuessPolynomial
            if Fraction Polynomial Integer has RETRACT SYMBOL and 
            Polynomial Integer has RETRACT SYMBOL

and it is quite sufficient to type

  guessRat [1,2,3,4]

  guessRat(q) ([1,q,q^2,q^3], [])

  guessRat [1,q,q^2,q^3]

  guess([1,2,6,24], [guessRat], [guessProduct])

and, probably most interestingly

(1) -> )se me bo on
(1) -> l: List EXPR INT := [1,2,3,4]

   (1)  [1,2,3,4]
                                                Type: List Expression Integer
(2) -> guessRat l
 Function Selection for guessRat
      Arguments: LIST EXPR INT 
   -> no function guessRat found for arguments LIST EXPR INT 

 Function Selection for map by coercion facility (map) 
      Arguments: ((EXPR INT -> INT),LIST EXPR INT) 
      Target type: LIST INT 
 
 [1]  signature:   ((EXPR INT -> INT),LIST EXPR INT) -> LIST INT
      implemented: slot (List (Integer))(Mapping (Integer) (Expression (Integer)))(List (Expression (Integer))) from LIST2(EXPR INT,INT)
 

 Function Selection for guessRat
      Arguments: LIST INT 
 
 [1]  signature:   LIST FRAC INT -> LIST Record(function: EXPR INT,order: NNI)
      implemented: slot (List (Record (: function (Expression (Integer))) (: order (NonNegativeInteger))))(List (Fraction (Integer))) from GUESSINT
 [2]  signature:   LIST FRAC POLY INT -> LIST Record(function: EXPR INT,order: NNI)
      implemented: slot (List (Record (: function (Expression (Integer))) (: order (NonNegativeInteger))))(List (Fraction (Polynomial (Integer)))) from GUESSP
 

 Function Selection for map by coercion facility (map) 
      Arguments: ((INT -> FRAC INT),LIST INT) 
      Target type: LIST FRAC INT 
 
 [1]  signature:   ((INT -> FRAC INT),LIST INT) -> LIST FRAC INT
      implemented: slot (List (Fraction (Integer)))(Mapping (Fraction (Integer)) (Integer))(List (Integer)) from LIST2(INT,FRAC INT)
 

   (7)  [[function= n + 1,order= 0]]
    Type: List Record(function: Expression Integer,order: NonNegativeInteger)

I.e., the interpreter realizes that we have a list of INT's (although it is
typed as list of EXPR INT's), and thus uses guessRat$GUESSINT instead of
guessRat$GUESSP.  This situation is quite common in my research, since very
very often the "numbers" (or polynomials) I want to guess formulas for are
coefficients of some Taylor series expansions or more complicated things, and
are only by mathematical coincidence integers.

If you want axiom to use GUESSP you can type

  guessRat(l)$GUESSP

of course.

\start
Date: Thu, 16 Aug 2007 06:11:42 -0400
From: William Sit
To: Martin Rubey
Subject: Re: [Aldor-l] "has" and "with" (was curious algebrafailure)
Cc: Ralf Hemmecke, Gabriel Dos Reis

Martin Rubey wrote:

> I have used Aldor, SPAD, the Aldor interpreter and the axiom interpreter quite
> intensively, and found the combination Aldor + axiom interpreter formidable.
>
> What I found most impressive is that the axiom interpreter is designed well
> enough to work seamlessly with new packages.

Since you do find the axiom interpreter helpful and indeed getting the
types right (your examples are not particularly impressive to me
because the names and signatures are quite unique and only the
arguments need be matched), why aren't you and Ralf in favor of
improving the compiler so that the compiler can be equally helpful?
Why should the human programmer be forced to manually perform what the
interpreter is doing so well (and most likely can be even improved)?
Currently, to translate from interpreter language to compiler
language, one needs a combination of ")show," ")display," ")set mess
bottom on," ")set message auto on," and hyperdoc searches to identify
packages and coercions. This process is repeated every time there is a
compiler complaint. This is time that could be spent for documentation
instead.

Thu, 16 Aug 2007 01:35:08 +0200
Ralf Hemmecke wrote:

> Interpreter and compiler language are
> identical and identically strict. No auto-coercions.

> You cannot expect that it will be painless to implement library
> code from fuzzy experimental code.

Why not? All code is experimental until it is final and
frozen. Documentation is constantly being added and revised. I don't
consider documentation "pain," because it is necessary. I do consider
spending time to rewrite interpreter code into compiler code a waste
of time and therefore "pain". (Compare this with the pain associated
with style changes for bibliography items when bibtex is not used.) As
long as the interpreter language (what you call experimental language)
and the compiler (or library) language are one and the same, the pain
level would be reduced substantially (to zero if the two are 100%
compatible).  Of course, we should not let the compiler "guess" like
the interpreter currently does, but the compiler can "help" to provide
a set of choices and recommended selections (much like a spell-checker
presents a list of alternatives to let the writer select or
decline). So in my dream editor for Axiom, there will be a pull down
menu to "type-check" and "package-check". This "help" should be the
same whether one is "experimenting" or writing library code (and
ideally, even when writing a pamphlet if pamphlet is the de facto
source) . This help need not be "automatic" as in the current
interpreter. In all other languages I have experience, the
"experimental" and the library languages are one (Maple, Mathematica
for example).

> William, you should really try to experience how it is to program in
> Aldor. Sure you will feel some pain in the beginning, but that will not
> last long. You will love the clarity.

Clarity is achieved by the programmer, not by the language and Axiom
code can be just as clear as Aldor code. What the Aldor compiler does
better is its better diagnostics and arguably a more expressive
language. Learning a new language is not "pain." For Aldor, the "pain"
comes from missed Axiom algebra libraries and incompatibilities (much
like between Maple and Mathematica).

I was at IBM Research when the new compiler for the precursor A# of
Aldor was written. At that time, I was using Scratchpad II, the old
compiler, which was roughly the same as the current Axiom compiler. I
was able to write my programs without knowing lisp, but there were
bugs and design-related suggestions that the team would not fix or
modify because it was working on the new language and compiler. I
mention this because I am afraid the same thing may happen again:
instead of fixing the problems, it would be more fun (and probably
easier to obtain grants and publish papers) to start a new language,
promising to be better. Certainly, there are good reasons to do that,
too, especially if the problems are due to poor design rather than
implementation. Nonetheless, a new language that is not 100% backward
compatible and without automatic conversion facilities alienates the
earlier programmers and obsoletes the old code base. The three
incompatibles (interpreter, Spad compiler, Aldor compiler) are, I
believe, the main reasons why the commercial version did not receive
wider popularity. This triad of languages becomes confusing to most
users, old or new. The few gurus, with due respects and admirations,
are great hackers (in addition to being excellent mathematicians and
computer scientists).

But hacking is only a good skill to find bugs or get a program
working, not essential, and indeed, may even be detrimental, to write
readable programs. Hacked code distracts and hides the natural flow of
mathematical or computational ideas. It would make documentation
"extra painful" to write, and thus often, not written.

The question is: do we want Axiom/Aldor to remain the havens for
hackers or make it palatable to general researchers, whose hacking
skills and stamina may be, on average, much less?

\start
Date: Thu, 16 Aug 2007 12:17:33 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with"

> | >        Now the compiler goes on typecheking the defnition x ** n.
> | >        It sees the use of expt() and find out that the only expt() in
> | >        scope if the one from RepeatedSquare(S).  Then it tries
> | >        to instantiate that package -- just like a function call.
> | >        From there, it applies the usual rules:  Can I coerce S of
> | >        type Monad to the expected argument type of RepeatedSquare()?
> | >        They answer comes out as "no".  Hence the error.
> | 
> | Well, of course the answer should be "yes".
> 
> It is not clear to me why the answer should *of course" be "yes".

We have

RepeatedSquaring(S): Exports == Implementation where
    S: SetCategory with
	"*":(%,%)->%
    Exports == with
      expt: (S,PositiveInteger) -> S
    Implementation == add ...

and furthermore

Monad(): Category == SetCategory with
       "*": (%,%) -> %
       ...
     add
       import RepeatedSquaring(%)
       x:% ** n:PositiveInteger == expt(x,n)
       rightPower(a,n) == ...
       leftPower(a,n) == ...


This should behave approximately like

---BEGIN aaa.as
#include "aldor"
macro SetCategory == PrimitiveType;
RepeatedSquaring(S: SetCategory with {*: (%,%)->%}): with {
	expt: (S, Integer) -> S;
} == add {
	expt(s: S, i: Integer): S == s; -- dummy implementation
}

Monad(): Category == SetCategory with {
	*: (%,%) -> %;
     default {
#if DoesntWork
	import from RepeatedSquaring(%);
	(x:%) ** (n:Integer): % == expt(x,n);
#else
	(x:%) ** (n:Integer): % == expt(x,n)$RepeatedSquaring(%);
#endif
     }
}
---END aaa.as

woodpecker:~/scratch>aldor -laldor aaa.as
woodpecker:~/scratch>aldor -laldor -DDoesntWork aaa.as
"aaa.as", line 14:         (x:%) ** (n:Integer): % == expt(x,n);
                    ...................................^
[L14 C36] #1 (Error) There are no suitable meanings for the operator `expt'.

Well. In fact, I would have liked that the Aldor compiler also works for 
the second case. Clearly "expt: (%, Integer) -> %" is in scope since it 
was just imported via the import statement. I consider that a bug in the 
Aldor compiler.

% as the argument of RepeatedSquaring stands for a domain of type 
Monad(). Such a domain obviously satisfies

   SetCategory with {*: (%,%)->%}

since Monad() has these exports (and more in the Axiom library case).

The compiler should check whether the type of % exports SetCategory. Yes 
it does, since Monad() exports it.

The compiler should check whether the type of % exports

   *: (%,%)->%

. Yes it does, since Monad() exports it.

Now why I believe that the SPAD compiler returns "false" is the following.

SPAD does not have "default". Implementations of a category are 
implemented by a private domain (therefore the "add" instead of 
"default" in SPAD). Now if I take the definition of the AUG about what 
the type of "add {...}" is, then, of course the % in RepeatedSquaring of

     add
       import RepeatedSquaring(%)
       x:% ** n:PositiveInteger == expt(x,n)
       rightPower(a,n) == ...
       leftPower(a,n) == ...

(see naalgc.spad.pamphlet)
does *not* export

   *: (%,%)->%

and therefore the instantiation of RepeatedSquaring(%) must fail.

Gaby, you have given in

http://lists.nongnu.org/archive/html/axiom-developer/2007-08/msg00412.html

how the "add" part in the Monad definition is translated to a private 
domain. That looks perfectly fine to me.
Bill has already shown that a proper value for the argument of 
RepeatedSquaring as in

http://wiki.axiom-developer.org/SandBoxMonad

works fine.

Gaby, you write there:

        Now the compiler goes on typecheking the defnition x ** n.
        It sees the use of expt() and find out that the only expt() in
        scope if the one from RepeatedSquare(S).  Then it tries
        to instantiate that package -- just like a function call.
        From there, it applies the usual rules:  Can I coerce S of
        type Monad to the expected argument type of RepeatedSquare()?
        They answer comes out as "no".  Hence the error.

Why would the compiler want to "coerce" if all that is needed is to 
check whether S of type Monad has at least the exports that are required 
by the argument type of RepeatedSquaring. (And it has.) I don't see a 
need for coercion at all.

\start
Date: Thu, 16 Aug 2007 12:23:30 +0200
From: Ralf Hemmecke
To: Bill Page
Subject: SubDomain in SPAD and not in Aldor
Cc: Gabriel Dos Reis

> No. subdomain is already part of Spad. Spad implements things this way
> but Aldor does not. If I am discussing changing anything it would be
> Aldor not Spad.

Bill, I hope I can convince you otherwise during the Aldor meeting or we 
can work out something better.

But writing

PositiveInteger == SubDomain(Integer, #1 > 0)

or something similar only *looks* nicer than it actually is. I do not 
think that there is any gain from keeping SubDomain in the SPAD language.

Let's report about this after the workshop.

\start
Date: Thu, 16 Aug 2007 12:52:53 +0200
From: Ralf Hemmecke
To: William Sit
Subject: .spad, .input, .as and autocoercion
Cc: Gabriel Dos Reis

On 08/16/2007 12:11 PM, William Sit wrote:
> Martin Rubey wrote:
> 
>> I have used Aldor, SPAD, the Aldor interpreter and the axiom 
>> interpreter quite intensively, and found the combination Aldor + 
>> axiom interpreter formidable.
>> 
>> What I found most impressive is that the axiom interpreter is 
>> designed well enough to work seamlessly with new packages.
> 
> Since you do find the axiom interpreter helpful and indeed getting 
> the types right (your examples are not particularly impressive to me 
> because the names and signatures are quite unique and only the 
> arguments need be matched), why aren't you and Ralf in favor of 
> improving the compiler so that the compiler can be equally helpful?

Because I believe we will end up in something like Maple or Mathematica.
I constantly hear people complain that they don't understand what
Mathematica is actually doing internally.

> Why should the human programmer be forced to manually perform what 
> the interpreter is doing so well (and most likely can be even 
> improved)?

You say it. The interpretation of your source code depends on the
capabilities of the "interpreter". That is like saying

simplify(someexpression)

in Maple which doen't simplify anything in Maple6 but does something in
Maple11.

> Currently, to translate from interpreter language to compiler
> language, one needs a combination of ")show," ")display," ")set mess
> bottom on," ")set message auto on," and hyperdoc searches to identify
> packages and coercions. This process is repeated every time there is
> a compiler complaint. This is time that could be spent for
> documentation instead.

If you simply make your experimental code into something that SPAD
understands than you are missing the *design* phase.

> Thu, 16 Aug 2007 01:35:08 +0200 Ralf Hemmecke wrote:

>> Interpreter and compiler language are identical and identically 
>> strict. No auto-coercions.
> 
>> You cannot expect that it will be painless to implement library 
>> code from fuzzy experimental code.

> Why not? All code is experimental until it is final and frozen.

I believe that it is good to have a system that let's you experiment
with objects and lets you invent new algorithms. But once you have an
idea how that should actually work you should make the input/output
specification clear. That for example will most probably rule out the
use of "Expression Integer" in library code. There will be most
certainly be domains that are more specific for the implementation of
the algorithm that you have just invented.

> Documentation is constantly being added and revised. I don't consider
>  documentation "pain," because it is necessary. I do consider
> spending time to rewrite interpreter code into compiler code a waste
> of time and therefore "pain".

Being also a mathematician, I clearly understand your point. But
Computer Algebra deals with constructive mathematics. And there is a lot
more to tell a stupid computer. If some day we arrive at a system that
can translate fuzzy experimental code into nicely specified and
efficient library code, then I am on your side. But this is probably a
big research topic.

> (Compare this with the pain associated with style changes for
> bibliography items when bibtex is not used.) As long as the
> interpreter language (what you call experimental language) and the
> compiler (or library) language are one and the same, the pain level
> would be reduced substantially (to zero if the two are 100%
> compatible).  Of course, we should not let the compiler "guess" like
> the interpreter currently does, but the compiler can "help" to
> provide a set of choices and recommended selections (much like a
> spell-checker presents a list of alternatives to let the writer
> select or decline).

The Aldor compiler sometimes tries to help you in such a way. There are
messages like

No function foo: () -> Integer is available but could be used if
imported from SomeFooType.

I certainly have nothing against the compiler listing all the options at
the place of failure. I know what a pain it was to rewrite .input files
into .spad files. That was one of the reasons I stopped writing .input
files in Axiom. Or I should better say, I stopped developing programs
using .input files.

[...]

> The three incompatibles (interpreter, Spad compiler, Aldor compiler)
> are, I believe, the main reasons why the commercial version did not
> receive wider popularity. This triad of languages becomes confusing
> to most users, old or new.

I very much agree. But I still don't want autocoercion. The user 
interface (i.e. type guessing and such -- which corresponds to BNatural) 
should be programmed in a library and should not be part of the 
Aldor/SPAD language.

> But hacking is only a good skill to find bugs or get a program 
> working, not essential, and indeed, may even be detrimental, to write
> readable programs. Hacked code distracts and hides the natural flow 
> of mathematical or computational ideas. It would make documentation 
> "extra painful" to write, and thus often, not written.

> The question is: do we want Axiom/Aldor to remain the havens for 
> hackers or make it palatable to general researchers, whose hacking 
> skills and stamina may be, on average, much less?

I understand your point. And it must be addressed that the ordinary 
mathematician is usually not very knowledgable in programming. But maybe 
that will change in the future. At least a bit. Languages will get 
better and closer to mathematics and people will be more knowledgable 
about computer programming.

\start
Date: Thu, 16 Aug 2007 06:53:12 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: .spad, .input, .as and autocoercion

On Thu, 16 Aug 2007, Ralf Hemmecke wrote:

| On 08/16/2007 12:11 PM, William Sit wrote:
| > Martin Rubey wrote:
| > 
| > > I have used Aldor, SPAD, the Aldor interpreter and the axiom interpreter
| > > quite intensively, and found the combination Aldor + axiom interpreter
| > > formidable.
| > > 
| > > What I found most impressive is that the axiom interpreter is designed
| > > well enough to work seamlessly with new packages.
| > 
| > Since you do find the axiom interpreter helpful and indeed getting the types
| > right (your examples are not particularly impressive to me because the names
| > and signatures are quite unique and only the arguments need be matched), why
| > aren't you and Ralf in favor of improving the compiler so that the compiler
| > can be equally helpful?
| 
| Because I believe we will end up in something like Maple or Mathematica.
| I constantly hear people complain that they don't understand what
| Mathematica is actually doing internally.

Notice that not because people will explicitly write out coercions
means they understand what the compiler is doing internally.

[...]

| > Documentation is constantly being added and revised. I don't consider
| > documentation "pain," because it is necessary. I do consider
| > spending time to rewrite interpreter code into compiler code a waste
| > of time and therefore "pain".
| 
| Being also a mathematician, I clearly understand your point. But
| Computer Algebra deals with constructive mathematics.

Coercions in mathematical programs don't the programs less constructive.

\start
Date: 16 Aug 2007 14:10:10 +0200
From: Martin Rubey
To: William Sit
Subject: Re: .spad, .input, .as and autocoercion
Cc: Ralf Hemmecke, Gabriel Dos Reis

William Sit writes:

> Martin Rubey wrote:
> 
> > I have used Aldor, SPAD, the Aldor interpreter and the axiom interpreter quite
> > intensively, and found the combination Aldor + axiom interpreter formidable.
> 
> Since you do find the axiom interpreter helpful and indeed getting the types
> right (your examples are not particularly impressive to me because the names
> and signatures are quite unique and only the arguments need be matched), why
> aren't you and Ralf in favor of improving the compiler so that the compiler can
> be equally helpful? 

I am *very* much in favour of improving the compiler so that it can be helpful,
but only by giving appropriate hints, as Ralf pointed out already.  Since I
doubt that we will be able to exclude the possibility of having two different
coercion paths, however, I want that code in the library is unambigous, and
cannot be made ambigous by "extend"ing a domain or by adding a package or a
domain.

This problem does not (or hardly) exist in the interpreter, since the axiom
library will probably not change during a mathematical experiment.

> Why should the human programmer be forced to manually perform what the
> interpreter is doing so well (and most likely can be even improved)?

Because experimentation and design are two distinct steps of engineering.

> Currently, to translate from interpreter language to compiler language, one
> needs a combination of ")show," ")display," ")set mess bottom on," ")set
> message auto on," and hyperdoc searches to identify packages and
> coercions. This process is repeated every time there is a compiler
> complaint. This is time that could be spent for documentation instead.

Try using Aldor!  Even with the axiom library, you will find that )sh, )di,
etc. are rarely needed, since the compiler tells you quite exactly what he is
missing.  The combinat experience was very enlightening for me.

\start
Date: Thu, 16 Aug 2007 07:18:28 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with"

On Thu, 16 Aug 2007, Ralf Hemmecke wrote:

| % as the argument of RepeatedSquaring stands for a domain of type Monad().
| Such a domain obviously satisfies
| 
|   SetCategory with {*: (%,%)->%}
| 
| since Monad() has these exports (and more in the Axiom library case).

Please be more precise about "satisfies".  What does it mean?

I understand what it means it terms of "has".

[...]

| Gaby, you have given in
| 
| http://lists.nongnu.org/archive/html/axiom-developer/2007-08/msg00412.html
| 
| how the "add" part in the Monad definition is translated to a private domain.

In fact, there is no nothing private about it.  The rewrite is available
to user.

| That looks perfectly fine to me.
| Bill has already shown that a proper value for the argument of
| RepeatedSquaring as in
| 
| http://wiki.axiom-developer.org/SandBoxMonad
| 
| works fine.
| 
| Gaby, you write there:
| 
|        Now the compiler goes on typecheking the defnition x ** n.
|        It sees the use of expt() and find out that the only expt() in
|        scope if the one from RepeatedSquare(S).  Then it tries
|        to instantiate that package -- just like a function call.
|        From there, it applies the usual rules:  Can I coerce S of
|        type Monad to the expected argument type of RepeatedSquare()?
|        They answer comes out as "no".  Hence the error.
| 
| Why would the compiler want to "coerce" if all that is needed is to check
| whether S of type Monad has at least the exports that are required by the
| argument type of RepeatedSquaring. 

The compiler is doing that because it treats function calls -- either
to produce a value of a type -- uniformly.  It seems to me that you're 
arguing two non-uniform rules: one for value, and one for types.  Is that
correct? 

\start
Date: Thu, 16 Aug 2007 07:28:49 -0500 (CDT)
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: .spad, .input, .as and autocoercion
Cc: Ralf Hemmecke

On Thu, 16 Aug 2007, Martin Rubey wrote:

| > Currently, to translate from interpreter language to compiler language, one
| > needs a combination of ")show," ")display," ")set mess bottom on," ")set
| > message auto on," and hyperdoc searches to identify packages and
| > coercions. This process is repeated every time there is a compiler
| > complaint. This is time that could be spent for documentation instead.
| 
| Try using Aldor!

I tried.  And many other language that take a, I would say "military",
approach to the issue.  Not everything works the same for everybody.
I constantly found that requiring explicit conversions was more of distraction
than help -- that does NOT mean I do not know the problems with implicit 
conversions.  I perfectly understand the arguments for requiring
everything to be written explicitly.  

Even Aldor permits some coercions -- sorry, they are called
"courtesy conversions".

\start
Date: 16 Aug 2007 14:34:20 +0200
From: Martin Rubey
To: Gabriel Dos Reis
Subject: Re: .spad, .input, .as and autocoercion
Cc: Ralf Hemmecke

Gabriel Dos Reis writes:

> Even Aldor permits some coercions -- sorry, they are called
> "courtesy conversions".

Yes.  But do note that they involve only builtin types, as far as I know.  If
for some reason these types would not be builtin anymore, I'd also be in favour
of removing the coercions concerned.

\start
Date: Thu, 16 Aug 2007 07:37:53 -0500 (CDT)
From: Gabriel Dos Reis
To: Martin Rubey
Subject: Re: .spad, .input, .as and autocoercion
Cc: Ralf Hemmecke

On Thu, 16 Aug 2007, Martin Rubey wrote:

| Gabriel Dos Reis writes:
| 
| > Even Aldor permits some coercions -- sorry, they are called
| > "courtesy conversions".
| 
| Yes. But do note that they involve only builtin types, as far as I know. 

I like the principle of giving built-in types and user-defined types 
equal support.

\start
Date: Thu, 16 Aug 2007 09:02:29 -0400
From: William Sit
To: Ralf Hemmecke
Subject: Re: .spad, .input, .as and autocoercion
Cc: Gabriel Dos Reis

Ralf Hemmecke wrote:

> On 08/16/2007 12:11 PM, William Sit wrote:
> > ...  why aren't you and Ralf in favor of
> > improving the compiler so that the compiler can be equally helpful?
>
> Because I believe we will end up in something like Maple or Mathematica.
> I constantly hear people complain that they don't understand what
> Mathematica is actually doing internally.

That is because neither Maple nor Mathematica is open source. Making the
compiler more helpful will not turn Axiom into either of them. Why do you
favor downgrading the interpreter instead of upgrading the compiler? We
already agree that there should be one language. All I ask is that there be
help in programming the language. I did not ask to make the language
"fuzzy".

> > Why should the human programmer be forced to manually perform what
> > the interpreter is doing so well (and most likely can be even
> > improved)?
>
> You say it. The interpretation of your source code depends on the
> capabilities of the "interpreter". That is like saying
>
> simplify(someexpression)
>
> in Maple which doen't simplify anything in Maple6 but does something in
> Maple11.

I don't follow what you are pointing at. You seem to be supporting my
thesis: When there is only one language, there will be NO interpreter, only
options to accept suggested selection or not in the user interface
(preferrably an editor, emacs if you like). Newer versions (as Maple6 vs
Maple11) will only improve the accuracy of the help.

> > Currently, to translate from interpreter language to compiler
> > language, one needs a combination of ")show," ")display," ")set mess
> > bottom on," ")set message auto on," and hyperdoc searches to identify
> > packages and coercions. This process is repeated every time there is
> > a compiler complaint. This is time that could be spent for
> > documentation instead.
>
> If you simply make your experimental code into something that SPAD
> understands than you are missing the *design* phase.

What has this discussion to do with the design phase? Are you implying that
experimental code need no design before hand? That would be a terrible way
to approach Axiom programming. (Recall the lengthy discussion we had for the
Units and Dimension.)

> I believe that it is good to have a system that let's you experiment
> with objects and lets you invent new algorithms. But once you have an
> idea how that should actually work you should make the input/output
> specification clear. That for example will most probably rule out the
> use of "Expression Integer" in library code. There will be most
> certainly be domains that are more specific for the implementation of
> the algorithm that you have just invented.

The way I program in Spad, the .input file is very close to my final Spad
code, except of course, the changes that is forced because of
incompatibility. Here I am referring to mainly packages or algorithms, not
domain or category constructors, which unfortunately, the Axiom interpreter
would not understand. Constructing a skeleton of category and domain is
fairly easy: you need as you say get the input/output and data structure,
and the exports. Implementation of packages is the harder part and can be
"experimented" using .input files.

I don't agree that Expression Integer should not be in library code. If what
you suggest is taken at face value, then Expression domain constructor
simply should be removed. As with any algebra domain, there are implicit
restrictions on their use and when not abused, they work as intended. Of
course, not all restrictions are enforced or enforceable currently. All
computer software are based on protocols.

> > Documentation is constantly being added and revised. I don't consider
> >  documentation "pain," because it is necessary. I do consider
> > spending time to rewrite interpreter code into compiler code a waste
> > of time and therefore "pain".
>
> Being also a mathematician, I clearly understand your point. But
> Computer Algebra deals with constructive mathematics. And there is a lot
> more to tell a stupid computer. If some day we arrive at a system that
> can translate fuzzy experimental code into nicely specified and
> efficient library code, then I am on your side. But this is probably a
> big research topic.

I am not suggesting fuzzy code (experimental or not).

> The Aldor compiler sometimes tries to help you in such a way. There are
> messages like
>
> No function foo: () -> Integer is available but could be used if
> imported from SomeFooType.
>
> I certainly have nothing against the compiler listing all the options at
> the place of failure. I know what a pain it was to rewrite .input files
> into .spad files. That was one of the reasons I stopped writing .input
> files in Axiom. Or I should better say, I stopped developing programs
> using .input files.

Of course when you have become an expert in writing in Aldor or Spad, there
is no need to use the interpreter. Do you think it would be easy for a
newcomer to program directly in Spad, with no help on coercion?

> > The three incompatibles (interpreter, Spad compiler, Aldor compiler)
> > are, I believe, the main reasons why the commercial version did not
> > receive wider popularity. This triad of languages becomes confusing
> > to most users, old or new.
>
> I very much agree. But I still don't want autocoercion. The user
> interface (i.e. type guessing and such -- which corresponds to BNatural)
> should be programmed in a library and should not be part of the
> Aldor/SPAD language.

The fact that you don't want autocoercion should not imply that autocoercion
should be denied others. Providing help does not mean the language is
changed. How to program the help is an implementation issue, not a design
principle.

\start
Date: Thu, 16 Aug 2007 15:26:27 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with"

On 08/16/2007 02:18 PM, Gabriel Dos Reis wrote:
> On Thu, 16 Aug 2007, Ralf Hemmecke wrote:
> 
> | % as the argument of RepeatedSquaring stands for a domain of type Monad().
> | Such a domain obviously satisfies
> | 
> |   SetCategory with {*: (%,%)->%}
> | 
> | since Monad() has these exports (and more in the Axiom library case).
> 
> Please be more precise about "satisfies".  What does it mean?

That was written above. So let me repeat:

Monad() (in Axiom) exports the symbols

(*1*)

   Monad
   SetCategory
   *: (%,%)->%
   rightPower: (%,PositiveInteger) -> %
   leftPower: (%,PositiveInteger) -> %
   **: (%,PositiveInteger) -> %

The requirements of the argument of RepeatedSquaring are

(*2*)

    SetCategory
    *:(%,%)->%

Now "

   Monad
   satisfies
   SetCategory with *:(%,%)->%

means that the (*1*) is a superset of (*2*).

Quote from AUG Section 7.7 "Type satisfaction" (p.83).

   We say that a type S satisfies the type T if any value of type S
   can be used in any context which requires a value of type T.

For example Integer is a value of type Monad (I hope). Integer (or any 
other domain of type Monad) can be used in a place where (*2*) is 
required. Why do I need coercion here? It's just a check that the 
exports of a certain domain are a superset of the required exports.

> I understand what it means it terms of "has".

That is SPAD compiler biased. ;-)

> [...]
> 
> | Gaby, you have given in
> | 
> | http://lists.nongnu.org/archive/html/axiom-developer/2007-08/msg00412.html
> | 
> | how the "add" part in the Monad definition is translated to a private domain.
> 
> In fact, there is no nothing private about it.  The rewrite is available
> to user.
> 
> | That looks perfectly fine to me.
> | Bill has already shown that a proper value for the argument of
> | RepeatedSquaring as in
> | 
> | http://wiki.axiom-developer.org/SandBoxMonad
> | 
> | works fine.
> | 
> | Gaby, you write there:
> | 
> |        Now the compiler goes on typecheking the defnition x ** n.
> |        It sees the use of expt() and find out that the only expt() in
> |        scope if the one from RepeatedSquare(S).  Then it tries
> |        to instantiate that package -- just like a function call.
> |        From there, it applies the usual rules:  Can I coerce S of
> |        type Monad to the expected argument type of RepeatedSquare()?
> |        They answer comes out as "no".  Hence the error.
> | 
> | Why would the compiler want to "coerce" if all that is needed is to check
> | whether S of type Monad has at least the exports that are required by the
> | argument type of RepeatedSquaring. 
> 
> The compiler is doing that because it treats function calls -- either
> to produce a value of a type -- uniformly.  It seems to me that you're 
> arguing two non-uniform rules: one for value, and one for types.  Is that
> correct? 

Hmmm, I would say, I don't completely understand all that, but I tend to 
say "yes".

You cannot achieve that uniformity. Take

define Cat: Category == with;
define Foo(T: Cat): Category == with {};
DomI: Foo(Integer) == add;
DomS: Foo(String)  == add;
b1: Boolean == DomI has Foo(Integer);
b2: Boolean == DomI has Foo(String);
b3: Boolean == DomS has Foo(Integer);
b4: Boolean == DomI has Foo(String);

If you treat domain constructors in the same way as basic values 
(functions) then

   Foo(Integer) = Foo(String) = with {}

So b1, ..., b4 should all be true, right? But I remember faintly that 
you argued about a functional language with respect to the types and 
that you would like to be able to distinguish

   Foo(Integer) from Foo(String)

No? Where would be the uniformity here?

\start
Date: Thu, 16 Aug 2007 08:35:12 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with"

On Thu, 16 Aug 2007, Ralf Hemmecke wrote:

[...]

| You cannot achieve that uniformity. Take
| 
| define Cat: Category == with;
| define Foo(T: Cat): Category == with {};
| DomI: Foo(Integer) == add;
| DomS: Foo(String)  == add;
| b1: Boolean == DomI has Foo(Integer);
| b2: Boolean == DomI has Foo(String);
| b3: Boolean == DomS has Foo(Integer);
| b4: Boolean == DomI has Foo(String);
| 
| If you treat domain constructors in the same way as basic values (functions)
| then
| 
|   Foo(Integer) = Foo(String) = with {}

How is the above is a logical consequence?  
In no way I have tied argument passing semantics to equality.

| So b1, ..., b4 should all be true, right? But I remember faintly that you
| argued about a functional language with respect to the types and that you
| would like to be able to distinguish
| 
|   Foo(Integer) from Foo(String)
| 
| No?

For sure, I would like to distinguish those two.  However, I do not
see how that follows from the semantics of passing arguments in function
calls. 

| Where would be the uniformity here?

The uniformity is in terms of prerequsite of instantiation -- same rules for
everybody. 

\start
Date: Thu, 16 Aug 2007 15:43:45 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with"

> |   Foo(Integer) = Foo(String) = with {}
> 
> How is the above is a logical consequence?  
> In no way I have tied argument passing semantics to equality.

What does that have to do with "argument passing semantics"?

Foo is a function and the resulting values of Foo(Integer) and 
Foo(String) are the same. Very much like foo(0) = foo(1) for
foo(i: Integer): Integer == 1.

So b1 ... b4 should all be true and

Foo(String) is indistinguishable from Foo(Integer).

\start
Date: Thu, 16 Aug 2007 09:02:59 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with"

On Thu, 16 Aug 2007, Ralf Hemmecke wrote:

| > |   Foo(Integer) = Foo(String) = with {}
| > 
| > How is the above is a logical consequence?  In no way I have tied argument
| > passing semantics to equality.
| 
| What does that have to do with "argument passing semantics"?

That was my question.

| Foo is a function and the resulting values of Foo(Integer) and Foo(String) are
| the same.

Why?


| Very much like foo(0) = foo(1) for
| foo(i: Integer): Integer == 1.

but 1 is not String, 1 is not Integer.

| So b1 ... b4 should all be true and
| 
| Foo(String) is indistinguishable from Foo(Integer).

I'm missing the logical reasons for that.

\start
Date: Thu, 16 Aug 2007 16:38:08 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with"

Gabriel Dos Reis wrote:
> On Thu, 16 Aug 2007, Ralf Hemmecke wrote:
> 
> | > |   Foo(Integer) = Foo(String) = with {}
> | > 
> | > How is the above is a logical consequence?  In no way I have tied argument
> | > passing semantics to equality.
> | 
> | What does that have to do with "argument passing semantics"?
> 
> That was my question.

Thank you. Your answer is quite helpful to me. :-(

> | Foo is a function and the resulting values of Foo(Integer) and Foo(String) are
> | the same.
> 
> Why?
> 
> 
> | Very much like foo(0) = foo(1) for
> | foo(i: Integer): Integer == 1.
> 
> but 1 is not String, 1 is not Integer.

Maybe you didn't realize that I wrote foo not Foo.
Let me repeat.

define Cat: Category == with;
define Foo(T: Cat): Category == with {};
DomI: Foo(Integer) == add;
DomS: Foo(String)  == add;
baz(i: Integer): Integer == 1;

I have two functions Foo: Cat -> Category and baz: Integer -> Integer.

Clearly, baz(0) evaluates to 1 and baz(1) also evaluates to 1.
Both values are equal with respect to "=" (used with the semantics
defined in Integer). The argument simply doesn't matter.

Now Foo(Integer) evaluates to

   with {}

and Foo(String) evaluates to

   with {}

There is not definition of equality between categories, but here the
even look identical. So my guess was that they should be treated in the
same way.

My guess therefore is that

   DomI has Foo(Integer)
   DomI has Foo(String)
   DomI has (with {})

should all return the same value, namely true. Again if treated
uniformly with the baz function above, the argument to Foo should not
matter. But it does, and perhaps that is even good.

> | So b1 ... b4 should all be true and
> | 
> | Foo(String) is indistinguishable from Foo(Integer).
> 
> I'm missing the logical reasons for that.

Hmmm, sorry, I seem to annoy you. Anyway, I'll stop explaining things if
I don't get any good explanation of your point of view in return.

\start
Date: Thu, 16 Aug 2007 09:56:31 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with"

On Thu, 16 Aug 2007, Ralf Hemmecke wrote:

| Gabriel Dos Reis wrote:
| > On Thu, 16 Aug 2007, Ralf Hemmecke wrote:
| > 
| > | > |   Foo(Integer) = Foo(String) = with {}
| > | > 
| > | > How is the above is a logical consequence?  In no way I have tied
| > | > argument
| > | > passing semantics to equality.
| > | 
| > | What does that have to do with "argument passing semantics"?
| > 
| > That was my question.
| 
| Thank you. Your answer is quite helpful to me. :-(

Ralf --

   It wasn't an answer.  It was a genuine question that I asked in
the mail you were replying to.

| > | Foo is a function and the resulting values of Foo(Integer) and Foo(String)
| > | are
| > | the same.
| > 
| > Why?
| > 
| > 
| > | Very much like foo(0) = foo(1) for
| > | foo(i: Integer): Integer == 1.
| > 
| > but 1 is not String, 1 is not Integer.
| 
| Maybe you didn't realize that I wrote foo not Foo.

"foo" was a tupo.

| Let me repeat.

I got what you were saying, but it seems to me that you were making
an implicit assumption on "=" that is in no way related to argument
passing.

| define Cat: Category == with;
| define Foo(T: Cat): Category == with {};
| DomI: Foo(Integer) == add;
| DomS: Foo(String)  == add;
| baz(i: Integer): Integer == 1;
| 
| I have two functions Foo: Cat -> Category and baz: Integer -> Integer.
| 
| Clearly, baz(0) evaluates to 1 and baz(1) also evaluates to 1.

So far, I agree.


| Both values are equal with respect to "=" (used with the semantics
| defined in Integer).

Bingo!  Here, you're using "=" from the Integer.  If that operation
were defined to always return false, then you would have reached a
different conclusion.

| The argument simply doesn't matter.

OK.

| Now Foo(Integer) evaluates to
| 
|   with {}
| 
| and Foo(String) evaluates to
| 
|   with {}

I don't think I agree here.

For me:

  *  Foo(Integer) evaluates to a category with empty body ("{ }")
  *  Foo(String) evaluates to another category with empty body ("{ }")

Whether those those two categories are equal in the sense that
"=" returns true is entirely a matter semantics attached to
the "with"-construct.  There is no predefined choice.


| There is not definition of equality between categories,
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It is very important to realize this and spell it out clearly.
Because, there is no fundamental reason why there is none.

| but here the even look identical.
                    ^^^^

"Looking" is not the same as being equal.  


| So my guess was that they should be treated in the  same way.

Well, ne need rules to define equality on objects we manipulate
in programs.  Every definition has its consequences -- pros and 
cons.

In the field of type theory, the notion of equality on types (and modules) 
is a fertile area of research that has been going on for ages.
Search for "manifest types" and "generative types".  Youcan replace
"type" by "modules".

| My guess therefore is that
| 
|   DomI has Foo(Integer)
|   DomI has Foo(String)
|   DomI has (with {})
| 
| should all return the same value, namely true. Again if treated
| uniformly with the baz function above, the argument to Foo should not
| matter. But it does, and perhaps that is even good.
| 
| > | So b1 ... b4 should all be true and
| > | 
| > | Foo(String) is indistinguishable from Foo(Integer).
| > 
| > I'm missing the logical reasons for that.
| 
| Hmmm, sorry, I seem to annoy you.

You're not annoying me.  I'm trying to get all implicit assumptions 
spelled out clearly so that they can be properly analyzed.  In particular,
the compiler will be performing the task as a logical chain of steps.

| Anyway, I'll stop explaining things if
| I don't get any good explanation of your point of view in return.

My point of view is this:  I believe the idea of treating category,
domain, and packages instantiation as function call is a good 
uniform rule.  I also believe that we should further uniformity by
having only one set of rules for function calls -- e.g. we don't
have one rule for values, one for types, and one for whatever.

Notice that, in that view, the notion of value equality is not involved.

\start
Date: Thu, 16 Aug 2007 17:34:54 +0200
From: Ralf Hemmecke
To: Gabriel Dos Reis
Subject: Re: "has" and "with"

Thank you for your answers that was better.
May I continue.

Gabriel Dos Reis wrote:
> I got what you were saying, but it seems to me that you were making
> an implicit assumption on "=" that is in no way related to argument
> passing.

> | define Cat: Category == with;
> | define Foo(T: Cat): Category == with {};
> | DomI: Foo(Integer) == add;
> | DomS: Foo(String)  == add;
> | baz(i: Integer): Integer == 1;
> | 
> | I have two functions Foo: Cat -> Category and baz: Integer -> Integer.
> | 
> | Clearly, baz(0) evaluates to 1 and baz(1) also evaluates to 1.
> 
> So far, I agree.

> | Both values are equal with respect to "=" (used with the semantics
> | defined in Integer).

> Bingo!  Here, you're using "=" from the Integer.  If that operation
> were defined to always return false, then you would have reached a
> different conclusion.

Of course.

> | Now Foo(Integer) evaluates to
> | 
> |   with {}
> | 
> | and Foo(String) evaluates to
> | 
> |   with {}
> 
> I don't think I agree here.
> 
> For me:
> 
>   *  Foo(Integer) evaluates to a category with empty body ("{ }")
>   *  Foo(String) evaluates to another category with empty body ("{ }")

I haven't stated anything else above. Just that I did not say "another".

> Whether those those two categories are equal in the sense that
> "=" returns true is entirely a matter semantics attached to
> the "with"-construct.  There is no predefined choice.

Yes, I understand and agree. I don't even remember that I have seen 
clearly that I have seen a statement in the AUG that says that

   with {}

and

   with {}

would necessarily two identical or non-identical things. Maybe that 
should be considered a bug in the documentation.

And that Foo(Integer) is different from Foo(String) but equal to 
Foo(Integer) you can only assure if the language restricted to types is 
functional.

We all know that one could define

define Bar(i: Integer): Category == with;

and here I am no longer sure whether Bar(0) is really treated 
differently (by the current aldor compiler) from Bar(1) in a "has" 
construct. I'd like to have the same behaviour as for type-valued 
arguments, but maybe there is some good reason why the Aldor compiler 
behaves different for non-type-valued arguments. There must be some 
examples on this list, I just don't know how I can find them now.

> | There is not definition of equality between categories,
>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> It is very important to realize this and spell it out clearly.
> Because, there is no fundamental reason why there is none.
> 
> | but here the even look identical.
>                     ^^^^
> "Looking" is not the same as being equal.  

I completely agree.

> | So my guess was that they should be treated in the  same way.

> Well, ne need rules to define equality on objects we manipulate
> in programs.  Every definition has its consequences -- pros and 
> cons.

Good. Where should these pros and cons go to? Any suggestion for a 
documentation. MathAction?

> In the field of type theory, the notion of equality on types (and modules) 
> is a fertile area of research that has been going on for ages.
> Search for "manifest types" and "generative types".  Youcan replace
> "type" by "modules".

Thank you. I'll do my homework.

> My point of view is this:  I believe the idea of treating category,
> domain, and packages instantiation as function call is a good 
> uniform rule.  I also believe that we should further uniformity by
> having only one set of rules for function calls -- e.g. we don't
> have one rule for values, one for types, and one for whatever.

If that can be done, I am all for it.

> Notice that, in that view, the notion of value equality is not involved.

Hmmm, but doesn't that mean that whether baz(0) is equal or not equal to 
baz(1) has nothing to do with the implementation of "=" in Integer? That 
sounds a bit strange to me. What are contexts (examples) where =$Integer 
would not be needed?

\start
Date: Thu, 16 Aug 2007 10:48:03 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with"

On Thu, 16 Aug 2007, Ralf Hemmecke wrote:

| > Whether those those two categories are equal in the sense that
| > "=" returns true is entirely a matter semantics attached to
| > the "with"-construct.  There is no predefined choice.
| 
| Yes, I understand and agree. I don't even remember that I have seen clearly
| that I have seen a statement in the AUG that says that
| 
|   with {}
| 
| and
| 
|   with {}
| 
| would necessarily two identical or non-identical things. Maybe that should be
| considered a bug in the documentation.
| 
| And that Foo(Integer) is different from Foo(String) but equal to Foo(Integer)
| you can only assure if the language restricted to types is functional.

Hmm; I'm lost.  Could you elaborate on the last paragraph?

| We all know that one could define
| 
| define Bar(i: Integer): Category == with;
| 
| and here I am no longer sure whether Bar(0) is really treated differently (by
| the current aldor compiler) from Bar(1) in a "has" construct. I'd like to have
| the same behaviour as for type-valued arguments, but maybe there is some good
| reason why the Aldor compiler behaves different for non-type-valued arguments.
| There must be some examples on this list, I just don't know how I can find
| them now.

In any cas,e it would be nice to have those examples, and the logical
inference rules that go with them put somewhere for future reference.

[...]

| > | So my guess was that they should be treated in the  same way.
| 
| > Well, ne need rules to define equality on objects we manipulate
| > in programs.  Every definition has its consequences -- pros and cons.
| 
| Good. Where should these pros and cons go to? Any suggestion for a
| documentation. MathAction?

I believe MathAction is a good place to start.
(But, I tend to leave on emails...)

| > In the field of type theory, the notion of equality on types (and modules)
| > is a fertile area of research that has been going on for ages.
| > Search for "manifest types" and "generative types".  Youcan replace
| > "type" by "modules".
| 
| Thank you. I'll do my homework.
| 
| > My point of view is this:  I believe the idea of treating category,
| > domain, and packages instantiation as function call is a good uniform rule.
| > I also believe that we should further uniformity by
| > having only one set of rules for function calls -- e.g. we don't
| > have one rule for values, one for types, and one for whatever.
| 
| If that can be done, I am all for it.
| 
| > Notice that, in that view, the notion of value equality is not involved.
| 
| Hmmm, but doesn't that mean that whether baz(0) is equal or not equal to
| baz(1) has nothing to do with the implementation of "=" in Integer? That
| sounds a bit strange to me. What are contexts (examples) where =$Integer would
| not be needed?

Well, there are two things here:

   * evaluating the expressions "baz(0)", "baz(1)", "baz(x)" where x is 
      a variable
   * evaluating the expression "baz(0) = "baz(1)"

what I'm saying is that in the evaluation of the function calls baz(1),
baz(0), baz(x), I don't see where the definition of =$Integer is involved.
Nor, am I sure it should be involved -- utimately we would like
=$Integer to be a function itself that can be called...

\start
Date: Thu, 16 Aug 2007 11:43:23 -0500 (CDT)
From: Gabriel Dos Reis
To: Ralf Hemmecke
Subject: Re: "has" and "with"

On Thu, 16 Aug 2007, Ralf Hemmecke wrote:

| Gabriel Dos Reis wrote:
| > On Thu, 16 Aug 2007, Ralf Hemmecke wrote:
| > 
| > | > Whether those those two categories are equal in the sense that
| > | > "=" returns true is entirely a matter semantics attached to
| > | > the "with"-construct.  There is no predefined choice.
| > | 
| > | Yes, I understand and agree. I don't even remember that I have seen
| > | clearly
| > | that I have seen a statement in the AUG that says that
| > | 
| > |   with {}
| > | 
| > | and
| > | 
| > |   with {}
| > | 
| > | would necessarily two identical or non-identical things. Maybe that should
| > | be
| > | considered a bug in the documentation.
| > | 
| > | And that Foo(Integer) is different from Foo(String) but equal to
| > | Foo(Integer)
| > | you can only assure if the language restricted to types is functional.
| 
| > Hmm; I'm lost.  Could you elaborate on the last paragraph?
| 
| We certainly agree that Foo(Integer) could be but need not be equal to
| Foo(String) since that depends on the definition whether the above two "with"
| expressions should be considered equal or not. That should clearly be
| specified and we are done.

Yes, I agree.

| Now you surely want
| 
| Foo(Integer)
| 
| and
| 
| Foo(Integer)
| 
| (in a reasonably close context) to refer to the same thing otherwise...

I also agree with that.

| In
| 
| if Integer has Foo(Integer) then ..
| if Integer has Foo(Integer) then ..
| 
| you probably don't want to evaluate Foo twice.

In fact, you could evaluate it twice.  The first time, it could setup
a timestamp saying that it is evaluated.  The second time, it would
just return the previously evaluated type.  See the very nice recent work
of dreyer on that subject

   http://portal.acm.org/citation.cfm?id=1090189.1086372
  
using what he called "destination-passing" evaluation strategy.


| (But actually the Aldor
| compiler should since here Foo(Integer) does not appear in "type context" (AUG
| Section 7.3).)
| 
| At the moment I don't find I nice example for categories, so let me to switch
| to another example.
| 
| define Cat: Category == with;
| define Ying: Category == with {
|   1: %
|   foo: (%, %) -> %;
| }
| Dom(D: Cat): Ying == add {
|   Rep == Integer;
|   import from Rep;
|   1: % == per(1$Rep);
|   foo(x:%, y:%):% == per(rep x + rep y);
| }
| DI: Cat == Dom(Integer) add;
| DS: Cat == Dom(String)  add;
| DJ: Cat == Dom(Integer) add;
| 
| DI, DJ, and DS are 3 different domains (because of the "add").
| (Which means the compiler should forbid
| 
|   (foo$DI)(1$DJ, 1$DJ)

OK.

| You probably would like
| 
|   (foo$DI)(1$DI, 1$DI)
| 
| to work.

OK.

| What about
| 
|   (foo$Dom(Integer))(1$Dom(Integer), 1$Dom(Integer))
| 
| ?

I would like it to work too.

| You agree that the "add" part of Dom(Integer) and Dom(String) are identical
| (in source code). (So many different equality meanings, its hard to tell
| somebody else what I actually mean.)
| 
| I probably should not be able to call
| 
|   (foo$Dom(Integer))(1$Dom(String), 1$Dom(String))
| 
| right?

Yes.

| But allowing
| 
|   (foo$Dom(Integer))(1$Dom(Integer), 1$Dom(Integer))
| 
| and forbidding
| 
|   (foo$Dom(Integer))(1$Dom(String), 1$Dom(String))
| 
| can only be done if you have a functional language when it comes to types.

Surely, a functional type system will ease that.  But is it necessary?
I'm not saying we should have a non-functional type system; I'm curious
as of the logical  implications one way or the other.

| Dom(Integer) should be the same as Dom(Integer) in
| 
|   (foo$Dom(Integer))(1$Dom(Integer), 1$Dom(Integer))
| 
| otherwise that does not typecheck.

Yes.  That works within Dreyer's framework, I think.

[...]

| In case of Foo(Integer) and Foo(String) there would be no (implemented) "="
| anyway. We cannot compare domains and cannot compare categories. All we could
| do is to use "pretend" and compare pointers. But uhhhhh..... nobody wants
| that.

Right -- I don't want pretend and pointer comparion that way :-)
At least not in "everyday programs".

\start
Date: Wed, 22 Aug 2007 20:13:15 +0200 (CEST)
From: Waldek Hebisch
To: Martin Rubey
Subject: Re: typo in the guessing package pamphlet, was: Re: Algebra and literate documentation

Martin Rubey wrote:
> Tim Daly writes:
> > I started adding your algebra to the system. I ran into a problem.
> > It appears that mantepse.spad.pamphlet will not format correctly.
> > When I looked into the problem you define a chunk:
> > 
> >   <<domain UFPS UnivariateFormalPowerSeries>>=
> 
> yes, all of these are typos, no idea why they weren't caught by wh-sandbox.
> Just make them into <<dom: ...>>= and <<pkg: ...>>== etc. everywhere.  I will
> fix this in the next version.
> 

Using <<dom: ...>>= and <<pkg: ...>>= does not work: the script 
find-algebra-files needs <<domain ...>>= and <<package ...>>=.
In wh-sandbox I have changed dom: to domain and pkg: to package, but
I have missed a few places.

\start
Date: Wed, 22 Aug 2007 20:49:10 +0200 (CEST)
From: Waldek Hebisch
To: Gabriel Dos Reis
Subject: Re: bootstrap Meta/Boot

Gabriel Dos Reis wrote:
> Tim Daly writes:
> 
> [...]
> 
> | The bootstrap-from-Axiom issue is not related to the CCL change.
> | Building Axiom from Axiom is ok if you own the whole project.  But
> | requiring a running Axiom to build Axiom was not a viable open source
> | strategy. I didn't see a way to distribute sources that included
> | pre-compiled binaries.
> 
> But, you could have built a binary of the open sourced Axiom and put
> it there for bootstrapping.  Since most of the stuff were mostly
> Linux, you could have done that and the world would have picked up --
> as it does today -- and to extend it to other platforms where needed.
> 
> [...]
> 
> | In any case I've distributed the original sources to the world. 
> 
> do you still have a link to the original open sourced Axiom from NAG?
> 

I have put copy of NAG version (as provided by Tim) at:

http://www.math.uni.wroc.pl/~hebisch/prog/NAGcdrom.tar.bz2

One can see that this tarball contains working Axiom binary (for
i386 Linux).  Also, it is possible to rebuild Axiom from the
included sources.

Note: the tarball builds algebra from the cached Lisp files.  AFAICS
there is no support for automatic recompilation of algebra.

\start
Date: Wed, 22 Aug 2007 14:03:13 -0500 (CDT)
From: Gabriel Dos Reis
To: Waldek Hebisch
Subject: Re: bootstrap Meta/Boot

On Wed, 22 Aug 2007, Waldek Hebisch wrote:

| Gabriel Dos Reis wrote:
| > Tim Daly writes:
| > 
| > [...]
| > 
| > | The bootstrap-from-Axiom issue is not related to the CCL change.
| > | Building Axiom from Axiom is ok if you own the whole project.  But
| > | requiring a running Axiom to build Axiom was not a viable open source
| > | strategy. I didn't see a way to distribute sources that included
| > | pre-compiled binaries.
| > 
| > But, you could have built a binary of the open sourced Axiom and put
| > it there for bootstrapping.  Since most of the stuff were mostly
| > Linux, you could have done that and the world would have picked up --
| > as it does today -- and to extend it to other platforms where needed.
| > 
| > [...]
| > 
| > | In any case I've distributed the original sources to the world. 
| > 
| > do you still have a link to the original open sourced Axiom from NAG?
| > 
| 
| I have put copy of NAG version (as provided by Tim) at:
| 
| http://www.math.uni.wroc.pl/~hebisch/prog/NAGcdrom.tar.bz2

Many thanks, Waldek.  I just downloaded it to a safe place.

| One can see that this tarball contains working Axiom binary (for
| i386 Linux).  Also, it is possible to rebuild Axiom from the
| included sources.
| 
| Note: the tarball builds algebra from the cached Lisp files.  AFAICS
| there is no support for automatic recompilation of algebra.

OK; thanks!

\start
Date: Thu, 23 Aug 2007 13:24:42 -0400
From: Alfredo Portes
To: Alasdair McAndrew
Subject: Re: A bug in windows Axiom

On 8/13/07, Alasdair McAndrew wrote:

> Now - I don't want to have to go through the arduous business of downloading
> masses of stuff before I can compile Axiom on Windows (and neither do my
> students).  All I want is one simple installation file: download, install
> and that's it.  Do you know if the current Windows binary will ever be
> upgraded?

I have uploaded an updated Axiom Windows binary (based on wh-sandbox branch):

http://alfredo.axiom-developer.org/axiom.exe

Please try it and let me know if it works fine.

A work in progress pamphlet (very undocumented currently) of the
script can be found
here: http://alfredoportes.com/~alfredo/axiom/winstaller.pamphlet

\start
Date: Thu, 23 Aug 2007 13:25:39 -0400
From: Alfredo Portes
To: Alasdair McAndrew
Subject: Re: A bug in windows Axiom

Correction:

https://alfredoportes.com/~alfredo/axiom/winstaller.pamphlet

\start
Date: Thu, 23 Aug 2007 10:43:53 -0700 (PDT)
From: Cliff Yapp
To: Alfredo Portes, Alasdair McAndrew
Subject: Re: A bug in windows Axiom

--- Alfredo Portes wrote:

> A work in progress pamphlet (very undocumented currently) of the
> script can be found here: 
> http://alfredoportes.com/~alfredo/axiom/winstaller.pamphlet

Very nice!  Unfortunately I don't have a Windows machine to try the
installer on yet.  Glad to see someone is looking into the NSIS
generation procedure.

\start
Date: Thu, 23 Aug 2007 15:03:09 -0500
From: Tim Daly
To: Alfredo Portes
Subject: documentation

Jose,

If you go to <http://daly.axiom-developer.org/spadhelp.tgz>
you'll get a tar-gzip file of axiom help.

Put these files into the axiom windows distribution at:
c:\program files\axiom\doc\spadhelp

and then you can type things like

)help cd

\start
Date: Thu, 23 Aug 2007 15:08:21 -0500
From: Tim Daly
To: Alfredo Portes, alfredo@axiom-developer.org
Subject: documentation

Jose,

The spadhelp files are just flat files. The )help command tries to 
complete abbreviations (thus )help abbrev == )help abbrevations)
but otherwise does nothing but display the corresponding file text.

Thus if you create $AXIOM/doc/spadhelp/foo.help you can say:

   )help foo

If you write any new help files please post copies to the axiom-developer
mailing list.

\start
Date: Thu, 23 Aug 2007 18:37:38 -0400
From: Alfredo Portes
To: Alasdair McAndrew
Subject: Re: A bug in windows Axiom

Hi Alasdair,

On 8/23/07, Alasdair McAndrew wrote:
> Thank you very much!  I shall try it out as soon as I can.  Does this
> version include Tim's help files?

Tim just emailed me on how to do this. The new version with the
help files is here:

http://alfredo.axiom-developer.org/axiom.exe

\start
Date: Fri, 24 Aug 2007 18:15:23 +0200 (CEST)
From: Waldek Hebisch
To: list
Subject: Meta parser

There were claims that meta translator does not work.  One can
easily check that fnewmeta.lisp file can be recreated from
fnew.meta:

1) Extract fnew.meta (note that noweb mangles it)
2) start axiom

)lisp (|oldParserAutoloadOnceTrigger|)
)lisp (meta "fnew.meta" "fnew.lisp")

One can check that differences between fnew.lisp fnewmeta.lisp
are trivial (due to different Lisp printer).

\start
Date: Fri, 24 Aug 2007 21:36:42 -0500
From: Tim Daly
To: Alasdair McAndrew, Alfredo Portes
Subject: new algebra documentation
Cc: list

Alasdair, Jose,

I've added new help documentation for some of the algebra domains. 
Specifically there are new help files for:

AssociationList   BalancedBinaryTree   BasicOperator
BinaryExpansion   BinarySearchTree     CardinalNumber
CartesianTensor   Character            CharacterClass
CliffordAlgebra   Complex              ContinuedFraction
CycleIndicators   DeRhamComplex        DecimalExpansion

More are in the pipeline as soon as they pass testing.

You can get the latest at <daly.axiom-developer.org/spadhelp.tgz>
  1) cd to $AXIOM/doc
  2) Download the file, 
  3) tar -zxf spadhelp.tgz
  4) start Axiom
  5) type
      )help CliffordAlgebra

\start
Date: Sun, 26 Aug 2007 12:37:30 -0300
From: Pablo De Napoli
To: list
Subject: problems compiling openaxiom

Hi,

I've just joined axiom-devel, though I've been following the axiom
development for a while.

I've been trying to compile the different forks (branches?) of Axiom
I've found problems both with OpenAxiom and Fricas, for sake of
clarity I report them in
separated e-mails.

By the way, don't you think that it is important to work all together
rather than split axiom
into different projects?

Perhaps you should consider using a distribuited version control like
mercurial or git
for axiom, rather than subversion that it is for centralized work (to
make merging code from
the different branches/forks easier)

I confess that I'm a bit confused with so many branches and so many
repositories in
different version control systems and places.

best regards,
Pablo

Here is my error report on building Open Axiom:

pcd ./src && \
=09=09make "PATH=/home/pablo/temporal/open-axiom.trunk/build-oa/build/i68=
6-pc-linux/bin:/home/pablo/axiom/mnt/linux/bin:/bin:/usr/bin:/opt/bin:/usr/=
i686-pc-linux-gnu/gcc-bin/4.1.2:/opt/sun-jdk-1.4.2.12/bin:/opt/sun-jdk-1.4.=
2.12/jre/bin:/opt/sun-jdk-1.4.2.12/jre/javaws:/usr/kde/3.5/bin:/usr/qt/3/bi=
n:/opt/HelixPlayer:/usr/games/bin"
all-src
make[1]: se ingresa al directorio
`/home/pablo/temporal/open-axiom.trunk/build-oa/src'
make[2]: se ingresa al directorio
`/home/pablo/temporal/open-axiom.trunk/build-oa/src/lib'
make[2]: No se hace nada para `all-lib'.
make[2]: se sale del directorio
`/home/pablo/temporal/open-axiom.trunk/build-oa/src/lib'
cd lisp && make all-lisp
make[2]: se ingresa al directorio
`/home/pablo/temporal/open-axiom.trunk/build-oa/src/lisp'
:
echo '(let* ((sys-cc compiler::*cc*) ' \
=09     '      (sys-ld compiler::*ld*) ' \
=09     '      (compiler::*cc* (concatenate (quote string) ' \
=09     '                                   "../../libtool --mode=compile=
 "    ' \
=09     '                                   sys-cc))       ' \
=09     '      (compiler::*ld* (concatenate (quote string) ' \
=09     '                                   "../../libtool --mode=link " =
   ' \
=09     '                                   sys-ld)))       ' \
             '(compiler::link (quote ("core.o")) "lisp" ' \
             ' (format nil "(progn (let ((*load-path* (cons ~S *load-path*)=
)'\
                                        ' (si::*load-types* ~S))' \
                                       ' (compiler::emit-fn t))' \
                                  ' (when (fboundp (quote si::sgc-on))' \
                                        ' (si::sgc-on nil))' \
                                  ' (setq compiler::*default-system-p* t)' =
\
=09=09=09=09  ' (setq si::*top-level-hook* (read-from-string
\"|AxiomCore|::|topLevel|\")))"' \
                      ' si::*system-directory* (quote (list ".lsp")))' \
               '  "./../../src/lib/bsdsignal.lo
./../../src/lib/cfuns-c.lo ./../../src/lib/sockio-c.lo "))' \
            | ./base-lisp
GCL (GNU Common Lisp)  2.6.7 ANSI    Jun 12 2006 13:32:33
Source License: LGPL(gcl,gmp), GPL(unexec,bfd)
Binary License:  GPL due to GPL'ed components: (READLINE BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.
GCL (GNU Common Lisp)  2.6.7 ANSI    Jun 12 2006 13:32:33
Source License: LGPL(gcl,gmp), GPL(unexec,bfd)
Binary License:  GPL due to GPL'ed components: (READLINE BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.

> gcc -c -O3 -march=athlon -funroll-loops -pipe -fomit-frame-pointer -Wal=
l -DVOL=volatile -fsigned-char -pipe -I/usr/lib/gcl-2.6.7/unixport/../h -=
O3 -fomit-frame-pointer -c ./user-init.c -w  -fPIC -DPIC -o ./.libs/user-in=
it.o
 gcc -c -O3 -march=athlon -funroll-loops -pipe -fomit-frame-pointer
-Wall -DVOL=volatile -fsigned-char -pipe
-I/usr/lib/gcl-2.6.7/unixport/../h -O3 -fomit-frame-pointer -c
./user-init.c -w -o ./user-init.o >/dev/null 2>&1
gcc -o ./raw_lisp ./user-init.o core.o -Wl,-Map ./raw_lisp_map
./../../src/lib/.libs/bsdsignal.o ./../../src/lib/.libs/cfuns-c.o
./../../src/lib/.libs/sockio-c.o  -L/usr/lib/gcl-2.6.7/unixport/
-lansi_gcl -lm /usr/lib/libgmp.so -lreadline -lncurses -lc -lgclp
gcc: core.o: No such file or directory
sh: ./raw_lisp: No existe el fichero o el directorio

Error in LET* [or a callee]: Cannot delete the file #p"./raw_lisp".

Fast links are on: do (use-fast-links nil) for debugging
Broken at DELETE-FILE.  Type :H for Help.
 1 (Abort) Return to top level.
dbl:>>../../../config/mkinstalldirs ../../build/i686-pc-linux/bin
/usr/bin/install -c lisp ../../build/i686-pc-linux/bin
/usr/bin/install: no se puede efectuar `stat' sobre =ABlisp=BB: No existe
el fichero o el directorio
make[2]: *** [../../build/i686-pc-linux/bin/lisp] Error 1
make[2]: se sale del directorio
`/home/pablo/temporal/open-axiom.trunk/build-oa/src/lisp'
make[1]: *** [all-lisp] Error 2
make[1]: se sale del directorio
`/home/pablo/temporal/open-axiom.trunk/build-oa/src'
make: *** [all-src] Error 2

\start
Date: Sun, 26 Aug 2007 12:42:44 -0300
From: Pablo De Napoli
To: list
Subject: problem compiling fricas

Here is my bug report on compiling Fricas
By the way, I think that using the standard configure/make/make install
process is indeed an important improvement on Axiom.
best regards
Pablo


cd ./src && make all-src
make[1]: se ingresa al directorio `/home/pablo/temporal/fricas/trunk/src'
make[2]: se ingresa al directorio `/home/pablo/temporal/fricas/trunk/src/lib'
make[2]: No se hace nada para `all'.
make[2]: se sale del directorio `/home/pablo/temporal/fricas/trunk/src/lib'
cd lisp && make all-lisp
make[2]: se ingresa al directorio `/home/pablo/temporal/fricas/trunk/src/lisp'
:
echo '(load "axiom-package.lisp")' \
	     '(setq compiler::*default-system-p* t)' \
	     '(compile-file "axiom-lisp.lisp")' | /usr/bin/gcl
GCL (GNU Common Lisp)  2.6.7 ANSI    Jun 12 2006 13:32:33
Source License: LGPL(gcl,gmp), GPL(unexec,bfd)
Binary License:  GPL due to GPL'ed components: (READLINE BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.

>
Loading axiom-package.lisp
Finished loading axiom-package.lisp
T

>
T

>
Compiling axiom-lisp.lisp.
End of Pass 1.
End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
Finished compiling axiom-lisp.lisp.
#p"axiom-lisp.o"

>echo '(compiler::link nil "prelisp" ' \
              ' (format nil "(progn (let ((*load-path* (cons ~S *load-path*))'\
                                        ' (si::*load-types* ~S))' \
                                       ' (compiler::emit-fn t))' \
                                  ' (when (fboundp (quote si::sgc-on))' \
                                        ' (si::sgc-on t))' \
                                  ' (setq compiler::*default-system-p* t))"' \
                      ' si::*system-directory* (quote (list ".lsp")))' \
               '
"/home/pablo/temporal/fricas/trunk/src/lib/bsdsignal.o
/home/pablo/temporal/fricas/trunk/src/lib/cfuns-c.o
/home/pablo/temporal/fricas/trunk/src/lib/sockio-c.o  -lutil")' \
            | /usr/bin/gcl
GCL (GNU Common Lisp)  2.6.7 ANSI    Jun 12 2006 13:32:33
Source License: LGPL(gcl,gmp), GPL(unexec,bfd)
Binary License:  GPL due to GPL'ed components: (READLINE BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter

Use (help) to get some basic information on how to use GCL.

>GCL (GNU Common Lisp)  April 1994  131072 pages
Building symbol table for
/home/pablo/temporal/fricas/trunk/src/lisp/raw_prelisp ..
loading /usr/lib/gcl-2.6.7/unixport/../lsp/gcl_export.lsp
Initializing gcl_defmacro.o
Can't open file ~s
Lisp initialization failed.

"prelisp"

>echo '(load "axiom-package.lisp") (load "axiom-lisp.o")' \
	     '(in-package "AXIOM-LISP") (save-core "lisp")' \
	    | ./prelisp
/bin/sh: line 2: ./prelisp: No existe el fichero o el directorio
make[2]: *** [do_it.gcl] Error 127
make[2]: se sale del directorio `/home/pablo/temporal/fricas/trunk/src/lisp'
make[1]: *** [all-lisp] Error 2
make[1]: se sale del directorio `/home/pablo/temporal/fricas/trunk/src'
make: *** [all-src] Error 2

\start
Date: Sun, 26 Aug 2007 09:11:20 -0700 (PDT)
From: Cliff Yapp
To: Pablo De Napoli
Subject: Re: problems compiling openaxiom

--- Pablo De Napoli wrote:

> Hi,
> 
> I've just joined axiom-devel, though I've been following the axiom
> development for a while.
> 
> I've been trying to compile the different forks (branches?) of Axiom
> I've found problems both with OpenAxiom and Fricas, for sake of
> clarity I report them in separated e-mails.

Both of these projects have their own email lists, those source trees
aren't maintained here:

http://groups.google.com/group/fricas-devel?hl=en

http://www.open-axiom.org/lists.html

> By the way, don't you think that it is important to work all together
> rather than split axiom into different projects?

If you look through the axiom-devel archives, there are extensive
discussions on that subject.  The forks were not made casually.  The
short version is that there are distinctly different and incompatible
goals being pursued.

> Perhaps you should consider using a distribuited version control like
> mercurial or git for axiom, rather than subversion that it is for
> centralized work (to make merging code from the different
> branches/forks easier)

For Axiom itself, git is rapidly becoming the tool of choice.  Other
forks will have different policies.
 
> I confess that I'm a bit confused with so many branches and so many
> repositories in different version control systems and places.

Axiom is in the process of re-organizing itself to refocus around the
original project goals, per Tim Daly's email.  I don't know if that
will involve a re-shuffling of the branch organization.

As for OpenAxiom and Fricas, those are separate projects and will have
their own decisions to make about tool choices and build trees.

\start
Date: Sun, 26 Aug 2007 19:33:54 +0200 (CEST)
From: Waldek Hebisch
To: Pablo De Napoli
Subject: Re: problem compiling fricas

> Here is my bug report on compiling Fricas
> By the way, I think that using the standard configure/make/make install
> process is indeed an important improvement on Axiom.
> best regards
> Pablo
> 
<snip>
> >echo '(compiler::link nil "prelisp" ' \
>               ' (format nil "(progn (let ((*load-path* (cons ~S *load-path*))'\
>                                         ' (si::*load-types* ~S))' \
>                                        ' (compiler::emit-fn t))' \
>                                   ' (when (fboundp (quote si::sgc-on))' \
>                                         ' (si::sgc-on t))' \
>                                   ' (setq compiler::*default-system-p* t))"' \
>                       ' si::*system-directory* (quote (list ".lsp")))' \
>                '
> "/home/pablo/temporal/fricas/trunk/src/lib/bsdsignal.o
> /home/pablo/temporal/fricas/trunk/src/lib/cfuns-c.o
> /home/pablo/temporal/fricas/trunk/src/lib/sockio-c.o  -lutil")' \
>             | /usr/bin/gcl
> GCL (GNU Common Lisp)  2.6.7 ANSI    Jun 12 2006 13:32:33
> Source License: LGPL(gcl,gmp), GPL(unexec,bfd)
> Binary License:  GPL due to GPL'ed components: (READLINE BFD UNEXEC)
> Modifications of this banner must retain notice of a compatible license
> Dedicated to the memory of W. Schelter
> 
> Use (help) to get some basic information on how to use GCL.
> 
> >GCL (GNU Common Lisp)  April 1994  131072 pages
> Building symbol table for
> /home/pablo/temporal/fricas/trunk/src/lisp/raw_prelisp ..
> loading /usr/lib/gcl-2.6.7/unixport/../lsp/gcl_export.lsp
> Initializing gcl_defmacro.o
> Can't open file ~s
> Lisp initialization failed.
> 
> "prelisp"
> 
> >echo '(load "axiom-package.lisp") (load "axiom-lisp.o")' \
> 	     '(in-package "AXIOM-LISP") (save-core "lisp")' \
> 	    | ./prelisp
> /bin/sh: line 2: ./prelisp: No existe el fichero o el directorio
> make[2]: *** [do_it.gcl] Error 127
> make[2]: se sale del directorio `/home/pablo/temporal/fricas/trunk/src/lisp'
> make[1]: *** [all-lisp] Error 2
> make[1]: se sale del directorio `/home/pablo/temporal/fricas/trunk/src'
> make: *** [all-src] Error 2
> 
>

Which OS (in case of Linux which distribution) do you use?  And do you
use self compiled gcl or one provided with your system?

I belive that this is bug in the gcl version you use.  I have seen this
problem on Gentoo, see:

http://bugs.gentoo.org/show_bug.cgi?id=183544

When I build my own gcl from sources (on the same Gentoo machine) it
worked fine.

PS:  In general you should report FriCAS problems on fricas-devel
mailing list.  I send this message also to axiom-devel because the
problem may affect all Axiom derivatives.

\start
Date: Mon, 27 Aug 2007 01:57:41 -0500
From: Tim Daly
To: list
Subject: 20070721.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 3ac5da7..0c9e91d 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,5 @@
+20070721 tpd src/interp/setq.lisp update contributor name list
+20070721 tpd readme update contributor name list
 20070716 tpd src/doc/axiom.bib move developernotes to bookvol4
 20070716 tpd src/doc/Makefile move developernotes to bookvol4
 20070716 tpd src/input/Makefile add chtheorem.regress
diff --git a/readme b/readme
index 2ce2d10..112fa70 100644
--- a/readme
+++ b/readme
@@ -166,24 +166,27 @@ which contains this list. Typing
 )credits 
 at the axiom command prompt will prettyprint the list.
 
-"An alphabetical listing of contributors to AXIOM (to October, 2006):"
+"An alphabetical listing of contributors to AXIOM (to July, 2007):"
 "Cyril Alberga          Roy Adler              Christian Aistleitner"
 "Richard Anderson       George Andrews         S.J. Atkins"
 "Henry Baker            Stephen Balzac         Yurij Baransky"
 "David R. Barton        Gerald Baumgartner     Gilbert Baumslag"
-"Fred Blair             Vladimir Bondarenko    Mark Botch"
+"Jay Belanger           David Bindel           Fred Blair"
+"Vladimir Bondarenko    Mark Botch"
 "Alexandre Bouyer       Peter A. Broadbery     Martin Brock"
 "Manuel Bronstein       Florian Bundschuh      Luanne Burns"
 "William Burge"
 "Quentin Carpent        Robert Caviness        Bruce Char"
-"Cheekai Chin           David V. Chudnovsky    Gregory V. Chudnovsky"
-"Josh Cohen             Christophe Conil       Don Coppersmith"
-"George Corliss         Robert Corless         Gary Cornell"
-"Meino Cramer           Claire Di Crescenzo"
+"Ondrej Certik          Cheekai Chin           David V. Chudnovsky"
+"Gregory V. Chudnovsky  Josh Cohen             Christophe Conil"
+"Don Coppersmith        George Corliss         Robert Corless"
+"Gary Cornell           Meino Cramer           Claire Di Crescenzo"
+"David Cyganski"
 "Timothy Daly Sr.       Timothy Daly Jr.       James H. Davenport"
-"Jean Della Dora        Gabriel Dos Reis       Michael Dewar"
-"Claire DiCrescendo     Sam Dooley             Lionel Ducos"
-"Martin Dunstan         Brian Dupee            Dominique Duval"
+"Didier Deshommes       Michael Dewar"
+"Jean Della Dora        Gabriel Dos Reis       Claire DiCrescendo"
+"Sam Dooley             Lionel Ducos           Martin Dunstan"
+"Brian Dupee            Dominique Duval"
 "Robert Edwards         Heow Eide-Goodman      Lars Erickson"
 "Richard Fateman        Bertfried Fauser       Stuart Feldman"
 "Brian Ford             Albrecht Fortenbacher  George Frances"
@@ -191,33 +194,36 @@ at the axiom command prompt will prettyprint the list.
 "Marc Gaetano           Rudiger Gebauer        Kathy Gerber"
 "Patricia Gianni        Holger Gollan          Teresa Gomez-Diaz"
 "Laureano Gonzalez-Vega Stephen Gortler        Johannes Grabmeier"
-"Matt Grayson           James Griesmer         Vladimir Grinberg"
-"Oswald Gschnitzer      Jocelyn Guidry"
-"Steve Hague            Satoshi Hamaguchi      Richard Harke"
-"Vilya Harvey           Martin Hassner         Arthur S. Hathaway"
-"Waldek Hebisch         Ralf Hemmecke          Henderson"
-"Antoine Hersen"
+"Matt Grayson           Klaus Ebbe Grue        James Griesmer"
+"Vladimir Grinberg      Oswald Gschnitzer      Jocelyn Guidry"
+"Steve Hague            Satoshi Hamaguchi      Mike Hansen"
+"Richard Harke          Vilya Harvey           Martin Hassner"
+"Arthur S. Hathaway     Waldek Hebisch         Ralf Hemmecke"
+"Henderson              Antoine Hersen         Gernot Hueber"
 "Pietro Iglio"
 "Richard Jenks"
 "Kai Kaminski           Grant Keady            Tony Kennedy"
 "Paul Kosinski          Klaus Kusche           Bernhard Kutzler"
-"Larry Lambe            Frederic Lehobey       Michel Levaud"
-"Howard Levy            Rudiger Loos           Michael Lucks"
-"Richard Luczak"
-"Camm Maguire           Francois Maltey        Bob McElrath"
-"Michael McGettrick     Ian Meikle             David Mentre"
-"Victor S. Miller       Gerard Milmeister      Mohammed Mobarak"
-"H. Michael Moeller     Michael Monagan        Marc Moreno-Maza"
-"Scott Morrison         Joel Moses             Mark Murray"
+"Larry Lambe            Franz Lehner           Frederic Lehobey"
+"Michel Levaud          Howard Levy            Rudiger Loos"
+"Michael Lucks          Richard Luczak"
+"Camm Maguire           Francois Maltey        Alasdair McAndrew"
+"Bob McElrath           Michael McGettrick     Ian Meikle"
+"David Mentre           Victor S. Miller       Gerard Milmeister"
+"Mohammed Mobarak       H. Michael Moeller     Michael Monagan"
+"Marc Moreno-Maza       Scott Morrison         Joel Moses"
+"Mark Murray"
 "William Naylor         C. Andrew Neff         John Nelder"
 "Godfrey Nolan          Arthur Norman          Jinzhong Niu"
-"Michael O'Connor       Kostas Oikonomou       Humberto Ortiz-Zuazaga"
+"Michael O'Connor       Summat Oemrawsingh     Kostas Oikonomou"
+"Humberto Ortiz-Zuazaga"  
 "Julian A. Padget       Bill Page              Susan Pelzel"
-"Michel Petitot         Didier Pinchon         Jose Alfredo Portes"
+"Michel Petitot         Didier Pinchon         Ayal Pinkus"
+"Jose Alfredo Portes"
 "Claude Quitte"
 "Norman Ramsey          Michael Richardson     Renaud Rioboo"
 "Jean Rivlin            Nicolas Robidoux       Simon Robinson"
-"Michael Rothstein      Martin Rubey"
+"Raymond Rogers         Michael Rothstein      Martin Rubey"
 "Philip Santas          Alfred Scheerhorn      William Schelter"
 "Gerhard Schneider      Martin Schoenert       Marshall Schor"
 "Frithjof Schulze       Fritz Schwarz          Nick Simicich"
@@ -234,8 +240,8 @@ at the axiom command prompt will prettyprint the list.
 "Stephen Wilson         Shmuel Winograd        Robert Wisbauer"
 "Sandra Wityak          Waldemar Wiwianka      Knut Wolf"
 "Clifford Yapp          David Yun"
-"Richard Zippel         Evelyn Zoernack        Bruno Zuercher"
-"Dan Zwillinger"
+"Vadim Zhytnikov        Richard Zippel         Evelyn Zoernack"
+"Bruno Zuercher         Dan Zwillinger"
 
 Pervasive Literate Programming
 
diff --git a/src/interp/setq.lisp.pamphlet b/src/interp/setq.lisp.pamphlet
index a4fc0ed..6f23778 100644
--- a/src/interp/setq.lisp.pamphlet
+++ b/src/interp/setq.lisp.pamphlet
@@ -722,24 +722,27 @@
 (setq |$profileCompiler| nil)
 
 (setq credits '(
-"An alphabetical listing of contributors to AXIOM (to October, 2006):"
+"An alphabetical listing of contributors to AXIOM (to July, 2007):"
 "Cyril Alberga          Roy Adler              Christian Aistleitner"
 "Richard Anderson       George Andrews         S.J. Atkins"
 "Henry Baker            Stephen Balzac         Yurij Baransky"
 "David R. Barton        Gerald Baumgartner     Gilbert Baumslag"
-"Fred Blair             Vladimir Bondarenko    Mark Botch"
+"Jay Belanger           David Bindel           Fred Blair"
+"Vladimir Bondarenko    Mark Botch"
 "Alexandre Bouyer       Peter A. Broadbery     Martin Brock"
 "Manuel Bronstein       Florian Bundschuh      Luanne Burns"
 "William Burge"
 "Quentin Carpent        Robert Caviness        Bruce Char"
-"Cheekai Chin           David V. Chudnovsky    Gregory V. Chudnovsky"
-"Josh Cohen             Christophe Conil       Don Coppersmith"
-"George Corliss         Robert Corless         Gary Cornell"
-"Meino Cramer           Claire Di Crescenzo"
+"Ondrej Certik          Cheekai Chin           David V. Chudnovsky"
+"Gregory V. Chudnovsky  Josh Cohen             Christophe Conil"
+"Don Coppersmith        George Corliss         Robert Corless"
+"Gary Cornell           Meino Cramer           Claire Di Crescenzo"
+"David Cyganski"
 "Timothy Daly Sr.       Timothy Daly Jr.       James H. Davenport"
-"Jean Della Dora        Gabriel Dos Reis       Michael Dewar"
-"Claire DiCrescendo     Sam Dooley             Lionel Ducos"
-"Martin Dunstan         Brian Dupee            Dominique Duval"
+"Didier Deshommes       Michael Dewar"
+"Jean Della Dora        Gabriel Dos Reis       Claire DiCrescendo"
+"Sam Dooley             Lionel Ducos           Martin Dunstan"
+"Brian Dupee            Dominique Duval"
 "Robert Edwards         Heow Eide-Goodman      Lars Erickson"
 "Richard Fateman        Bertfried Fauser       Stuart Feldman"
 "Brian Ford             Albrecht Fortenbacher  George Frances"
@@ -747,33 +750,36 @@
 "Marc Gaetano           Rudiger Gebauer        Kathy Gerber"
 "Patricia Gianni        Holger Gollan          Teresa Gomez-Diaz"
 "Laureano Gonzalez-Vega Stephen Gortler        Johannes Grabmeier"
-"Matt Grayson           James Griesmer         Vladimir Grinberg"
-"Oswald Gschnitzer      Jocelyn Guidry"
-"Steve Hague            Satoshi Hamaguchi      Richard Harke"
-"Vilya Harvey           Martin Hassner         Arthur S. Hathaway"
-"Waldek Hebisch         Ralf Hemmecke          Henderson"
-"Antoine Hersen"
+"Matt Grayson           Klaus Ebbe Grue        James Griesmer"
+"Vladimir Grinberg      Oswald Gschnitzer      Jocelyn Guidry"
+"Steve Hague            Satoshi Hamaguchi      Mike Hansen"
+"Richard Harke          Vilya Harvey           Martin Hassner"
+"Arthur S. Hathaway     Waldek Hebisch         Ralf Hemmecke"
+"Henderson              Antoine Hersen         Gernot Hueber"
 "Pietro Iglio"
 "Richard Jenks"
 "Kai Kaminski           Grant Keady            Tony Kennedy"
 "Paul Kosinski          Klaus Kusche           Bernhard Kutzler"
-"Larry Lambe            Frederic Lehobey       Michel Levaud"
-"Howard Levy            Rudiger Loos           Michael Lucks"
-"Richard Luczak"
-"Camm Maguire           Francois Maltey        Bob McElrath"
-"Michael McGettrick     Ian Meikle             David Mentre"
-"Victor S. Miller       Gerard Milmeister      Mohammed Mobarak"
-"H. Michael Moeller     Michael Monagan        Marc Moreno-Maza"
-"Scott Morrison         Joel Moses             Mark Murray"
+"Larry Lambe            Franz Lehner           Frederic Lehobey"
+"Michel Levaud          Howard Levy            Rudiger Loos"
+"Michael Lucks          Richard Luczak"
+"Camm Maguire           Francois Maltey        Alasdair McAndrew"
+"Bob McElrath           Michael McGettrick     Ian Meikle"
+"David Mentre           Victor S. Miller       Gerard Milmeister"
+"Mohammed Mobarak       H. Michael Moeller     Michael Monagan"
+"Marc Moreno-Maza       Scott Morrison         Joel Moses"
+"Mark Murray"
 "William Naylor         C. Andrew Neff         John Nelder"
 "Godfrey Nolan          Arthur Norman          Jinzhong Niu"
-"Michael O'Connor       Kostas Oikonomou       Humberto Ortiz-Zuazaga"
+"Michael O'Connor       Summat Oemrawsingh     Kostas Oikonomou"
+"Humberto Ortiz-Zuazaga"  
 "Julian A. Padget       Bill Page              Susan Pelzel"
-"Michel Petitot         Didier Pinchon         Jose Alfredo Portes"
+"Michel Petitot         Didier Pinchon         Ayal Pinkus"
+"Jose Alfredo Portes"
 "Claude Quitte"
 "Norman Ramsey          Michael Richardson     Renaud Rioboo"
 "Jean Rivlin            Nicolas Robidoux       Simon Robinson"
-"Michael Rothstein      Martin Rubey"
+"Raymond Rogers         Michael Rothstein      Martin Rubey"
 "Philip Santas          Alfred Scheerhorn      William Schelter"
 "Gerhard Schneider      Martin Schoenert       Marshall Schor"
 "Frithjof Schulze       Fritz Schwarz          Nick Simicich"
@@ -790,8 +796,8 @@
 "Stephen Wilson         Shmuel Winograd        Robert Wisbauer"
 "Sandra Wityak          Waldemar Wiwianka      Knut Wolf"
 "Clifford Yapp          David Yun"
-"Richard Zippel         Evelyn Zoernack        Bruno Zuercher"
-"Dan Zwillinger"
+"Vadim Zhytnikov        Richard Zippel         Evelyn Zoernack"
+"Bruno Zuercher         Dan Zwillinger"
 ))
 
 @

\start
Date: Mon, 27 Aug 2007 02:08:34 -0500
From: Tim Daly
To: list
Subject: 20070721.02.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 0c9e91d..7091ec9 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070721 wxh src/interp/spad.lisp make evalSharpOne declare arg specials
 20070721 tpd src/interp/setq.lisp update contributor name list
 20070721 tpd readme update contributor name list
 20070716 tpd src/doc/axiom.bib move developernotes to bookvol4
diff --git a/src/interp/spad.lisp.pamphlet b/src/interp/spad.lisp.pamphlet
index c6e7542..c39b435 100644
--- a/src/interp/spad.lisp.pamphlet
+++ b/src/interp/spad.lisp.pamphlet
@@ -450,7 +450,14 @@
 	 (if |$InteractiveMode| (|spadThrow|))
 	 (S-PROCESS x))))
 
-(defun |evalSharpOne| (x \#1) (declare (special \#1)) (EVAL x))
+
+@
+The evalSharpOne function needs to declare the second argument
+special to reduce warning messages about variables being assumed
+special.
+<<*>>=
+(defun |evalSharpOne| (x |#1|) (declare (special |#1|))
+ (EVAL `(let() (declare (special |#1|)) ,x)))
 
 (defun new () (|New,ENTRY|))
 
\start
Date: Mon, 27 Aug 2007 02:14:00 -0500
From: Tim Daly
To: list
Subject: 20070810.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 962132e..7cbe49b 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,65 @@
+20070810 tpd src/interp/metameta.lisp removed (unused)
+20070810 tpd src/interp/ccl-depsys.lsp remove metameta
+20070810 tpd src/interp/parsing.lisp remove metameta
+20070810 tpd src/interp/Makefile remove metameta
+20070810 tpd src/interp/debugsys.lisp remove metameta.lisp load
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-REPEATOR
+20070810 tpd src/interp/metameta.lisp unused PARSE-REPEATOR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-OPT_EXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-OPT_EXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-LOCAL_VAR
+20070810 tpd src/interp/metameta.lisp unused PARSE-LOCAL_VAR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-DEST_REF
+20070810 tpd src/interp/metameta.lisp unused PARSE-DEST_REF
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-NON_DEST_REF
+20070810 tpd src/interp/metameta.lisp unused PARSE-NON_DEST_REF
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-SEXPR_STRING
+20070810 tpd src/interp/metameta.lisp unused PARSE-SEXPR_STRING
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-CONS_SEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-CONS_SEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-REF_SEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-REF_SEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-SEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-SEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-N_TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-N_TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-REP_TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-REP_TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-FIL_TEST
+20070810 tpd src/interp/metameta.lisp unused PARSE-FIL_TEST
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-SUBEXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-SUBEXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-EXPR2
+20070810 tpd src/interp/metameta.lisp unused PARSE-EXPR2
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-EXPR1
+20070810 tpd src/interp/metameta.lisp unused PARSE-EXPR1
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-EXPR
+20070810 tpd src/interp/metameta.lisp unused PARSE-EXPR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-FID
+20070810 tpd src/interp/metameta.lisp unused PARSE-FID
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-RULE1
+20070810 tpd src/interp/metameta.lisp unused PARSE-RULE1
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-RULE
+20070810 tpd src/interp/metameta.lisp unused PARSE-RULE
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-HEADER
+20070810 tpd src/interp/metameta.lisp unused PARSE-HEADER
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::PARSE-PROGRAM
+20070810 tpd src/interp/metameta.lisp unused parse-program
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::IN-META
+20070810 tpd src/interp/metalex.lisp.pamphlet unused in-meta function
+20070810 tpd src/interp/metalex.lisp.pamphlet unused meta function
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::NEWRULE
+20070810 tpd src/interp/metalex.lisp unused newrule 
+20070810 tpd src/interp/spad.lisp unused TRAPFLAG
+20070810 tpd src/interp/debug.lisp unused TRAPFLAG
+20070810 tpd src/interp/debug.lisp unused (MAKEPROP 'META '/TRAN '/TRANSMETA)
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::/TRANSMETA
+20070810 tpd src/interp/spad.lisp unused /transmeta 
+20070810 tpd src/interp/parsing.lisp unused transpgvar 
+20070810 tpd src/interp/sys-pkg.lisp unused BOOT::TRANSPGVAR
+20070810 tpd src/interp/interp-proclaims.lisp unused BOOT::TRANSPGVAR
 20070722 tpd src/interp/Makefile cleanup latex warnings
 20070721 wxh src/interp/spad.lisp make evalSharpOne declare arg specials
 20070721 tpd src/interp/setq.lisp update contributor name list
diff --git a/src/boot/ccl-depsys.lsp.pamphlet b/src/boot/ccl-depsys.lsp.pamphlet
index e6a94f8..b0e91fc 100644
--- a/src/boot/ccl-depsys.lsp.pamphlet
+++ b/src/boot/ccl-depsys.lsp.pamphlet
@@ -63,7 +63,6 @@
 (load "def.lisp")
 (load "fnewmeta.lisp")
 (load "metalex.lisp")
-(load "metameta.lisp")
 (load "postprop.lisp")
 (load "preparse.lisp")
 
diff --git a/src/doc/axiom.bib.pamphlet b/src/doc/axiom.bib.pamphlet
index 4bb27e4..97204c7 100644
--- a/src/doc/axiom.bib.pamphlet
+++ b/src/doc/axiom.bib.pamphlet
@@ -671,13 +671,6 @@ pamphlet and booklet files.
 }
 
 @
-\subsection{metameta.lisp}
-<<metameta.lisp>>=
-@MISC{metameta.lisp,
-   path=./src/interp/metameta.lisp.pamphlet
-}
-
-@
 \subsection{modemap.boot}
 <<modemap.boot>>=
 @MISC{modemap.boot,
@@ -13873,13 +13866,6 @@ pamphlet and booklet files.
 }
 
 @
-\subsection{metameta.lisp}
-<<metameta.lisp>>=
-@MISC{metameta.lisp,
-   path=./new/src/interp/metameta.lisp.pamphlet
-}
-
-@
 \subsection{modemap.boot}
 <<modemap.boot>>=
 @MISC{modemap.boot,
@@ -20850,7 +20836,6 @@ pamphlet and booklet files.
 <<macros.lisp>>
 <<metalex.lisp>>
 <<mark.boot>>
-<<metameta.lisp>>
 <<modemap.boot>>
 <<monitor.lisp>>
 <<nci.lisp>>
@@ -22736,7 +22721,6 @@ pamphlet and booklet files.
 <<mark.boot>>
 <<match.boot>>
 <<metalex.lisp>>
-<<metameta.lisp>>
 <<modemap.boot>>
 <<monitor.lisp>>
 <<msg.boot>>
diff --git a/src/interp/Makefile.pamphlet b/src/interp/Makefile.pamphlet
index 23ec4cc..3fa2d97 100644
--- a/src/interp/Makefile.pamphlet
+++ b/src/interp/Makefile.pamphlet
@@ -244,7 +244,6 @@ generations of ``old'' and all meaning of the term is lost.
 OPOBJS=	${AUTO}/parsing.${O}	${AUTO}/bootlex.${O}	\
         ${AUTO}/def.${O}	\
 	${AUTO}/fnewmeta.${O}	${AUTO}/metalex.${O}	\
-	${AUTO}/metameta.${O}	\
 	${AUTO}/parse.${O}	${AUTO}/postpar.${O}	\
 	${AUTO}/postprop.${LISP}	${AUTO}/preparse.${O}
 
@@ -460,7 +459,7 @@ DOCFILES=${DOC}/alql.boot.dvi \
 	 ${DOC}/lisplib.boot.dvi ${DOC}/macex.boot.dvi \
 	 ${DOC}/macros.lisp.dvi ${DOC}/Makefile.dvi \
 	 ${DOC}/mark.boot.dvi ${DOC}/match.boot.dvi \
-	 ${DOC}/metalex.lisp.dvi ${DOC}/metameta.lisp.dvi \
+	 ${DOC}/metalex.lisp.dvi  \
 	 ${DOC}/modemap.boot.dvi ${DOC}/monitor.lisp.dvi \
 	 ${DOC}/msg.boot.dvi ${DOC}/msgdb.boot.dvi \
 	 ${DOC}/nag-c02.boot.dvi ${DOC}/nag-c05.boot.dvi \
@@ -755,7 +754,7 @@ ${DEPSYS}:	${DEP} ${OUT}/sys-pkg.${LISP} ${OUT}/nocompil.${LISP} \
 	        ${OUT}/bootlex.${LISP} ${OUT}/newaux.${LISP} \
 	        ${OUT}/preparse.${LISP} \
 	        ${OUT}/postprop.${LISP} ${OUT}/def.${LISP} \
-	        ${OUT}/metameta.${LISP} ${OUT}/fnewmeta.${LISP} \
+	        ${OUT}/fnewmeta.${LISP} \
 	        ${OUT}/g-boot.${LISP} ${OUT}/c-util.${LISP} \
 	        ${OUT}/g-util.${LISP} \
 	        ${OUT}/clam.${LISP} \
@@ -806,10 +805,6 @@ ${DEPSYS}:	${DEP} ${OUT}/sys-pkg.${LISP} ${OUT}/nocompil.${LISP} \
           '(compile-file "${OUT}/def.${LISP}"' \
           ':output-file "${OUT}/def.${O}"))' >> ${OUT}/makedep.lisp
 	@ echo '(load "${OUT}/def")' >> ${OUT}/makedep.lisp
-	@ echo '(unless (probe-file "${OUT}/metameta.${O}")' \
-          '(compile-file "${OUT}/metameta.${LISP}"' \
-          ':output-file "${OUT}/metameta.${O}"))' >> ${OUT}/makedep.lisp
-	@ echo '(load "${OUT}/metameta")' >> ${OUT}/makedep.lisp
 	@ echo '(unless (probe-file "${OUT}/fnewmeta.${O}")' \
           '(compile-file "${OUT}/fnewmeta.${LISP}"' \
           ':output-file "${OUT}/fnewmeta.${O}"))' >> ${OUT}/makedep.lisp
@@ -1603,53 +1598,6 @@ ${DOC}/metalex.lisp.dvi: ${IN}/metalex.lisp.pamphlet
 
 @
 
-\subsection{metameta.lisp \cite{23}}
-<<metameta.o (AUTO from OUT)>>=
-${AUTO}/metameta.${O}: ${OUT}/metameta.${O}
-	@ echo 71 making ${AUTO}/metameta.${O} from ${OUT}/metameta.${O}
-	@ cp ${OUT}/metameta.${O} ${AUTO}
-
-@
-<<metameta.o (OUT from MID)>>=
-${OUT}/metameta.${O}: ${MID}/metameta.lisp 
-	@ echo 72 making ${OUT}/metameta.${O} from ${MID}/metameta.lisp
-	@ ( cd ${MID} ; \
-	  if [ -z "${NOISE}" ] ; then \
-	   echo '(progn  (compile-file "${MID}/metameta.lisp"' \
-            ':output-file "${OUT}/metameta.${O}") (${BYE}))' | ${DEPSYS} ; \
-	  else \
-	   echo '(progn  (compile-file "${MID}/metameta.lisp"' \
-            ':output-file "${OUT}/metameta.${O}") (${BYE}))' | ${DEPSYS} \
-            >${TMP}/trace ; \
-	  fi )
-	  
-@
-<<metameta.lisp (OUT from MID)>>=
-${OUT}/metameta.${LISP}: ${MID}/metameta.lisp
-	@ echo 73 making ${OUT}/metameta.${LISP} from ${MID}/metameta.lisp
-	@ rm -f ${OUT}/metameta.${O}
-	@ cp ${MID}/metameta.lisp ${OUT}/metameta.${LISP}
-
-@
-<<metameta.lisp (MID from IN)>>=
-${MID}/metameta.lisp: ${IN}/metameta.lisp.pamphlet
-	@ echo 74 making ${MID}/metameta.lisp from ${IN}/metameta.lisp.pamphlet
-	@ ( cd ${MID} ; \
-	  ${TANGLE} ${IN}/metameta.lisp.pamphlet >metameta.lisp )
-	  
-@
-<<metameta.lisp.dvi (DOC from IN)>>=
-${DOC}/metameta.lisp.dvi: ${IN}/metameta.lisp.pamphlet 
-	@echo 75 making ${DOC}/metameta.lisp.dvi from ${IN}/metameta.lisp.pamphlet
-	@(cd ${DOC} ; \
-	cp ${IN}/metameta.lisp.pamphlet ${DOC} ; \
-	${DOCUMENT} ${NOISE} metameta.lisp ; \
-	rm -f ${DOC}/metameta.lisp.pamphlet ; \
-	rm -f ${DOC}/metameta.lisp.tex ; \
-	rm -f ${DOC}/metameta.lisp )
-
-@
-
 \subsection{monitor.lisp \cite{24}}
 <<monitor.o (OUT from MID)>>=
 ${OUT}/monitor.${O}: ${MID}/monitor.lisp
@@ -9019,12 +8967,6 @@ clean:
 <<metalex.lisp (MID from IN)>>
 <<metalex.lisp.dvi (DOC from IN)>>
 
-<<metameta.o (AUTO from OUT)>>
-<<metameta.o (OUT from MID)>>
-<<metameta.lisp (OUT from MID)>>
-<<metameta.lisp (MID from IN)>>
-<<metameta.lisp.dvi (DOC from IN)>>
-
 <<modemap.o (AUTO from OUT)>>
 <<modemap.o (OUT from MID)>>
 <<modemap.clisp (MID from IN)>>
@@ -9406,7 +9348,6 @@ pp
 \bibitem{20} {\bf \$SPAD/src/interp/hash.lisp.pamphlet}
 \bibitem{21} {\bf \$SPAD/src/interp/macros.lisp.pamphlet}
 \bibitem{22} {\bf \$SPAD/src/interp/metalex.lisp.pamphlet}
-\bibitem{23} {\bf \$SPAD/src/interp/metameta.lisp.pamphlet}
 \bibitem{24} {\bf \$SPAD/src/interp/monitor.lisp.pamphlet}
 \bibitem{25} {\bf \$SPAD/src/interp/newaux.lisp.pamphlet}
 \bibitem{26} {\bf \$SPAD/src/interp/nlib.lisp.pamphlet}
diff --git a/src/interp/debug.lisp.pamphlet b/src/interp/debug.lisp.pamphlet
index 9a9e613..f1a4e08 100644
--- a/src/interp/debug.lisp.pamphlet
+++ b/src/interp/debug.lisp.pamphlet
@@ -125,7 +125,6 @@ exit (rds ifile)
 (MAKEPROP 'BOOT '/XCAPE '#\_)
 (MAKEPROP 'SPAD '/XCAPE '#\_)
 (MAKEPROP 'META '/READFUN 'META\,RULE)
-(MAKEPROP 'META '/TRAN '/TRANSMETA)
 (MAKEPROP 'INPUT '/READFUN '|New,LEXPR,Interactive|)
 (MAKEPROP 'INPUT '/TRAN '/TRANSPAD)
 (MAKEPROP 'BOOT '/READFUN '|New,LEXPR1|)
@@ -189,13 +188,13 @@ exit (rds ifile)
 	 ISID NBLNK COMMENTCHR $TOKSTACK (/SOURCEFILES |$sourceFiles|)
 	 METAKEYLST DEFINITION_NAME (|$sourceFileTypes| '(|spad| |boot| |lisp| |lsp| |meta|))
 	 ($FUNCTION FN) $BOOT $NEWSPAD $LINESTACK $LINENUMBER STACK STACKX BACK OK
-	 TRAPFLAG |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE
+	 |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE
 	 (*COMP370-APPLY* (if (eq op 'define) #'eval-defun #'compile-defun)))
 	(declare (special ECHOMETA SINGLINEMODE XCAPE XTOKENREADER INPUTSTREAM
 		     SPADERRORSTREAM ISID NBLNK COMMENTCHR $TOKSTACK /SOURCEFILES
 		     METAKEYLST DEFINITION_NAME |$sourceFileTypes|
 		     $FUNCTION $BOOT $NEWSPAD $LINESTACK $LINENUMBER STACK STACKX BACK OK
-		     TRAPFLAG |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE))
+		     |$InteractiveMode| TOK COUNT ERRCOL COLUMN *QUERY CHR LINE))
         (if (PAIRP FN) (SETQ FN (QCAR FN)))
         (SETQ INFILE (OR INFILE (|getFunctionSourceFile| FN)))
 	  ;; $FUNCTION is freely set in getFunctionSourceFile
@@ -297,7 +296,6 @@ exit (rds ifile)
 		 ;(SETQ ERRCOL 0)
 		 ;(SETQ COUNT 0)
 		 ;(SETQ COLUMN 0)
-		 ;(SETQ TRAPFLAG NIL)
 		 (SETQ OK 'T)
 		 ;(NXTTOK)
 		 ;(SETQ LINE (CURINPUTLINE))
diff --git a/src/interp/debugsys.lisp.pamphlet b/src/interp/debugsys.lisp.pamphlet
index 7f4fa95..1674e8f 100644
--- a/src/interp/debugsys.lisp.pamphlet
+++ b/src/interp/debugsys.lisp.pamphlet
@@ -195,7 +195,6 @@ loaded by hand we need to establish a value.
     (thesymb "/int/interp/def.lisp")
     (thesymb "/int/interp/fnewmeta.lisp")
     (thesymb "/int/interp/metalex.lisp")
-    (thesymb "/int/interp/metameta.lisp")
     (thesymb "/int/interp/parsing.lisp")
     (thesymb "/int/interp/parse.clisp")
     (thesymb "/int/interp/postpar.clisp")
diff --git a/src/interp/interp-proclaims.lisp b/src/interp/interp-proclaims.lisp
index 7d9c8ad..016d485 100644
--- a/src/interp/interp-proclaims.lisp
+++ b/src/interp/interp-proclaims.lisp
@@ -699,8 +699,6 @@
             BOOT::|d03faf| BOOT::|d03eef| BOOT::|d03edf|
             BOOT::|htSystemVariables| BOOT::|htSetVars|
             BOOT::|mkSetTitle| BOOT::|npCategory|
-            BOOT::PARSE-CONS_SEXPR BOOT::PARSE-SEXPR
-            BOOT::PARSE-REF_SEXPR BOOT::PARSE-EXPR2 BOOT::PARSE-EXPR1
             BOOT::|htsv| BOOT::|npDefinitionItem| BOOT::|npDefn|
             BOOT::|npMacro| BOOT::|npMDEFinition| BOOT::|npRule|
             BOOT::RESETHASHTABLES BOOT::READSPADEXPR
@@ -731,8 +729,8 @@
             BOOT::|f02axf| BOOT::|f02awf| BOOT::|f02akf| BOOT::|f02ajf|
             BOOT::|f02agf| BOOT::|htShowPageNoScroll| BOOT::|f02aff|
             BOOT::|f02aef| BOOT::|f02adf| BOOT::|f02abf| BOOT::|f02aaf|
-            BOOT::|measure| BOOT::|writeSaturnSuffix| BOOT::NEWRULE
-            BOOT::PARSE-LOCAL_VAR BOOT::|htErrorStar|
+            BOOT::|measure| BOOT::|writeSaturnSuffix| 
+            BOOT::|htErrorStar|
             BOOT::|queryClients| BOOT::|onDisk| BOOT::|endHTPage|
             BOOT::|readSpadProfileIfThere| BOOT::|bcDraw3Dpar1|
             BOOT::|bcDraw3Dpar| BOOT::|htShowPageStarSaturn|
@@ -842,17 +840,16 @@
             BOOT::|npSCategory| BOOT::|npPrimary| BOOT::|npState|
             BOOT::|npDefaultValue| BOOT::|npAssignVariableName|
             BOOT::|npPDefinition| BOOT::|npDollar|
-            BOOT::|npSQualTypelist| BOOT::PARSE-NON_DEST_REF
-            BOOT::PARSE-OPT_EXPR BOOT::PARSE-REPEATOR
-            BOOT::|npCategoryL| BOOT::PARSE-SEXPR_STRING
-            BOOT::|npProduct| BOOT::PARSE-TEST BOOT::|npIterators|
-            BOOT::PARSE-EXPR BOOT::|npWhile|
-            BOOT::|displayPreCompilationErrors| BOOT::PARSE-N_TEST
-            BOOT::|npForIn| BOOT::PARSE-REP_TEST BOOT::|npGives|
-            BOOT::PARSE-FIL_TEST BOOT::|npLogical| BOOT::PARSE-SUBEXPR
-            BOOT::|npExpress| BOOT::PARSE-FID BOOT::PARSE-RULE
-            BOOT::|npExpress1| BOOT::PARSE-HEADER
-            BOOT::|npCommaBackSet| BOOT::PARSE-RULE1 BOOT::|npQualType|
+            BOOT::|npSQualTypelist| 
+            BOOT::|npCategoryL| 
+            BOOT::|npProduct| BOOT::|npIterators|
+            BOOT::|npWhile|
+            BOOT::|displayPreCompilationErrors| 
+            BOOT::|npForIn| BOOT::|npGives|
+            BOOT::|npLogical| 
+            BOOT::|npExpress| 
+            BOOT::|npExpress1| 
+            BOOT::|npCommaBackSet|  BOOT::|npQualType|
             VMLISP:$TOTAL-GC-TIME BOOT::|npADD|
             BOOT::|npConditionalStatement|
             BOOT::|npQualifiedDefinition| BOOT::|npPushId|
@@ -934,10 +931,10 @@
             BOOT::|menuButton| BOOT::|htSaturnBreak| BOOT::|random|
             BOOT::|dbConsExposureMessage| BOOT::|mkSigPredVectors|
             BOOT::FIRST-ERROR BOOT::|writeSaturnPrefix| BOOT::|on|
-            BOOT::|offDisk| BOOT::|htBigSkip| BOOT::PARSE-PROGRAM
-            BOOT::IN-META BOOT::|traceReply| BOOT::|?t|
+            BOOT::|offDisk| BOOT::|htBigSkip| 
+            BOOT::|traceReply| BOOT::|?t|
             BOOT::SKIP-BLANKS BOOT::|pspacers| BOOT::NEXT-LINES-SHOW
-            BOOT::|resetCounters| BOOT::PARSE-DEST_REF
+            BOOT::|resetCounters| 
             BOOT::SPAD_SHORT_ERROR BOOT::|pcounters|
             BOOT::SPAD_LONG_ERROR BOOT::INIT-BOOT/SPAD-READER
             BOOT::NEXT-LINES-CLEAR BOOT::|resetTimers|
@@ -1675,7 +1672,7 @@
             BOOT::DECIMAL-LENGTH BOOT::|unabbrevAndLoad| BOOT::READLISP
             BOOT::|abbQuery| BOOT::SPAD-EVAL BOOT::/TRANSNBOOT
             BOOT::SPAD-MDTR-2 BOOT::SPAD-MDTR-1 BOOT::/TRANSPAD
-            BOOT::|setAutoLoadProperty| BOOT::/TRANSMETA
+            BOOT::|setAutoLoadProperty| 
             BOOT::|getConstructorUnabbreviation| BOOT::|getLisplibName|
             BOOT::OPTIMIZE&PRINT
             BOOT::|getPartialConstructorModemapSig| BOOT::UNCONS
@@ -2550,7 +2547,7 @@
             BOOT:|initializeSetVariables| BOOT::|inclmsgSay|
             BOOT::|inclmsgConStill| BOOT::|incStringStream|
             BOOT::|inclmsgConActive| BOOT:NUMOFNODES FOAM::TYPE2INIT
-            BOOT:TRANSPGVAR FOAM::FOAM-FUNCTION-INFO BOOT::|GetValue|
+            FOAM::FOAM-FUNCTION-INFO BOOT::|GetValue|
             BOOT::|hasToInfo| FOAM::INSERT-TYPES BOOT::|formatPred|
             BOOT::|chaseInferences,foo| BOOT::|liftCond|
             FOAM::FOAMPROGINFOSTRUCT-P BOOT::|formatInfo|
diff --git a/src/interp/metalex.lisp.pamphlet b/src/interp/metalex.lisp.pamphlet
index 00f1b76..5778b44 100644
--- a/src/interp/metalex.lisp.pamphlet
+++ b/src/interp/metalex.lisp.pamphlet
@@ -58,38 +58,6 @@
  
 (in-package "BOOT")
  
-; *** 1. META file handling
- 
-(defun in-meta ()
-  (setq XTokenReader 'get-META-token)
-  (setq Line-Handler 'next-META-line)
-  (setq Meta_Error_Handler 'meta-meta-error-handler)
-  (setq $BOOT nil))
- 
-(defun newrule ()
-  (in-meta)
-  (setq meta_prefix "PARSE-")
-  (test Rule1)
-  (eval (pop-stack-1))
-  (ioclear)
-  (in-boot))
- 
-(defun meta (&optional (*meta-input-file* "/spad/meta.meta")
-                       (*meta-output-file* nil))
-  (ioclear)
-  (in-meta)
-  (with-open-stream
-    (in-stream (open *meta-input-file* :direction :input))
-    (with-open-stream
-      (out-stream (if *meta-output-file*
-               (open *meta-output-file* :direction :output)
-               *terminal-io*))
-      (format out-stream
-	      "~&;;; -*- Mode:Lisp; Package:Boot  -*-~%~%")
-      (parse-program)
-      (IOClear in-stream out-stream)))
-  T)
- 
 ; *** 2. META Line Handling
  
 (defun next-META-line (&optional (in-stream t))
@@ -319,6 +287,26 @@ special character be the atom whose print name is the character itself."
              (incf $num_of_meta_errors)
              (setq Meta_Errors_Occurred t)))
    nil)
+
+; (trace skip-blanks)
+; (trace get-special-token)
+; (trace token-lookahead-type)
+; (trace make-adjustable-string)
+; (trace print-package)
+; (trace get-number-token)
+
+(trace next-META-line)
+(trace kill-comments)
+(trace kill-trailing-blanks)
+(trace get-META-token)
+(trace get-identifier-token)
+(trace get-string-token)
+(trace get-bstring-token)
+(trace make-defun)
+(trace print-fluids)
+(trace set-prefix)
+(trace print-rule)
+(trace meta-meta-error-handler)
 @
 \eject
 \begin{thebibliography}{99}
diff --git a/src/interp/metameta.lisp.pamphlet b/src/interp/metameta.lisp.pamphlet
deleted file mode 100644
index 47070f8..0000000
--- a/src/interp/metameta.lisp.pamphlet
+++ /dev/null
@@ -1,384 +0,0 @@
-\documentclass{article}
-\usepackage{axiom}
-\begin{document}
-\title{\$SPAD/src/interp metameta.lisp}
-\author{Timothy Daly}
-\maketitle
-\begin{abstract}
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-\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.
-
-@
-<<*>>=
-<<license>>
-
-; .META(META PROGRAM)
-; .PREFIX 'PARSE-'
-; .PACKAGE 'PARSING'
-; .DECLARE(METAPGVAR METAVARLST METAKEYLST METARULNAM TRAPFLAG)
- 
-(IN-PACKAGE "BOOT")
- 
-(DEFPARAMETER METAPGVAR NIL)
-(DEFPARAMETER METAVARLST NIL)
-(DEFPARAMETER METAKEYLST NIL)
-(DEFPARAMETER METARULNAM NIL)
-(DEFPARAMETER TRAPFLAG NIL)
- 
-; PROGRAM:<HEADER*>! <RULE*>! ='.FIN' ;
- 
-(DEFUN PARSE-PROGRAM NIL
-  (AND (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-HEADER))))
-       (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-RULE))))
-       (MATCH-STRING ".FIN")))
- 
-; HEADER:       '.META' '(' IDENTIFIER IDENTIFIER <IDENTIFIER>! ')' .(SETQ XNAME ##3)
-; / '.DECLARE' '(' IDENTIFIER* ')' .(PRINT-FLUIDS #1)
-; / '.PREFIX' STRING .(SET-PREFIX #1)
-; / '.PACKAGE' STRING .(PRINT-PACKAGE #1) ;
- 
-(DEFUN PARSE-HEADER NIL
-  (OR (AND (MATCH-ADVANCE-STRING ".META")
-           (MUST (MATCH-ADVANCE-STRING "("))
-           (MUST (PARSE-IDENTIFIER))
-           (MUST (PARSE-IDENTIFIER))
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-IDENTIFIER)))
-           (MUST (MATCH-ADVANCE-STRING ")"))
-           (ACTION (SETQ XNAME (NTH-STACK 3))))
-      (AND (MATCH-ADVANCE-STRING ".DECLARE")
-           (MUST (MATCH-ADVANCE-STRING "("))
-           (MUST (STAR REPEATOR (PARSE-IDENTIFIER)))
-           (MUST (MATCH-ADVANCE-STRING ")"))
-           (ACTION (PRINT-FLUIDS (POP-STACK-1))))
-      (AND (MATCH-ADVANCE-STRING ".PREFIX")
-           (MUST (PARSE-STRING))
-           (ACTION (SET-PREFIX (POP-STACK-1))))
-      (AND (MATCH-ADVANCE-STRING ".PACKAGE")
-           (MUST (PARSE-STRING))
-           (ACTION (PRINT-PACKAGE (POP-STACK-1))))))
- 
-; RULE:     RULE1 ';' .(PRINT-RULE #1) / ^='.FIN' .(META-SYNTAX-ERROR) ;
- 
-(DEFUN PARSE-RULE NIL
-  (OR (AND (PARSE-RULE1)
-           (MUST (MATCH-ADVANCE-STRING ";"))
-           (ACTION (PRINT-RULE (POP-STACK-1))))
-      (AND (NOT (MATCH-STRING ".FIN"))
-           (ACTION (META-SYNTAX-ERROR)))))
- 
-; RULE1: IDENTIFIER .(SETQ METARULNAM (INTERN (STRCONC META_PREFIX ##1)))
-; <'{' FID* '}'>! ':' EXPR =';'
-; < =$METAPGVAR +(PROG =(TRANSPGVAR METAPGVAR) (RETURN #1))
-; .(SETQ METAPGVAR NIL) >
-; +=(MAKE-DEFUN #3 #2 #1) ;
- 
-(DEFUN PARSE-RULE1 NIL
-  (AND (PARSE-IDENTIFIER)
-       (ACTION (SETQ METARULNAM (INTERN (STRCONC |META_PREFIX| (NTH-STACK 1)))))
-       (BANG |FIL_TEST|
-             (OPTIONAL (AND (MATCH-ADVANCE-STRING "{")
-                            (MUST (STAR REPEATOR (PARSE-FID)))
-                            (MUST (MATCH-ADVANCE-STRING "}")))))
-       (MUST (MATCH-ADVANCE-STRING ":"))
-       (MUST (PARSE-EXPR))
-       (MUST (MATCH-STRING ";"))
-       (OPTIONAL (AND METAPGVAR
-                      (PUSH-REDUCTION 'PARSE-RULE1
-                                      (CONS 'PROG
-                                            (CONS (TRANSPGVAR METAPGVAR)
-                                                  (CONS (CONS
-                                                         'RETURN
-                                                         (CONS (POP-STACK-1) NIL))
-                                                        NIL))))
-                      (ACTION (SETQ METAPGVAR NIL))))
-       (PUSH-REDUCTION 'PARSE-RULE1
-                       (MAKE-DEFUN (POP-STACK-3) (POP-STACK-2) (POP-STACK-1)))))
- 
-; FID:  IDENTIFIER +#1 ;
- 
-(DEFUN PARSE-FID NIL
-  (AND (PARSE-IDENTIFIER)
-       (PUSH-REDUCTION 'PARSE-FID (POP-STACK-1))))
- 
-; EXPR:   SUBEXPR
-; <   EXPR1* +(OR #2 -#1)
-; / EXPR2* +(OR #2 -#1) >  ;
- 
-(DEFUN PARSE-EXPR NIL
-  (AND (PARSE-SUBEXPR)
-       (OPTIONAL (OR (AND (STAR REPEATOR (PARSE-EXPR1))
-                          (PUSH-REDUCTION 'PARSE-EXPR
-                                          (CONS 'OR
-                                                (CONS (POP-STACK-2)
-                                                      (APPEND (POP-STACK-1) NIL)))))
-                     (AND (STAR REPEATOR (PARSE-EXPR2))
-                          (PUSH-REDUCTION 'PARSE-EXPR
-                                          (CONS 'OR
-                                                (CONS (POP-STACK-2)
-                                                      (APPEND (POP-STACK-1) NIL)))))))))
- 
-; EXPR1:  '/' <^'/'>  SUBEXPR   ;
- 
-(DEFUN PARSE-EXPR1 NIL
-  (AND (MATCH-ADVANCE-STRING "/")
-       (OPTIONAL (NOT (MATCH-ADVANCE-STRING "/")))
-       (MUST (PARSE-SUBEXPR))))
- 
-; EXPR2:  '\\' <^'\\'>  SUBEXPR  ;
- 
-(DEFUN PARSE-EXPR2 NIL
-  (AND (MATCH-ADVANCE-STRING "\\")
-       (OPTIONAL (NOT (MATCH-ADVANCE-STRING "\\")))
-       (MUST (PARSE-SUBEXPR))))
- 
-; SUBEXPR:FIL_TEST <^?$TRAPFLAG FIL_TEST>*!
-; <FIL_TEST <?$TRAPFLAG +(MUST #1)> >*!
-; +(#3 -#2 -#1) +=(MAKE-PARSE-FUNCTION #1 "AND) ;
- 
-(DEFUN PARSE-SUBEXPR NIL
-  (AND (PARSE-FIL_TEST)
-       (BANG |FIL_TEST|
-             (OPTIONAL (STAR |OPT_EXPR|
-                             (AND (NOT TRAPFLAG)
-                                  (PARSE-FIL_TEST)))))
-       (BANG |FIL_TEST|
-             (OPTIONAL (STAR |OPT_EXPR|
-                             (AND (PARSE-FIL_TEST)
-                                  (OPTIONAL (AND TRAPFLAG
-                                                 (PUSH-REDUCTION 'PARSE-SUBEXPR
-                                                                 (CONS
-                                                                  'MUST
-                                                                  (CONS (POP-STACK-1) NIL))))))
-                             )))
-       (PUSH-REDUCTION 'PARSE-SUBEXPR
-                       (CONS (POP-STACK-3)
-                             (APPEND (POP-STACK-2) (APPEND (POP-STACK-1) NIL))))
-       (PUSH-REDUCTION 'PARSE-SUBEXPR (MAKE-PARSE-FUNCTION (POP-STACK-1) 'AND))))
- 
-; FIL_TEST: REP_TEST <'!' +(BANG FIL_TEST #1)>      ;
- 
-(DEFUN PARSE-FIL_TEST NIL
-  (AND (PARSE-REP_TEST)
-       (OPTIONAL (AND (MATCH-ADVANCE-STRING "!")
-                      (PUSH-REDUCTION 'PARSE-FIL_TEST
-                                      (CONS 'BANG
-                                            (CONS '|FIL_TEST| (CONS (POP-STACK-1) NIL))))))))
- 
-; REP_TEST: N_TEST <REPEATOR>  ;
- 
-(DEFUN PARSE-REP_TEST NIL
-  (AND (PARSE-N_TEST)
-       (OPTIONAL (PARSE-REPEATOR))))
- 
-; N_TEST:   '^' TEST  +(NOT #1) / TEST  ;
- 
-(DEFUN PARSE-N_TEST NIL
-  (OR (AND (MATCH-ADVANCE-STRING "^")
-           (MUST (PARSE-TEST))
-           (PUSH-REDUCTION 'PARSE-N_TEST (CONS 'NOT (CONS (POP-STACK-1) NIL))))
-      (PARSE-TEST)))
- 
-; TEST:     IDENTIFIER (    '{' <SEXPR*>! '}'
-; +(=(INTERN (STRCONC META_PREFIX #2)) -#1)
-; / +(=(INTERN (STRCONC META_PREFIX #1))))        .(SETQ TRAPFLAG T)
-; / STRING  +(MATCH-ADVANCE-STRING #1)            .(SETQ TRAPFLAG T)
-; / '=' REF_SEXPR                                 .(SETQ TRAPFLAG T)
-; / '?' REF_SEXPR                                 .(SETQ TRAPFLAG NIL)
-; / '.' SEXPR         +(ACTION #1)                .(SETQ TRAPFLAG NIL)
-; / '+' CONS_SEXPR    +(PUSH-REDUCTION =(LIST "QUOTE METARULNAM) #1)
-; .(SETQ TRAPFLAG NIL)
-; / '(' EXPR ')'                                  .(SETQ TRAPFLAG T)
-; / '<' EXPR '>'      .(PARSE-OPT_EXPR)           .(SETQ TRAPFLAG NIL) ;
- 
-(DEFUN PARSE-TEST NIL
-  (OR (AND (PARSE-IDENTIFIER)
-           (MUST (OR (AND (MATCH-ADVANCE-STRING "{")
-                          (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-SEXPR))))
-                          (MUST (MATCH-ADVANCE-STRING "}"))
-                          (PUSH-REDUCTION 'PARSE-TEST
-                                          (CONS (INTERN (STRCONC
-                                                         |META_PREFIX|
-                                                         (POP-STACK-2)))
-                                                (APPEND (POP-STACK-1) NIL))))
-                     (PUSH-REDUCTION 'PARSE-TEST
-                                     (CONS (INTERN (STRCONC |META_PREFIX| (POP-STACK-1)))
-                                           NIL))))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (PARSE-STRING)
-           (PUSH-REDUCTION 'PARSE-TEST
-                           (CONS 'MATCH-ADVANCE-STRING (CONS (POP-STACK-1) NIL)))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (MATCH-ADVANCE-STRING "=")
-           (MUST (PARSE-REF_SEXPR))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (MATCH-ADVANCE-STRING "?")
-           (MUST (PARSE-REF_SEXPR))
-           (ACTION (SETQ TRAPFLAG NIL)))
-      (AND (MATCH-ADVANCE-STRING ".")
-           (MUST (PARSE-SEXPR))
-           (PUSH-REDUCTION 'PARSE-TEST (CONS 'ACTION (CONS (POP-STACK-1) NIL)))
-           (ACTION (SETQ TRAPFLAG NIL)))
-      (AND (MATCH-ADVANCE-STRING "+")
-           (MUST (PARSE-CONS_SEXPR))
-           (PUSH-REDUCTION 'PARSE-TEST
-                           (CONS 'PUSH-REDUCTION
-                                 (CONS (LIST 'QUOTE METARULNAM) (CONS (POP-STACK-1) NIL))))
-           (ACTION (SETQ TRAPFLAG NIL)))
-      (AND (MATCH-ADVANCE-STRING "(")
-           (MUST (PARSE-EXPR))
-           (MUST (MATCH-ADVANCE-STRING ")"))
-           (ACTION (SETQ TRAPFLAG T)))
-      (AND (MATCH-ADVANCE-STRING "<")
-           (MUST (PARSE-EXPR))
-           (MUST (MATCH-ADVANCE-STRING ">"))
-           (ACTION (PARSE-OPT_EXPR))
-           (ACTION (SETQ TRAPFLAG NIL)))))
- 
-; SEXPR:          IDENTIFIER / NUMBER / STRING / NON_DEST_REF / DEST_REF / LOCAL_VAR
-; / '"' SEXPR +(QUOTE #1) / '=' SEXPR / '(' <SEXPR*>! ')' ;
- 
-(DEFUN PARSE-SEXPR NIL
-  (OR (PARSE-IDENTIFIER)
-      (PARSE-NUMBER)
-      (PARSE-STRING)
-      (PARSE-NON_DEST_REF)
-      (PARSE-DEST_REF)
-      (PARSE-LOCAL_VAR)
-      (AND (MATCH-ADVANCE-STRING "\"")
-           (MUST (PARSE-SEXPR))
-           (PUSH-REDUCTION 'PARSE-SEXPR (CONS 'QUOTE (CONS (POP-STACK-1) NIL))))
-      (AND (MATCH-ADVANCE-STRING "=")
-           (MUST (PARSE-SEXPR)))
-      (AND (MATCH-ADVANCE-STRING "(")
-           (BANG |FIL_TEST| (OPTIONAL (STAR REPEATOR (PARSE-SEXPR))))
-           (MUST (MATCH-ADVANCE-STRING ")")))))
- 
-; REF_SEXPR: STRING +(MATCH-STRING #1) / SEXPR ;
- 
-(DEFUN PARSE-REF_SEXPR NIL
-  (OR (AND (PARSE-STRING)
-           (PUSH-REDUCTION 'PARSE-REF_SEXPR (CONS 'MATCH-STRING (CONS (POP-STACK-1) NIL))))
-      (PARSE-SEXPR)))
- 
-; CONS_SEXPR: IDENTIFIER <^=(MEMBER ##1 METAPGVAR) +(QUOTE #1)>
-; / LOCAL_VAR +(QUOTE #1)
-; / '(' <SEXPR_STRING>! ')'
-; / SEXPR ;
- 
-(DEFUN PARSE-CONS_SEXPR NIL
-  (OR (AND (PARSE-IDENTIFIER)
-           (OPTIONAL (AND (NOT (MEMBER (NTH-STACK 1) METAPGVAR))
-                          (PUSH-REDUCTION 'PARSE-CONS_SEXPR
-                                          (CONS 'QUOTE (CONS (POP-STACK-1) NIL))))))
-      (AND (PARSE-LOCAL_VAR)
-           (PUSH-REDUCTION 'PARSE-CONS_SEXPR (CONS 'QUOTE (CONS (POP-STACK-1) NIL))))
-      (AND (MATCH-ADVANCE-STRING "(")
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-SEXPR_STRING)))
-           (MUST (MATCH-ADVANCE-STRING ")")))
-      (PARSE-SEXPR)))
- 
-; SEXPR_STRING: CONS_SEXPR <SEXPR_STRING>!    +(CONS #2 #1)
-; / '-' CONS_SEXPR <SEXPR_STRING>! +(APPEND #2 #1)      ;
- 
-(DEFUN PARSE-SEXPR_STRING NIL
-  (OR (AND (PARSE-CONS_SEXPR)
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-SEXPR_STRING)))
-           (PUSH-REDUCTION 'PARSE-SEXPR_STRING
-                           (CONS 'CONS (CONS (POP-STACK-2) (CONS (POP-STACK-1) NIL)))))
-      (AND (MATCH-ADVANCE-STRING "-")
-           (MUST (PARSE-CONS_SEXPR))
-           (BANG |FIL_TEST| (OPTIONAL (PARSE-SEXPR_STRING)))
-           (PUSH-REDUCTION 'PARSE-SEXPR_STRING
-                           (CONS 'APPEND (CONS (POP-STACK-2) (CONS (POP-STACK-1) NIL)))))))
- 
-; NON_DEST_REF: '##' NUMBER +(NTH-STACK #1) ;
- 
-(DEFUN PARSE-NON_DEST_REF NIL
-  (AND (MATCH-ADVANCE-STRING "##")
-       (MUST (PARSE-NUMBER))
-       (PUSH-REDUCTION 'PARSE-NON_DEST_REF (CONS 'NTH-STACK (CONS (POP-STACK-1) NIL)))))
- 
-; DEST_REF:     '#' NUMBER +=(LIST (INTERN (STRCONC 'POP-STACK-' (STRINGIMAGE #1)))) ;
- 
-(DEFUN PARSE-DEST_REF NIL
-  (AND (MATCH-ADVANCE-STRING "#")
-       (MUST (PARSE-NUMBER))
-       (PUSH-REDUCTION 'PARSE-DEST_REF
-                       (LIST (INTERN (STRCONC "POP-STACK-" (STRINGIMAGE (POP-STACK-1))))))))
- 
-; LOCAL_VAR:    '$' (   IDENTIFIER / NUMBER +=(GETGENSYM #1) .(PUSH ##1 METAPGVAR)) ;
- 
-(DEFUN PARSE-LOCAL_VAR NIL
-  (AND (MATCH-ADVANCE-STRING "$")
-       (MUST (OR (PARSE-IDENTIFIER)
-                 (AND (PARSE-NUMBER)
-                      (PUSH-REDUCTION 'PARSE-LOCAL_VAR (GETGENSYM (POP-STACK-1)))
-                      (ACTION (PUSH (NTH-STACK 1) METAPGVAR)))))))
- 
-; OPT_EXPR:     <'*' +(STAR OPT_EXPR #1) / REPEATOR> +(OPTIONAL #1) ;
- 
-(DEFUN PARSE-OPT_EXPR NIL
-  (AND (OPTIONAL (OR (AND (MATCH-ADVANCE-STRING "*")
-                          (PUSH-REDUCTION 'PARSE-OPT_EXPR
-                                          (CONS 'STAR
-                                                (CONS '|OPT_EXPR|
-                                                      (CONS (POP-STACK-1) NIL)))))
-                     (PARSE-REPEATOR)))
-       (PUSH-REDUCTION 'PARSE-OPT_EXPR (CONS 'OPTIONAL (CONS (POP-STACK-1) NIL)))))
- 
-; REPEATOR:     ('*' / BSTRING +(AND (MATCH-ADVANCE-STRING #1) (MUST ##1)))
-; +(STAR REPEATOR #1) ;
- 
-(DEFUN PARSE-REPEATOR NIL
-  (AND (OR (MATCH-ADVANCE-STRING "*")
-           (AND (PARSE-BSTRING)
-                (PUSH-REDUCTION 'PARSE-REPEATOR
-                                (CONS 'AND
-                                      (CONS (CONS 'MATCH-ADVANCE-STRING
-                                                  (CONS (POP-STACK-1) NIL))
-                                            (CONS (CONS 'MUST (CONS (NTH-STACK 1) NIL))
-                                                  NIL))))))
-       (PUSH-REDUCTION 'PARSE-REPEATOR
-                       (CONS 'STAR (CONS 'REPEATOR (CONS (POP-STACK-1) NIL))))))
- 
-; .FIN ;
-@
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} nothing
-\end{thebibliography}
-\end{document}
diff --git a/src/interp/parsing.lisp.pamphlet b/src/interp/parsing.lisp.pamphlet
index cce7470..8dbb420 100644
--- a/src/interp/parsing.lisp.pamphlet
+++ b/src/interp/parsing.lisp.pamphlet
@@ -53,10 +53,6 @@
 ;          in META/LISP, R.D. Jenks, Tech Report, IBM T.J. Watson Research Center,
 ;          1969.  Familiarity with this document is assumed.
 ;
-;          The parser generator itself is described in either the file
-;          MetaBoot.lisp (hand-coded version) or the file MetaMeta.lisp (machine
-;          generated from self-descriptive Meta code), both of which load themselves
-;          into package Parsing.
 
 ; CONTENTS:
 ;
@@ -85,8 +81,6 @@
 ;       5. Routines for inspecting and resetting total I/O system state
 ;
 ;       METALEX.LISP:  Meta file handling, auxiliary parsing actions and tokenizing
-;       METAMETA.LISP: Meta parsing
-;
 ;       BOOTLEX.LISP:  Boot file handling, auxiliary parsing actions and tokenizing
 ;       NEWMETA.LISP:  Boot parsing
 
@@ -875,8 +869,6 @@ Symbolics read-line returns embedded newlines in a c-m-Y.")
 
 (defparameter /genvarlst nil    "??")
 
-(defun transpgvar (metapgvar) (remove-duplicates metapgvar))
-
 (defparameter /gensymlist nil   "List of rule local variables generated by getgensym.")
 
 (defun getgensym (n)
diff --git a/src/interp/spad.lisp.pamphlet b/src/interp/spad.lisp.pamphlet
index c39b435..cfc828f 100644
--- a/src/interp/spad.lisp.pamphlet
+++ b/src/interp/spad.lisp.pamphlet
@@ -169,15 +169,6 @@
 
 (DEFUN /TRANSNBOOT (X) (S-PROCESS X) NIL)
 
-(DEFUN /TRANSMETA (X)
-  (PROG (KEYNAM ROOTFN U)
-	(SETQ ROOTFN (/MFINDROOT (CAR /SOURCEFILES)))
-	(SETQ $LASTPREFIX (GET ROOTFN 'METAPFX))
-	(SETQ KEYNAM (INTERNL $LASTPREFIX (PNAME ROOTFN) "KEY"))
-	(SET KEYNAM (REMDUP (APPEND METAKEYLST (EVAL KEYNAM))))
-	(SETQ U (GETRULEFUNLISTS ROOTFN (LIST X)))
-	(SUBLISNQ (PAIR (CADR U) (CAR U)) X)))
-
  ;; NIL needed below since END\_UNIT is not generated by current parser
 (defun |isTokenDelimiter| () (MEMBER (CURRENT-SYMBOL) '(\) END\_UNIT NIL)))
 
@@ -486,7 +477,7 @@ special.
     (let (ZZ str N RLGENSYMFG RLGENSYMLST |NewFLAG| XCAPE *PROMPT*
 	  SINGLELINEMODE OK ISID NBLNK COUNT CHR ULCASEFG ($LINESTACK 'BEGIN_UNIT)
 	  $NEWLINSTACK $TOKSTACK COMMENTCHR TOK LINE BACK INPUTSTREAM XTRANS
-	  XTOKENREADER STACK STACKX TRAPFLAG)
+	  XTOKENREADER STACK STACKX)
       (SETQ XTRANS '|boot-New|
 	    XTOKENREADER 'NewSYSTOK
 	    SYNTAX_ERROR 'SPAD_SYNTAX_ERROR)
@@ -563,7 +554,7 @@ special.
 	  (NewFLAG T) (XTRANS '|boot-New|) (XCAPE '!)
 	  (COMMENTCHR 'NOTHING)	 (XTOKENREADER 'NewSYSTOK)
 	  ($NBOOT T) (ERRCOL 0) (COUNT 0) (COLUMN 0)
-	  (TRAPFLAG NIL) (OK T)	 (SPADERRORSTREAM CUROUTSTREAM)
+	  (OK T) (SPADERRORSTREAM CUROUTSTREAM)
 	  ($LINESTACK 'BEGIN_UNIT)
 	  (INPUTSTREAM LINESET)
 	  (CHR 'ENDOFLINECHR))
diff --git a/src/interp/sys-pkg.lisp.pamphlet b/src/interp/sys-pkg.lisp.pamphlet
index 850237d..eaa76b7 100644
--- a/src/interp/sys-pkg.lisp.pamphlet
+++ b/src/interp/sys-pkg.lisp.pamphlet
@@ -174,7 +174,7 @@ provides support for compiler code.
 	 BOOT::$FILELINENUMBER BOOT::|$timerTicksPerSecond|
 	 BOOT::|bootUnionPrint| BOOT::|$consistencyCheck|
 	 BOOT::|$oldTime| BOOT::$NEWSPAD BOOT::NUMOFNODES
-	 BOOT::|$ResMode| BOOT::S* BOOT::TRANSPGVAR BOOT::$BOXSTRING
+	 BOOT::|$ResMode| BOOT::S*  BOOT::$BOXSTRING
 	 BOOT::|$BasicPredicates| BOOT::|$eltIfNil| BOOT::$FUNNAME_TAIL
 	 BOOT::|$QuickCode| BOOT::GENVAR BOOT::|$TypeEqui|
 	 BOOT::TOKEN-TYPE BOOT::|updateSourceFiles| BOOT::|$BFtag|

\start
Date: Mon, 27 Aug 2007 02:24:47 -0500
From: Tim Daly
To: list
Subject: 20070811.02.tpd.patch applied to silver

diff --git a/changelog b/changelog
index e3d84c9..6b8cd6f 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070811 gxv src/interp/metalex.lisp remove trace commands
 20070811 tpd src/input/Makefile add mathml.input
 20070811 tpd src/input/mathml.input write test cases
 20070810 tpd readme add Arthur C. Ralfs
diff --git a/src/interp/metalex.lisp.pamphlet b/src/interp/metalex.lisp.pamphlet
index 5778b44..bd491f9 100644
--- a/src/interp/metalex.lisp.pamphlet
+++ b/src/interp/metalex.lisp.pamphlet
@@ -288,25 +288,6 @@ special character be the atom whose print name is the character itself."
              (setq Meta_Errors_Occurred t)))
    nil)
 
-; (trace skip-blanks)
-; (trace get-special-token)
-; (trace token-lookahead-type)
-; (trace make-adjustable-string)
-; (trace print-package)
-; (trace get-number-token)
-
-(trace next-META-line)
-(trace kill-comments)
-(trace kill-trailing-blanks)
-(trace get-META-token)
-(trace get-identifier-token)
-(trace get-string-token)
-(trace get-bstring-token)
-(trace make-defun)
-(trace print-fluids)
-(trace set-prefix)
-(trace print-rule)
-(trace meta-meta-error-handler)
 @
 \eject
 \begin{thebibliography}{99}

\start
Date: Mon, 27 Aug 2007 02:27:02 -0500
From: Tim Daly
To: list
Subject: 20070811.03.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 6b8cd6f..bede2a3 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,6 @@
+20070811 sxw src/interp/i-output.boot use digits-by-radix
+20070811 sxw src/interp/sys-pkg.lisp add digits-by-radix export
+20070811 sxw src/interp/vmlisp.lisp add digits-by-radix function
 20070811 gxv src/interp/metalex.lisp remove trace commands
 20070811 tpd src/input/Makefile add mathml.input
 20070811 tpd src/input/mathml.input write test cases
diff --git a/src/interp/i-output.boot.pamphlet b/src/interp/i-output.boot.pamphlet
index a1a84ab..b1066aa 100644
--- a/src/interp/i-output.boot.pamphlet
+++ b/src/interp/i-output.boot.pamphlet
@@ -9,25 +9,6 @@
 \eject
 \tableofcontents
 \eject
-\section{GCL\_log10\_bug}
-In some versions of GCL the LOG10 function returns improperly rounded values.
-The symptom is:
-\begin{verbatim}
-(24) -> [1000]
-   (24)  [100]
-\end{verbatim}
-The common lisp failure can be shown with:
-\begin{verbatim}
-(25) -> )lisp (log10 1000)
-Value = 2.9999999999999996
-\end{verbatim}
-This previous boot code was:
-\begin{verbatim}
-    u < MOST_-POSITIVE_-LONG_-FLOAT => 1+negative+FLOOR LOG10 u
-\end{verbatim}
-and should be restored when the GCL bug is fixed.
-<<GCLlog10bug>>=
-    u < MOST_-POSITIVE_-LONG_-FLOAT => 1+negative+FLOOR ((LOG10 u) + 0.0000001)
 @ 
 \section{License}
 <<license>>=
@@ -887,18 +868,12 @@ WIDTH u ==
     u.0="%" and ((u.1 = char 'b) or (u.1 = char 'd)) => 1
     #u
   INTEGERP u => 
+    u = 0 => 1
     if (u < 1) then 
       negative := 1
-      u := -u
     else
       negative := 0
-    -- Try and be fairly exact for smallish integers:
-    u = 0 => 1
-<<GCLlog10bug>>
-    -- Rough guess: integer-length returns log2 rounded up, so divide it by
-    -- roughly log2(10). This should return an over-estimate, but for objects
-    -- this big does it matter?
-    FLOOR(INTEGER_-LENGTH(u)/3.3)
+    DIGITS_-BY_-RADIX(u, 10) + negative
   atom u => # atom2String u
   putWidth u is [[.,:n],:.] => n
   THROW('outputFailure,'outputFailure)
diff --git a/src/interp/sys-pkg.lisp.pamphlet b/src/interp/sys-pkg.lisp.pamphlet
index eaa76b7..9a56b7c 100644
--- a/src/interp/sys-pkg.lisp.pamphlet
+++ b/src/interp/sys-pkg.lisp.pamphlet
@@ -337,7 +337,7 @@ provides support for compiler code.
 <<GCL.DEFINE-MACRO>>
 <<GCL.MEMQ>>
 <<GCL.PNAME>>
-         VMLISP::PUT
+         VMLISP::PUT VMLISP::DIGITS-BY-RADIX
 	 VMLISP::QVELT-1 VMLISP::QSETVELT-1 vmlisp::throw-protect
 	 VMLISP::|directoryp| VMLISP::EQCAR
 	 VMLISP::DEFIOSTREAM VMLISP::RDEFIOSTREAM VMLISP::MLAMBDA
diff --git a/src/interp/vmlisp.lisp.pamphlet b/src/interp/vmlisp.lisp.pamphlet
index 7247d7a..2478e04 100644
--- a/src/interp/vmlisp.lisp.pamphlet
+++ b/src/interp/vmlisp.lisp.pamphlet
@@ -95,6 +95,62 @@ Contributed by Juergen Weiss.
 (defun get-current-directory ()
   (namestring (truename "")))
 
+@ 
+\section{The digits-by-radix function} 
+The purpose of the following function is to calculate the number of
+digits in the radix $B$ expansion of an arbitrary Lisp integer $n$.
+The width of an integer can be determined rapidly when the radix is a
+power of two, otherwise an approach based on successive divisions is
+used.
+
+<<digits-by-radix>>=
+(defun digits-by-radix (n &optional (radix 10))
+  (flet (<<power-of-two-width>>
+         <<iterative-width>>)
+    (assert (>= radix 2) (radix) 
+            "Bad radix ~D < 2 given to DIGITS-BY-RADIX." radix)
+    (setq n (abs n))
+    (cond
+      ((zerop n) (values 1))
+      ((zerop (logand radix (1- radix))) (power-of-two-width n radix))
+      (t (iterative-width n radix)))))
+
+@ When the radix $B$ is of the form $2^b$, $b$ bits are needed to
+represent one radix $B$ digit. The radix $B$ width of $n$ is obtained
+by dividing the width of the binary representation of $n$ by $b$, and
+incrementing the result when the remainder is non-zero.
+
+<<power-of-two-width>>=
+ (power-of-two-width (n radix)
+   (let ((bits (integer-length n))
+         (radix-bits (1- (integer-length radix))))
+     (multiple-value-bind (quo rem) (floor bits radix-bits)
+       (if (zerop rem) quo (1+ quo)))))
+
+@ When the radix is not a power of two, we choose a power $p$ of the
+radix $B$ and use $B^p$ as a divisor.  Each division counts as $p$
+digits in the radix $B$ expansion.  The power, bound to the variable
+[[digits]] below, is chosen so that $B^p <$
+\texttt{most-positive-long-float}. This allows use of [[log]] to
+compute $p$ without concern for floating point overflow.  Once a
+quotient is produced which is smaller than the divisor, we complete
+the calculation by repeated divisions using the radix itself.
+
+<<iterative-width>>=
+ (iterative-width (n radix)
+   (multiple-value-bind (q width)
+       (let* ((target (if (< n most-positive-long-float)
+                          (values n)
+                          (values most-positive-long-float)))
+              (digits (let ((d (floor (log target radix))))
+                        (if (zerop d) 1 d)))
+              (div (expt radix digits)))
+         (loop for q = n then (floor q div)
+               until (< q div) sum digits into width
+               finally (return (values q width))))
+     (+ width (loop for r = q then (floor r radix)
+                    until (zerop r) count t))))
+
 @
 \section{License}
 <<license>>=
@@ -133,6 +189,7 @@ Contributed by Juergen Weiss.
 <<*>>=
 <<license>>
 
+
 ;      VM LISP EMULATION PACKAGE
 ;      Lars Ericson, Barry Trager, Martial Schor, tim daly, LVMCL, et al
 ;      IBM Thomas J. Watson Research Center
@@ -945,6 +1002,8 @@ Contributed by Juergen Weiss.
 
 ; 12.0 Operations on Numbers
 
+<<digits-by-radix>>
+
 ; 12.1 Conversion
 
 (define-function 'FIX #'truncate)

\start
Date: Mon, 27 Aug 2007 02:31:36 -0500
From: Tim Daly
To: list
Subject: 20070812.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 0aeec85..19aff4b 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070812 tpd re-merge input branch
 20070811 tpd src/input/Makefile add classtalk, calcprob
 20070811 tpd src/input/limit.input.pamphlet updated with new tests
 20070811 tpd src/input/intbypart.input.pamphlet updated with new tests
diff --git a/src/input/Makefile.pamphlet b/src/input/Makefile.pamphlet
index 621d8ed..34850f2 100644
--- a/src/input/Makefile.pamphlet
+++ b/src/input/Makefile.pamphlet
@@ -292,9 +292,10 @@ REGRES= algaggr.regress algbrbf.regress  algfacob.regress alist.regress  \
     binary.regress    bop.regress      bstree.regress   bouquet.regress \
     bug10069.regress \
     bugs.regress      bug10312.regress bug6357.regress  bug9057.regress \
+    calcprob.regress  \
     calculus2.regress calculus.regress cardinal.regress card.regress \
     carten.regress    cclass.regress   char.regress     ch.regress \
-    chtheorem.regress \
+    chtheorem.regress classtalk.regress \
     clifford.regress  clif.regress     coercels.regress collect.regress \
     complex.regress   conformal.regress \
     constant.regress  contfrac.regress contfrc.regress \
@@ -486,10 +487,10 @@ FILES= ${OUT}/algaggr.input  ${OUT}/algbrbf.input    ${OUT}/algfacob.input \
        ${OUT}/bernpoly.input ${OUT}/binary.input     ${OUT}/bop.input \
        ${OUT}/bouquet.input  ${OUT}/bstree.input     ${OUT}/bug6357.input \
        ${OUT}/bug9057.input  ${OUT}/bug10069.input   ${OUT}/bug10312.input \
-       ${OUT}/calculus.input \
+       ${OUT}/calcprob.input ${OUT}/calculus.input \
        ${OUT}/cardinal.input ${OUT}/card.input       ${OUT}/carten.input \
        ${OUT}/cclass.input   ${OUT}/cdraw.input      ${OUT}/char.input \
-       ${OUT}/ch.input       ${OUT}/chtheorem.input \
+       ${OUT}/ch.input       ${OUT}/chtheorem.input  ${OUT}/classtalk.input \
        ${OUT}/clifford.input ${OUT}/clif.input \
        ${OUT}/coercels.input ${OUT}/collect.input    ${OUT}/color.input \
        ${OUT}/complex.input  ${OUT}/cone.input       ${OUT}/conformal.input \
@@ -669,12 +670,13 @@ DOCFILES= \
   ${DOC}/c06fqf.input.dvi      ${DOC}/c06frf.input.dvi     \
   ${DOC}/c06fuf.input.dvi      ${DOC}/c06gbf.input.dvi     \
   ${DOC}/c06gcf.input.dvi      ${DOC}/c06gqf.input.dvi     \
-  ${DOC}/c06gsf.input.dvi      ${DOC}/calculus2.input.dvi  \
+  ${DOC}/c06gsf.input.dvi      ${DOC}/calcprob.input.dvi   \
+  ${DOC}/calculus2.input.dvi  \
   ${DOC}/calculus.input.dvi    ${DOC}/cardinal.input.dvi   \
   ${DOC}/card.input.dvi        ${DOC}/carten.input.dvi     \
   ${DOC}/cclass.input.dvi      ${DOC}/cdraw.input.dvi      \
   ${DOC}/char.input.dvi        ${DOC}/ch.input.dvi         \
-  ${DOC}/chtheorem.input.dvi \
+  ${DOC}/chtheorem.input.dvi   ${DOC}/classtalk.input.dvi  \
   ${DOC}/clifford.input.dvi    ${DOC}/clif.input.dvi       \
   ${DOC}/coercels.input.dvi    ${DOC}/collect.input.dvi    \
   ${DOC}/color.input.dvi       ${DOC}/complex.input.dvi    \
diff --git a/src/input/calcprob.input.pamphlet b/src/input/calcprob.input.pamphlet
new file mode 100644
index 0000000..f41808d
--- /dev/null
+++ b/src/input/calcprob.input.pamphlet
@@ -0,0 +1,124 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/input calcprob.input}
+\author{Timothy Daly}
+\maketitle
+\begin{abstract}
+Cover a range of calculus problems
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+<<*>>=
+)spool calcprob.output
+)set message test on
+)set message auto off
+)clear all
+ 
+--S 1 
+solve(3*x-(x-7)=4*x-5,x)
+--R
+--R   (1)  [x= 6]
+--R                              Type: List Equation Fraction Polynomial Integer
+--E 1
+
+--S 2
+solve(4*x-3*y=9,y)::List Equation Polynomial Fraction Integer
+--R
+--R            4
+--R   (2)  [y= - x - 3]
+--R            3
+--R                              Type: List Equation Polynomial Fraction Integer
+--E 2
+
+--S 3
+solve(A*x+B*y=C,y)
+--R
+--R            - A x + C
+--R   (3)  [y= ---------]
+--R                B
+--R                              Type: List Equation Fraction Polynomial Integer
+--E 3
+
+--S 4
+m:=3*x-4*(x-(2/3)*y)=(4/5)*x-(7*y+3)
+--R
+--R        8               4
+--R   (4)  - y - x= - 7y + - x - 3
+--R        3               5
+--R                                   Type: Equation Polynomial Fraction Integer
+--E 4
+
+--S 5
+n:=solve(m*15,y)
+--R
+--R            27x - 45
+--R   (5)  [y= --------]
+--R               145
+--R                              Type: List Equation Fraction Polynomial Integer
+--E 5
+
+--S 6
+p:=n.1*145-27*x
+--R
+--R   (6)  145y - 27x= - 45
+--R                                   Type: Equation Fraction Polynomial Integer
+--E 6
+
+--S 7
+(x1,y1):=(-3,-8)
+--R
+--R   (7)  - 8
+--R                                                                Type: Integer
+--E 7
+
+--S 8
+(x2,y2):=(-6,2)
+--R
+--R   (8)  2
+--R                                                        Type: PositiveInteger
+--E 8
+
+--S 9
+m:=(y2-y1)/(x2-x1)
+--R
+--R          10
+--R   (9)  - --
+--R           3
+--R                                                       Type: Fraction Integer
+--E 9
+
+--S 10
+solve(y1=m*x1+b,b)
+--R
+--R   (10)  [b= - 18]
+--R                              Type: List Equation Fraction Polynomial Integer
+--E 10
+
+--S 11
+b:=-18
+--R
+--R   (11)  - 18
+--R                                                                Type: Integer
+--E 11
+
+--S 12
+y=m*x+b
+--R
+--R              10
+--R   (12)  y= - -- x - 18
+--R               3
+--R                                   Type: Equation Polynomial Fraction Integer
+--E 12
+)spool 
+)lisp (bye)
+ 
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}
+
+ 
diff --git a/src/input/classtalk.input.pamphlet b/src/input/classtalk.input.pamphlet
new file mode 100644
index 0000000..7f89df1
--- /dev/null
+++ b/src/input/classtalk.input.pamphlet
@@ -0,0 +1,733 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/input classtalk.input}
+\author{Timothy Daly}
+\maketitle
+\begin{abstract}
+These are examples from the talk ``Axiom in an Educational Setting''.
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+<<*>>=
+)spool classtalk.output
+)set message test on
+)set message auto off
+)set break resume
+)clear all
+
+@
+\section{Numbers}
+<<*>>=
+--S 1
+1
+--R
+--R   (1)  1
+--R                                                        Type: PositiveInteger
+--E 1
+
+--S 2
+1/2
+--R
+--R        1
+--R   (2)  -
+--R        2
+--R                                                       Type: Fraction Integer
+--E 2
+
+--S 3
+3+4*%i
+--R
+--R   (3)  3 + 4%i
+--R                                                        Type: Complex Integer
+--E 3
+
+--S 4
+3.4
+--R
+--R   (4)  3.4
+--R                                                                  Type: Float
+--E 4
+
+--S 5
+X::ROMAN
+--R
+--R   (5)  X
+--R                                                           Type: RomanNumeral
+--E 5
+
+--S 6
+binary(5)
+--R
+--R   (6)  101
+--R                                                        Type: BinaryExpansion
+--E 6
+
+--S 7
+factor(60)
+--R
+--R         2
+--R   (7)  2 3 5
+--R                                                       Type: Factored Integer
+--E 7
+
+--S 8
+q:=(y-1)*x*(z+5)
+--R
+--R   (8)  (x y - x)z + 5x y - 5x
+--R                                                     Type: Polynomial Integer
+--E 8
+
+--S 9
+factor q
+--R
+--R   (9)  x(y - 1)(z + 5)
+--R                                            Type: Factored Polynomial Integer
+--E 9
+
+--S 10
+eval(q,[x=5,y=6,z=7])
+--R
+--R   (10)  300
+--R                                                     Type: Polynomial Integer
+--E 10
+
+--S 11
+eval(q,[x=5,y=6])
+--R
+--R   (11)  25z + 125
+--R                                                     Type: Polynomial Integer
+--E 11
+
+@
+\section{Trigonometry}
+<<*>>=
+--S 12
+b:=[log a, exp a, asin a, acos a, atan a, acot a, sinh a]
+--R
+--R                   a
+--R   (12)  [log(a),%e ,asin(a),acos(a),atan(a),acot(a),sinh(a)]
+--R                                                Type: List Expression Integer
+--E 12
+
+--S 13
+[exp b.1, log b.2, sin b.3, cos b.4, tan b.5, cot b.6, asinh b.7]
+--R
+--R   (13)  [a,a,a,a,a,a,a]
+--R                                                Type: List Expression Integer
+--E 13
+
+--S 14
+a:=.7
+--R
+--R   (14)  0.7
+--R                                                                  Type: Float
+--E 14
+
+--S 15
+b:=[log a, exp a, asin a, acos a, atan a, acot a, sinh a]
+--R
+--R   (15)
+--R   [- 0.3566749439 3873237891, 2.0137527074 704765216, 0.7753974966 1075306374,
+--R    0.7953988301 8414355549, 0.6107259643 8920861654, 0.9600703624 0568800269,
+--R    0.7585837018 3953350346]
+--R                                                             Type: List Float
+--E 15
+
+--S 16
+[exp b.1, log b.2, sin b.3, cos b.4, tan b.5, cot b.6, asinh b.7]
+--R
+--R   (16)  [0.7,0.7,0.7,0.7,0.7,0.7,0.7]
+--R                                                             Type: List Float
+--E 16
+
+--S 17
+simplify(sin(x)**2+cos(x)**2)
+--R
+--R   (17)  1
+--R                                                     Type: Expression Integer
+--E 17
+
+@
+\section{Polynomial Manipulations}
+<<*>>=
+)clear all
+--S 18
+eq1:=A*x^2 + B*x*y + C*y^2 + D*x + E*y + F
+--R
+--R           2                   2
+--R   (1)  C y  + (B x + E)y + A x  + D x + F
+--R                                                     Type: Polynomial Integer
+--E 18
+
+--S 19
+rotatex:=x'*cos(t)-y'*sin(t)
+--R
+--R   (2)  - y' sin(t) + x' cos(t)
+--R                                                     Type: Expression Integer
+--E 19
+
+--S 20
+rotatey:=x'*sin(t)+y'*cos(t)
+--R
+--R   (3)  x' sin(t) + y' cos(t)
+--R                                                     Type: Expression Integer
+--E 20
+
+--S 21
+eval(eq1,[x=rotatex, y=rotatey])
+--R
+--R   (4)
+--R          2                 2       2
+--R     (A y'  - B x' y' + C x' )sin(t)
+--R   + 
+--R             2                        2
+--R     ((- B y'  + (2C - 2A)x' y' + B x' )cos(t) - D y' + E x')sin(t)
+--R   + 
+--R          2                 2       2
+--R     (C y'  + B x' y' + A x' )cos(t)  + (E y' + D x')cos(t) + F
+--R                                                     Type: Expression Integer
+--E 21
+
+@
+\section{Polynomials over Simple Algebraic Extension Fields}
+<<*>>=
+)clear all
+--S 22
+a:=rootOf(a^2+a+1)
+--R
+--R   (1)  a
+--R                                                        Type: AlgebraicNumber
+--E 22
+
+--S 23
+factor(x^2+3)
+--R
+--R         2
+--R   (2)  x  + 3
+--R                                            Type: Factored Polynomial Integer
+--E 23
+
+--S 24
+factor(x^2+3,[a])
+--R
+--R   (3)  (x - 2a - 1)(x + 2a + 1)
+--R                                    Type: Factored Polynomial AlgebraicNumber
+--E 24
+
+--S 25
+definingPolynomial(a)
+--R
+--R         2
+--R   (4)  a  + a + 1
+--R                                                        Type: AlgebraicNumber
+--E 25
+
+--S 26
+zerosOf(b^2+b+1,b)
+--R
+--R          +---+        +---+
+--R         \|- 3  - 1 - \|- 3  - 1
+--R   (5)  [----------,------------]
+--R              2           2
+--R                                                Type: List Expression Integer
+--E 26
+
+@
+\section{Derivatives}
+<<*>>=
+--S 27
+differentiate(sin(x),x)
+--R
+--R   (6)  cos(x)
+--R                                                     Type: Expression Integer
+--E 27
+
+--S 28
+differentiate(sin(x),x,2)
+--R
+--R   (7)  - sin(x)
+--R                                                     Type: Expression Integer
+--E 28
+
+--S 29
+differentiate(cos(z)/(x^2+y^3),[x,y,z],[1,2,3])
+--R
+--R                    4      3
+--R            (- 84x y  + 24x y)sin(z)
+--R   (8)  --------------------------------
+--R         12     2 9     4 6     6 3    8
+--R        y   + 4x y  + 6x y  + 4x y  + x
+--R                                                     Type: Expression Integer
+--E 29
+
+--S 30
+y:=operator y
+--R
+--R   (9)  y
+--R                                                          Type: BasicOperator
+--E 30
+
+--S 31
+deqx:=D(y(x),x,2)+D(y(x),x)+y(x)
+--R 
+--R
+--R          ,,       ,
+--R   (10)  y  (x) + y (x) + y(x)
+--R
+--R                                                     Type: Expression Integer
+--E 31
+
+--S 32
+solve(deqx,y,x)
+--R
+--R                                              x     x
+--R                                      +-+   - -   - -      +-+
+--R                                    x\|3      2     2    x\|3
+--R   (11)  [particular= 0,basis= [cos(-----)%e   ,%e   sin(-----)]]
+--R                                      2                    2
+--RType: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
+--E 32
+
+@
+\section{Limits}
+<<*>>=
+)clear all
+--S 33
+limit((x^2-3*x+2)/(x^2-1),x=1)
+--R
+--R          1
+--R   (1)  - -
+--R          2
+--R               Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
+--E 33
+
+--S 34
+limit(x*log(x),x=0)
+--R
+--R   (2)  [leftHandLimit= "failed",rightHandLimit= 0]
+--RType: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
+--E 34
+
+--S 35
+limit(sinh(a*x)/tan(b*x),x=0)
+--R
+--R        a
+--R   (3)  -
+--R        b
+--R                        Type: Union(OrderedCompletion Expression Integer,...)
+--E 35
+
+--S 36
+limit(sqrt(3*x^2+1)/(5*x),x=%plusInfinity)
+--R
+--R         +-+
+--R        \|3
+--R   (4)  ----
+--R          5
+--R                        Type: Union(OrderedCompletion Expression Integer,...)
+--E 36
+
+--S 37
+complexLimit((2+z)/(1-z),z=%infinity)
+--R
+--R   (5)  - 1
+--R                         Type: OnePointCompletion Fraction Polynomial Integer
+--E 37
+
+@
+\section{Indefinite Integration}
+<<*>>=
+)clear all
+--S 38
+integrate(1+sqrt(x)/x,x)
+--R
+--R          +-+
+--R   (1)  2\|x  + x
+--R                                          Type: Union(Expression Integer,...)
+--E 38
+
+--S 39
+integrate(sin(x)/x,x)
+--R
+--R   (2)  Si(x)
+--R                                          Type: Union(Expression Integer,...)
+--E 39
+
+@
+This used to give the answer:
+$$\frac{\sqrt{x}\sqrt{\pi} erf(x\sqrt{a})}{2a}$$
+<<*>>=
+--S 40
+integrate(exp(-a*x^2),x)
+--R
+--R           x       2
+--R         ++    - %Q a
+--R   (3)   |   %e      d%Q
+--R        ++
+--R                                          Type: Union(Expression Integer,...)
+--E 40
+
+--S 41
+integrate(sin(x)/x^2,x)
+--R
+--R           x
+--R         ++  sin(%Q)
+--R   (4)   |   ------- d%Q
+--R        ++       2
+--R               %Q
+--R                                          Type: Union(Expression Integer,...)
+--E 41
+
+@
+\section{Definite Integration}
+<<*>>=
+)clear all
+--S 42
+integrate(exp(-x)/sqrt(x),x=0..%plusInfinity)
+--R
+--R         _ 1
+--R   (1)  | (-)
+--R           2
+--R                    Type: Union(f1: OrderedCompletion Expression Integer,...)
+--E 42
+
+--S 43
+integrate(1/x^2,x=-1..1)
+--R 
+--R 
+--RDaly Bug
+--R   >> Error detected within library code:
+--R   integrate: pole in path of integration
+--R
+--R   Continuing to read the file...
+--R
+--E 43
+
+)clear all
+
+@
+This used to return
+$$\frac{4\log{(4)}-8\log{(2)}+3\pi}{12}$$
+<<*>>=
+--S 44
+integrate(sin(x)^3/(sin(x)^3+cos(x)^3),x=0..%pi/2,"noPole")
+--R
+--R        2log(16) - 4log(4) + 3%pi
+--R   (1)  -------------------------
+--R                    12
+--R                    Type: Union(f1: OrderedCompletion Expression Integer,...)
+--E 44
+
+--S 45
+integrate(exp(-x^2)*log(x)^2,x=0..%plusInfinity)
+--R
+--R         _ 1             1     _ 1         1 2
+--R        | (-)polygamma(1,-) + | (-)digamma(-)
+--R           2             2       2         2
+--R   (2)  --------------------------------------
+--R                           8
+--R                    Type: Union(f1: OrderedCompletion Expression Integer,...)
+--E 45
+
+@
+\section{Laplace Transformations}
+<<*>>=
+)clear all
+
+--S 46
+laplace(sin(a*t)*cosh(a*t)-cos(a*t)*sinh(a*t),t,s)
+--R
+--R             3
+--R           4a
+--R   (1)  --------
+--R         4     4
+--R        s  + 4a
+--R                                                     Type: Expression Integer
+--E 46
+
+--S 47
+laplace(2/t * (1-cos(a*t)),t,s)
+--R
+--R             2    2
+--R   (2)  log(s  + a ) - 2log(s)
+--R                                                     Type: Expression Integer
+--E 47
+
+--S 48
+laplace((exp(a*t)-exp(b*t))/t,t,s)
+--R
+--R   (3)  - log(s - a) + log(s - b)
+--R                                                     Type: Expression Integer
+--E 48
+
+--S 49
+laplace(exp(a*t+b)*Ei(c*t),t,s)
+--R
+--R          b    s + c - a
+--R        %e log(---------)
+--R                   c
+--R   (4)  -----------------
+--R              s - a
+--R                                                     Type: Expression Integer
+--E 49
+
+@
+\section{Clifford Algebras}
+{\tt CliffordAlgebra(n,K,Q)} defines a vector space of dimension $2^n$
+over $K$, given a quadratic form $Q$ on $K^n$ (e.q. quaternions).
+<<*>>=
+)clear all
+--S 50
+K:=Fraction Polynomial Integer
+--R
+--R   (1)  Fraction Polynomial Integer
+--R                                                                 Type: Domain
+--E 50
+
+--S 51
+qf:QFORM(2,K):=quadraticForm matrix([[-1,0],[0,-1]])$(SQMATRIX(2,K))
+--R
+--R        +- 1   0 +
+--R   (2)  |        |
+--R        + 0   - 1+
+--R                           Type: QuadraticForm(2,Fraction Polynomial Integer)
+--E 51
+
+--S 52
+i:=e(1)$CLIF(2,K,qf)
+--R
+--R   (3)  e
+--R         1
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 52
+
+--S 53
+j:=e(2)$CLIF(2,K,qf)
+--R
+--R   (4)  e
+--R         2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 53
+
+--S 54
+k:=i*j
+--R
+--R   (5)  e e
+--R         1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 54
+
+--S 55
+x:=a+b*i+c*j+d*k
+--R
+--R   (6)  a + b e  + c e  + d e e
+--R               1      2      1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 55
+
+--S 56
+y:=m+f*i+g*j+h*k
+--R
+--R   (7)  m + f e  + g e  + h e e
+--R               1      2      1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 56
+
+--S 57
+x+y
+--R
+--R   (8)  m + a + (f + b)e  + (g + c)e  + (h + d)e e
+--R                        1           2           1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 57
+
+--S 58
+x*y
+--R
+--R   (9)
+--R     a m - d h - c g - b f + (b m + c h - d g + a f)e
+--R                                                     1
+--R   + 
+--R     (c m - b h + a g + d f)e  + (d m + a h + b g - c f)e e
+--R                             2                           1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 58
+
+@
+\section{Taylor Series}
+<<*>>=
+)clear all
+--S 59
+taylor(sin(x),x=0)
+--R
+--R            1  3    1   5     1   7      1    9      11
+--R   (1)  x - - x  + --- x  - ---- x  + ------ x  + O(x  )
+--R            6      120      5040      362880
+--R                         Type: UnivariateTaylorSeries(Expression Integer,x,0)
+--E 59
+
+@
+\section{Laurent Series}
+<<*>>=
+--S 60
+laurent(x/log(x),x=1)
+--R
+--R   (2)
+--R            - 1   3    5            1        2    11        3    11         4
+--R     (x - 1)    + - + -- (x - 1) - -- (x - 1)  + --- (x - 1)  - ---- (x - 1)
+--R                  2   12           24            720            1440
+--R   + 
+--R      271         5    13         6     7297         7     425         8
+--R     ----- (x - 1)  - ---- (x - 1)  + ------- (x - 1)  - ------ (x - 1)
+--R     60480            4480            3628800            290304
+--R   + 
+--R       530113         9            10
+--R     --------- (x - 1)  + O((x - 1)  )
+--R     479001600
+--R                        Type: UnivariateLaurentSeries(Expression Integer,x,1)
+--E 60
+
+@
+\section{Puiseux Series}
+<<*>>=
+--S 61
+puiseux(sqrt(sec(x)),x=3*%pi/2)
+--R 
+--R
+--R                    1                3                 7
+--R                  - -                -                 -
+--R             3%pi   2    1      3%pi 2    1       3%pi 2          3%pi 5
+--R   (3)  (x - ----)    + -- (x - ----)  + --- (x - ----)  + O((x - ----) )
+--R               2        12        2      160        2               2
+--R                 Type: UnivariatePuiseuxSeries(Expression Integer,x,(3*pi)/2)
+--E 61
+
+@
+\section{General Series}
+<<*>>=
+--S 62
+series(x^x,x=0)
+--R
+--R   (4)
+--R                         2            3            4            5
+--R                   log(x)   2   log(x)   3   log(x)   4   log(x)   5
+--R     1 + log(x)x + ------- x  + ------- x  + ------- x  + ------- x
+--R                      2            6            24          120
+--R   + 
+--R           6            7            8            9            10
+--R     log(x)   6   log(x)   7   log(x)   8   log(x)   9   log(x)    10      11
+--R     ------- x  + ------- x  + ------- x  + ------- x  + -------- x   + O(x  )
+--R       720          5040        40320        362880       3628800
+--R                   Type: GeneralUnivariatePowerSeries(Expression Integer,x,0)
+--E 62
+
+@
+\section{Matrices}
+<<*>>=
+)clear all
+--S 63
+m:=matrix [[1,2],[3,4]]
+--R
+--R        +1  2+
+--R   (1)  |    |
+--R        +3  4+
+--R                                                         Type: Matrix Integer
+--E 63
+
+--S 64
+4*m*(-5)
+--R
+--R        +- 20  - 40+
+--R   (2)  |          |
+--R        +- 60  - 80+
+--R                                                         Type: Matrix Integer
+--E 64
+
+--S 65
+n:=matrix [[1,0,-2],[-3,5,1]]
+--R
+--R        + 1   0  - 2+
+--R   (3)  |           |
+--R        +- 3  5   1 +
+--R                                                         Type: Matrix Integer
+--E 65
+
+--S 66
+m*n
+--R
+--R        +- 5  10   0 +
+--R   (4)  |            |
+--R        +- 9  20  - 2+
+--R                                                         Type: Matrix Integer
+--E 66
+
+--S 67
+hilb:=matrix([[1/(i+j) for i in 1..3] for j in 1..3])
+--R
+--R        +1  1  1+
+--R        |-  -  -|
+--R        |2  3  4|
+--R        |       |
+--R        |1  1  1|
+--R   (5)  |-  -  -|
+--R        |3  4  5|
+--R        |       |
+--R        |1  1  1|
+--R        |-  -  -|
+--R        +4  5  6+
+--R                                                Type: Matrix Fraction Integer
+--E 67
+
+--S 68
+inverse(hilb)
+--R
+--R        + 72    - 240   180 +
+--R        |                   |
+--R   (6)  |- 240   900   - 720|
+--R        |                   |
+--R        + 180   - 720   600 +
+--R                                     Type: Union(Matrix Fraction Integer,...)
+--E 68
+
+@
+\section{Systems of Equations}
+<<*>>=
+)clear all
+--S 69
+solve([x+y+z=8,3*x-2*y+z=0,x+2*y+2*z=17],[x,y,z])
+--R
+--R   (1)  [[x= - 1,y= 2,z= 7]]
+--R                         Type: List List Equation Fraction Polynomial Integer
+--E 69
+
+--S 70
+solve([x+2*y+3*z=2,2*x+3*y+4*z=2,3*x+4*y+5*z=2],[x,y,z])
+--R
+--R   (2)  [[x= %W - 2,y= - 2%W + 2,z= %W]]
+--R                         Type: List List Equation Fraction Polynomial Integer
+--E 70
+
+--S 71
+solve([[1,1,1],[3,-2,1],[1,2,2]],[8,0,17])
+--R
+--R   (3)  [particular= [- 1,2,7],basis= [[0,0,0]]]
+--RType: Record(particular: Union(Vector Fraction Integer,"failed"),basis: List Vector Fraction Integer)
+--E 71
+
+--S 72
+solve([[1,2,3],[2,3,4],[3,4,5]],[2,2,2])
+--R
+--R   (4)  [particular= [- 2,2,0],basis= [[1,- 2,1]]]
+--RType: Record(particular: Union(Vector Fraction Integer,"failed"),basis: List Vector Fraction Integer)
+--E 72
+)spool 
+)lisp (bye)
+ 
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}
diff --git a/src/input/intbypart.input.pamphlet b/src/input/intbypart.input.pamphlet
index 72a04e5..0b26c61 100644
--- a/src/input/intbypart.input.pamphlet
+++ b/src/input/intbypart.input.pamphlet
@@ -91,6 +91,7 @@ integrate(x*exp(x),x)
 --R                                          Type: Union(Expression Integer,...)
 --E 2
 @
+
 \section{integrate $e^x cos(x) dx$}
 This integral will require the substituion by parts rule to be applied twice.
 
@@ -165,8 +166,8 @@ integrate(x^3*exp(x^2),x)
 --R              2
 --R                                          Type: Union(Expression Integer,...)
 --E 4
-@
 
+@
 \section{integrate $ln(x^2+2)dx$}
 To integrate
 $$\int{ln(x^2+2)dx}$$
@@ -194,49 +195,123 @@ integrate(log(x^2+2),x)
 --E 5
 @
 
-\section{integrate $ln(x) dx$}
+\section{integrate $x\ sin(x) dx$}
 To integrate
-$$\int{ln(x) dx}$$
+$$\int{x\ sin(x)\ dx}$$
 Let
-$$u=ln(x)$$
-$$dv=dx$$
-$$du=\frac{1}{x}dx$$
-$$v=x$$
+$$u=x$$
+$$dv=sin(x)\ dx$$
+$$du = dx$$
+$$v = -cos(x)$$
 so
-$$\int{ln(x)\ dx}$$
-$$=x\ ln(x)=\int{1\ dx}$$
-$$=x\ ln(x) - x + C$$
-$$=x(ln(x)-1)+C$$
+$$\int{x\ sin(x)\ dx}$$
+$$= -x\ cos(x) - \int{-cos(x)\ dx}$$
+$$= -x\ cos(x)+sin(x)+C$$
 <<*>>=
 --S 6
-integrate(log(x),x)
+integrate(x*sin(x),x)
 --R
---R   (6)  x log(x) - x
+--R   (6)  sin(x) - x cos(x)
 --R                                          Type: Union(Expression Integer,...)
 --E 6
 @
 
-\section{integrate $x\ sin(x) dx$}
+\section{integrate $x\ cos(x) dx$}
 To integrate
-$$\int{x\ sin(x)\ dx}$$
+$$\int{x\ cos(x)\ dx}$$
 Let
 $$u=x$$
-$$dv=sin(x)\ dx$$
+$$dv=cos(x)\ dx$$
 $$du = dx$$
-$$v = -cos(x)$$
+$$v = sin(x)$$
 so
-$$\int{x\ sin(x)\ dx}$$
-$$= -x\ cos(x) - \int{-cos(x)\ dx}$$
-$$= -x\ cos(x)+sin(x)+C$$
+$$\int{x\ cos(x)\ dx}$$
+$$= x\ sin(x) - \int{sin(x)\ dx}$$
+$$= x\ sin(x)+cos(x)+C$$
 <<*>>=
 --S 7
-integrate(x*sin(x),x)
+integrate(x*cos(x),x)
+--R 
 --R
---R   (7)  sin(x) - x cos(x)
+--R   (7)  x sin(x) + cos(x)
 --R                                          Type: Union(Expression Integer,...)
 --E 7
 @
 
+\section{integrate $x^2\ sin(x) dx$}
+To integrate
+$$\int{x^2\ sin(x)\ dx}$$
+Let
+$$u=x^2$$
+$$dv=sin(x)\ dx$$
+$$du = 2x\ dx$$
+$$v = -cos(x)$$
+so
+$$\int{x^2\ sin(x)\ dx}$$
+$$= -x^2\ cos(x) - \int{-2x\ cos(x)\ dx}$$
+$$= -x^2\ cos(x)+2\int{x\ cos(x)\ dx}$$
+$$=-x^2\ cos(x)+2(x\ sin(x)+cos(x))+C$$
+<<*>>=
+--S 8
+integrate(x^2*cos(x),x)
+--R 
+--R
+--R          2
+--R   (8)  (x  - 2)sin(x) + 2x cos(x)
+--R                                          Type: Union(Expression Integer,...)
+--E 8
+@
+
+\section{integrate $sin(x)\ cos(x)\ dx$}
+To integrate
+$$\int{sin(x)\ cos(x)\ dx}$$
+Let
+$$u=sin(x)$$
+$$dv=cos(x)\ dx$$
+$$du=cos(x)\ dx$$
+$$v=sin(x)$$
+so
+$$\int{sin(x)cos(x)dx}
+=sin(x)sin(x) - \int{sin(x)cos(x)dx}$$
+but the integral appears on both sides of the equation so
+$$2\int{sin(x)cos(x)dx}=sin^2(x)$$
+so
+$$\int{sin(x)cos(x)dx}=\frac{1}{2}sin^2(x)+C$$
+<<*>>=
+--S 9
+integrate(sin(x)*cos(x),x)
+--R 
+--R
+--R                2
+--R          cos(x)
+--R   (9)  - -------
+--R             2
+--R                                          Type: Union(Expression Integer,...)
+--E 9
+@
+
+\section{integrate $ln(x) dx$}
+To integrate
+$$\int{ln(x) dx}$$
+Let
+$$u=ln(x)$$
+$$dv=dx$$
+$$du=\frac{1}{x}dx$$
+$$v=x$$
+so
+$$\int{ln(x)\ dx}$$
+$$=x\ ln(x)=\int{1\ dx}$$
+$$=x\ ln(x) - x + C$$
+$$=x(ln(x)-1)+C$$
+<<*>>=
+--S 10
+integrate(log(x),x)
+--R
+--R   (10)  x log(x) - x
+--R                                          Type: Union(Expression Integer,...)
+--E 10
+@
+
 \section{integrate $x^2\ ln(x)\ dx$}
 To integrate
 $$\int{x^2\ ln(x)\ dx}$$
@@ -251,15 +326,38 @@ $$\frac{x^3}{3} ln(x) - \int{\frac{x^3}{3}\frac{dx}{x}}$$
 $$\frac{x^3}{3} ln(x)-\frac{1}{3}\int{x^2\ dx}$$
 $$\frac{x^3}{3}ln(x)-\frac{1}{9}x^3 + C$$
 <<*>>=
---S 8
+--S 11
 integrate(x^2*log(x),x)
 --R
---R          3          3
---R        3x log(x) - x
---R   (8)  --------------
---R               9
+--R           3          3
+--R         3x log(x) - x
+--R   (11)  --------------
+--R                9
 --R                                          Type: Union(Expression Integer,...)
---E 8
+--E 11
+@
+
+\section{integrate $x^2\ e^x\ dx$}
+To integrate
+$$\int{x^2\ e^x\ dx}$$
+Let
+$$u=x^2$$
+$$dv=e^x\ dx$$
+$$du = 2x\ dx$$
+$$v = e^x$$
+so
+$$\int{x^2\ e^x\ dx}$$
+$$x^2\ e^x - 2x\ e^x - \int{e^x\ 2dx}$$
+$$x^2\ e^x - 2x\ e^x+2\ e^x+C$$
+<<*>>=
+--S 12
+integrate(x^2*exp(x),x)
+--R 
+--R
+--R           2            x
+--R   (12)  (x  - 2x + 2)%e
+--R                                          Type: Union(Expression Integer,...)
+--E 12
 @
 
 \section{integrate $sin^{-1}(x)\ dx$}
@@ -278,15 +376,128 @@ $$=x\ sin^{-1}(x) + \frac{1}{2}(2(1-x^2)^{1/2})+C$$
 $$=x\ sin^{-1}(x)+(1-x^2)^{1/2}+C$$
 $$=x\ sin^{-1}(x)+\sqrt{1-x^2}+C$$
 <<*>>=
---S 9
-integrate(1/sin(x),x)
+--S 13
+integrate(asin(x),x)
+--R 
 --R
---R              sin(x)
---R   (9)  log(----------)
---R            cos(x) + 1
+--R                     +--------+
+--R                     |   2           +--------+
+--R                  2x\|- x  + 1       |   2
+--R         - x atan(-------------) + 2\|- x  + 1
+--R                       2
+--R                     2x  - 1
+--R   (13)  --------------------------------------
+--R                            2
 --R                                          Type: Union(Expression Integer,...)
---E 9
-)spool 
+--E 13
+@
+
+\section{integrate $\tan^{-1}(x)\ dx$}
+$$\int{\tan^{-1}(x)\ dx}$$
+Let
+$$u=tan^{-1}$$
+$$dv=dx$$
+$$du=\frac{1}{1+x^2}\ dx$$
+$$v=x$$
+so
+$$\int{\tan^{-1}(x)\ dx}$$
+$$=x\ \tan^{-1}-\int{\frac{x}{1+x^2}\ dx}$$
+$$=x\ tan^{-1}(x)-\frac{1}{2}\int{\frac{2x}{1+x^2}\ dx}$$
+$$=x\ tan^{-1}(x)-\frac{1}{2}ln(1+x^2)+C$$
+<<*>>=
+--S 14
+integrate(atan(x),x)
+--R 
+--R
+--R                2                 2x
+--R         - log(x  + 1) - x atan(------)
+--R                                 2
+--R                                x  - 1
+--R   (14)  ------------------------------
+--R                        2
+--R                                          Type: Union(Expression Integer,...)
+--E 14
+@
+
+\section{integrate $\sec^3(x)\ dx$}
+$$\int{\sec^3(x)\ dx}$$
+Let
+$$u=sec(x)$$
+$$dv=sec^2(x)\ dx$$
+$$du=sec(x)tan(x)\ dx$$
+$$v=tan(x)$$
+so
+$$\int{\sec^3(x)\ dx}$$
+$$=sec(x)tan(x)-\int{sec(x)tan^2(x)\ dx}$$
+$$=sec(x)tan(x)-\int{sec(x)(sec^2(x)-1)\ dx}$$
+$$=sec(x)tan(x)-\int{sec^3(x)\ dx}+\int{sec(x)\ dx}$$
+$$=sec(x)tan(x)-\int{sec^3(x)\ dx}+ln(\vert sec(x)+\tan(x)\vert )$$
+but
+$$=2\int{sec^3(x)\ dx}=sec(x)tan(x)+ln(\vert sec(x)+\tan(x)\vert )$$
+so
+$$\int{sec^3(x)\ dx}=
+\frac{1}{2}(sec(x)tan(x)+ln(\vert sec(x)+\tan(x)\vert ))+C$$
+<<*>>=
+--S 15
+integrate(sec(x)^3,x)
+--R 
+--R
+--R   (15)
+--R         2    sin(x) + cos(x) + 1          2    sin(x) - cos(x) - 1
+--R   cos(x) log(-------------------) - cos(x) log(-------------------) + sin(x)
+--R                   cos(x) + 1                        cos(x) + 1
+--R   --------------------------------------------------------------------------
+--R                                           2
+--R                                    2cos(x)
+--R                                          Type: Union(Expression Integer,...)
+--E 15
+@
+
+\section{integrate $x^3\ e^{2x}$}
+$$\int{x^3\ e^{2x}\ dx}$$
+Let
+$$u=x^3$$
+$$dv=e^{2x}\ dx$$
+$$du=3x^2\ dx$$
+$$v=\frac{1}{2}e^{2x}$$
+$$\int{x^3\ e^{2x}\ dx}$$
+$$=\frac{1}{2}x^3\ e^{2x} - \frac{3}{2}\int{x^2\ e^{2x}\ dx}$$
+
+To solve
+$$\frac{3}{2}\int{x^2\ e^{2x}\ dx}$$
+Let
+$$u=x^2$$
+$$dv=e^{2x}\ dx$$
+$$du=2x\ dx$$
+$$v=\frac{1}{2}e^{2x}$$
+so after substitution the new result is
+$$=\frac{1}{2}x^3\ e^{2x} - 
+\frac{3}{2}\left(\frac{1}{2}x^2\ e^{2x}-\int{xe^{2x}\ dx}\right)$$
+$$=\frac{1}{2}x^3\ e^{2x} - \frac{3}{4}x^2e^{2x}+
+\frac{3}{2}\int{xe^{2x}\ dx}$$
+Let
+$$u=x$$
+$$dv=e^{2x}\ dx$$
+$$du=dx$$
+$$v=\frac{1}{2}e^{2x}$$
+so
+$$\int{x^3\ e^{2x}\ dx}$$
+$$=\frac{1}{2}x^3\ e^{2x}-\frac{3}{4}x^2\ e^{2x}+
+\frac{3}{2}\left(\frac{1}{2}xe^{2x}-\frac{1}{2}\int{e^{2x}\ dx}\right)$$
+$$=\frac{1}{2}x^3\ e^{2x}-\frac{3}{4}x^2\ e^{2x}+
+\frac{3}{4}xe^{2x}-\frac{3}{8}e^{2x}+C$$
+<<*>>=
+--S 16
+integrate(x^3*exp(2*x),x)
+--R 
+--R
+--R            3     2            2x
+--R         (4x  - 6x  + 6x - 3)%e
+--R   (16)  ------------------------
+--R                     8
+--R                                          Type: Union(Expression Integer,...)
+--E 16
+)spool
 )lisp (bye)
 @
 
diff --git a/src/input/limit.input.pamphlet b/src/input/limit.input.pamphlet
index c210c87..ec80f68 100644
--- a/src/input/limit.input.pamphlet
+++ b/src/input/limit.input.pamphlet
@@ -5,24 +5,276 @@
 \author{Timothy Daly}
 \maketitle
 \begin{abstract}
+Exercise the limit function.
 \end{abstract}
 \eject
 \tableofcontents
 \eject
-\section{License}
-<<license>>=
---Copyright The Numerical Algorithms Group Limited 1991.
-@
+\section{Limit of a Function}
+If $f$ is a function, then 
+$$\lim_{x -> a}{f(x) = A}$$
+if the value of $f(x)$ gets arbitrarily close to $A$ as $x$ gets 
+arbitrarily close to $a$. For example, 
+$$\lim_{x->3}{x^2}=9$$
+since $x^2$ gets arbitrarily close to 9 as $x$ approaches 3.
+
+By definition, the limit 
+$$\lim_{x -> a}{f(x) = A}$$ if and only if, for any chosen positive
+number $\epsilon$, however small, there exists a positive number 
+$\delta$ such that
+$$0 < \vert x-a \vert < \delta {\tt\ implies\ }
+\vert f(x)-A \vert < \epsilon$$
+Note that $f(x)$ does not need to be defined at $a$.
+
 <<*>>=
 )spool limit.output
 )set message test on
 )set message auto off
 )clear all
  
+--S 1 of 15
+limit((x^2-4)/(x-2),x=2)
+--R 
+--R
+--R   (1)  4
+--R               Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
+--E 1
+@
+\section{Right and Left Limits}
+The limit
+$$\lim_{x -> a^-}{f(x) = A}$$
+given that $f$ is defined in the interval $(c,a)$ and $f(x)$
+approaches $A$ as $x$ approaches $a$ through the values less than
+$a$, that is, as $x$ approaches $a$ from the left. 
+
+Similarly
+$$\lim_{x -> a^+}{f(x) = A}$$
+means that $f$ is defined in some interval $(a,d)$ and $f(x)$
+approaches $A$ as $x$ approaches $a$ from the right. 
+
+If $f$ is defined in an interval to the left of $a$ and in an interval
+to the right of $a$ then the statement
+$$\lim_{x -> a}{f(x) = A}$$
+is equivalent to the conjunction of the two statements
+$$\lim_{x -> a^-}{f(x) = A} {\rm\ and\ } \lim_{x -> a^+}{f(x) = A}$$.
+
+The existence of the limit from the left does not imply the existence
+of the limit from the right.  The existence of the limit from the
+right does not imply the existence of the limit from the left.
+
+When a function is defined only on one side of a point $a$, then
+$$\lim_{x -> a}{f(x)}$$
+is identical with the one-sided limit, if it exists. A two-sided
+limit might not exist because it is not defined outside a certain 
+bound. For example, if
+$$f(x)=\sqrt{x}$$
+then $f$ is defined only at and to the right of 0. Hence,
+$$\lim_{x->0}{\sqrt{x}}=\lim_{x->0^+}{\sqrt{x}}=0$$
+But the limit
+$$\lim_{x->0^-}{\sqrt{x}}$$
+does not exist since $\sqrt{x}$ is not defined for real values of $x$.
+
+A limit might not exist because the function grows without bound
+as it approaches the limit point. For example, the function
+$\sqrt{\frac{1}{x}}$ is only defined when $x > 0$. So
+$$\lim_{x->0^+}{\sqrt{\frac{1}{x}}}$$
+does not exist since $\frac{1}{x}$ gets larger as $x -> 0$ from
+the right. So
+$$\lim_{x->0}{\sqrt{\frac{1}{x}}}$$
+does not exist.
+
+<<*>>=
+--S 2 of 15
+limit(sqrt(9-x^2),x=-4)
+--R 
+--R
+--R   (2)  "failed"
+--R                                                    Type: Union("failed",...)
+--E 2
+
+--S 3 of 15
+limit(sqrt(9-x^2),x=-3)
+--R 
+--R
+--R   (3)  [leftHandLimit= "failed",rightHandLimit= 0]
+--RType: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
+--E 3
+
+--S 4 of 15
+limit(sqrt(9-x^2),x=-2)
+--R 
+--R
+--R         +-+
+--R   (4)  \|5
+--R                        Type: Union(OrderedCompletion Expression Integer,...)
+--E 4
+
+--S 5 of 15
+limit(sqrt(9-x^2),x=0)
+--R 
+--R
+--R   (5)  3
+--R                        Type: Union(OrderedCompletion Expression Integer,...)
+--E 5
+
+--S 6 of 15
+limit(sqrt(9-x^2),x=2)
+--R 
+--R
+--R         +-+
+--R   (6)  \|5
+--R                        Type: Union(OrderedCompletion Expression Integer,...)
+--E 6
+
+--S 7 of 15
+limit(sqrt(9-x^2),x=3)
+--R 
+--R
+--R   (7)  [leftHandLimit= 0,rightHandLimit= "failed"]
+--RType: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
+--E 7
+
+--S 8 of 15
+limit(sqrt(9-x^2),x=4)
+--R 
+--R
+--R   (8)  "failed"
+--R                                                    Type: Union("failed",...)
+--E 8
+
 @
+\section{Theorems on Limits}
+If $$f(x)=c$$ where $c$ is a constant, then
+$$\lim_{x->a}{f(x)=c}$$
+
+Assume that 
+$$\lim_{x->a}{f(x)=A}{\rm\ and\ }\lim_{x->a}{g(x)=B}$$
+then the limit of a constant times a function is 
+the constant times limit of a function is
+the constant times the limit.
+$$\lim_{x->a}{cf(x)}=
+c*\lim_{x->a}{f(x)=
+cA}$$
+
+The limit of a function plus (or minus) another function is
+the limit of the first function plus (or minus)
+the limit of the second function is
+the sum (or difference) of their limits.
+$$\lim_{x->a}{[f(x)\pm{}g(x)]}=
+\lim_{x->a}{f(x)}\pm\lim_{x->a}{g(x)}=
+A\pm{}B$$
+
+The limit of the product of functions is
+the limit of the first function times the limit of the second function is
+the product of their limits.
+$$\lim_{x->a}{[f(x)g(x)]}=
+\lim_{x->a}{f(x)}*\lim_{x->a}{g(x)}=
+A*B$$
+
+The limit of the ratio of two functions is 
+the the limit of the first function divided by the limit of the
+second function provided the limit of the second function is non-zero.
+$$\lim_{x->a}{\left(\frac{f(x)}{g(x)}\right)}=
+\frac{\lim_{x->a}{f(x)}}{\lim_{x->a}{g(x)}}=
+\frac{A}{B},
+{\rm\ if\ }B\ne{}0$$
+
+The limit of the ${\rm{}n}^{th}$ root of a function is
+the ${\rm{}n}^{th}$ root of the limit of the function provided
+the ${\rm{}n}^{th}$ root exists.
+$$\lim_{x->a}{\sqrt[n]{f(x)}}=\sqrt[n]{\lim_{x->a}{f(x)}}=
+\sqrt[n]{A},{\rm\ if\ }\sqrt[n]{A}{\rm\ is\ defined}$$
+
 The returned limit seems to be wrong:
+
+\section{Infinity}
+Let
+$$\lim_{x->a}{f(x)}=+\infty$$
+mean that, as $x$ approaches $a$, $f(x)$ eventually becomes and
+therefore remains greater than any preassigned positive number,
+however large. In such a case, we say that $f(x)$ approaches
+$+\infty$ as $x$ approaches $a$. The
+$$\lim_{x->a}{f(x)}=+\infty$$
+if and only if, for any positive number $M$, there exists a
+positive number $\delta$ such that, whenever
+$$0 < \vert x-a \vert < \delta {\rm\ then\ }f(x) > M$$
+
+Similarly, let
+$$\lim_{x->a}{f(x)}=-\infty$$
+mean that, as $x$ approaches $a$, $f(x)$ eventually becomes and 
+thereafter remains less than any preassigned negative number. In
+that case, we say that $f(x)$ approaches
+$-\infty$ as $x$ approaches $a$. 
+
+Let
+$$\lim_{x->a}{f(x)}=\infty$$
+mean that, as $x$ approaches $a$, $\vert f(x)\vert$ eventually becomes and 
+thereafter remains greater than any preassigned positive number. Hence,
+$$\lim_{x->a}{f(x)}=\infty$$ if and only if 
+$$\lim_{x->a}{\vert f(x)\vert}=+\infty$$
+
+These definitions can be extended to one-sided limits.
+
+<<*>>=
+--S 9 of 15
+limit(1/x^2,x=0)
+--R 
+--R
+--R   (9)   + infinity
+--R               Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
+--E 9
+
+--S 10 of 15
+limit(-1/(x-1)^2,x=1)
+--R 
+--R
+--R   (10)  - infinity
+--R               Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
+--E 10
+
+--S 11 of 15
+limit(1/x,x=0)
+--R 
+--R
+--R   (11)  [leftHandLimit= - infinity,rightHandLimit=  + infinity]
+--RType: Union(Record(leftHandLimit: Union(OrderedCompletion Fraction Polynomial Integer,"failed"),rightHandLimit: Union(OrderedCompletion Fraction Polynomial Integer,"failed")),...)
+--E 11
+
+@
+The limit concepts already introduced can be extended to the case
+where the variable approaches $+\infty$ or $-\infty$. For example,
+$$\lim_{x->+\infty}{f(x)}=A$$
+means that $f(x)$ approaches $A$ as $x -> +\infty$ or, in more 
+precise terms, given any positive $\epsilon$, there exists a
+number $N$ such that, whenever $x>N$, then 
+$$\vert f(x)-A\vert < \epsilon$$
+
+Similar statements can be made for:
+$$\lim_{x->-\infty}{f(x)}=A$$
+$$\lim_{x->+\infty}{f(x)}=+\infty$$
+$$\lim_{x->-\infty}{f(x)}=-\infty$$
+$$\lim_{x->+\infty}{f(x)}=-\infty$$
+$$\lim_{x->-\infty}{f(x)}=+\infty$$
 <<*>>=
---S 1 of 2
+--S 12 of 15
+limit(1/x,x=%plusInfinity)
+--R 
+--R
+--R   (12)  0
+--R               Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
+--E 12
+
+--S 13 of 15
+limit(2+(1/x^2),x=%plusInfinity)
+--R 
+--R
+--R   (13)  2
+--R               Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
+--E 13
+
+)clear all
+
+--S 14 of 15
 f := exp(n) * (sin(1/n + exp(-n)) - sin(1/n))
 --R 
 --R
@@ -31,22 +283,24 @@ f := exp(n) * (sin(1/n + exp(-n)) - sin(1/n))
 --R   (1)  %e sin(-----------) - %e sin(-)
 --R                    n                n
 --R                                                     Type: Expression Integer
---E 1
+--E 14
 
---S 2 of 2
+--S 15 of 15
 limit(f,n=%plusInfinity)
 --R 
 --R
 --R   (2)  "failed"
 --R                                                    Type: Union("failed",...)
---E 2
+--E 15
 )spool 
 )lisp (bye)
  
 @
 \eject
 \begin{thebibliography}{99}
-\bibitem{1} nothing
+\bibitem{1} Ayres, Frank Jr. and Mendelson, Elliott
+``Calculus'' Schaum's Outlines 4th edition 1999
+ISBN 0-07-041973-6 pp61-63
 \end{thebibliography}
 \end{document}
 
\start
Date: Mon, 27 Aug 2007 02:32:45 -0500
From: Tim Daly
To: list
Subject: 20070812.02.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 19aff4b..c74b102 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070812 acr src/algebra/mathml.spad license change
 20070812 tpd re-merge input branch
 20070811 tpd src/input/Makefile add classtalk, calcprob
 20070811 tpd src/input/limit.input.pamphlet updated with new tests
diff --git a/src/algebra/mathml.spad.pamphlet b/src/algebra/mathml.spad.pamphlet
index c589e78..f704c76 100644
--- a/src/algebra/mathml.spad.pamphlet
+++ b/src/algebra/mathml.spad.pamphlet
@@ -1334,7 +1334,7 @@ have to be switched by swapping names.
 @
 \section{License}
 <<license>>=
---Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+--Copyright (c) 2007, Arthur C. Ralfs
 --All rights reserved.
 --
 --Redistribution and use in source and binary forms, with or without
@@ -1349,9 +1349,9 @@ have to be switched by swapping names.
 --      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.
+--    - The name of Arthur C. Ralfs may not 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

\start
Date: Mon, 27 Aug 2007 02:33:58 -0500
From: Tim Daly
To: list
Subject: 20070812.03.tpd.patch applied to silver

diff --git a/changelog b/changelog
index c74b102..8b9969f 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,5 @@
+20070812 tpd src/algebra/Makefile newton.spad added
+20070812 tpd src/algebra/newton.spad added
 20070812 acr src/algebra/mathml.spad license change
 20070812 tpd re-merge input branch
 20070811 tpd src/input/Makefile add classtalk, calcprob
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index 9172e69..6a281bc 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -346,7 +346,8 @@ LAYER8=\
   ${OUT}/BSTREE.o  ${OUT}/BTOURN.o   ${OUT}/CARD.o    ${OUT}/DRAWHACK.o \
   ${OUT}/DQAGG.o   ${OUT}/FACTFUNC.o ${OUT}/FMTC.o    ${OUT}/FR2.o      \
   ${OUT}/FRAC2.o   ${OUT}/FRUTIL.o   ${OUT}/ITAYLOR.o ${OUT}/MLO.o      \
-  ${OUT}/NAALG.o   ${OUT}/NAALG-.o   ${OUT}/OAGROUP.o ${OUT}/OAMONS.o   \
+  ${OUT}/NAALG.o   ${OUT}/NAALG-.o   ${OUT}/NEWTON.o  \
+  ${OUT}/OAGROUP.o ${OUT}/OAMONS.o   \
   ${OUT}/OP.o      ${OUT}/ORDCOMP2.o ${OUT}/PID.o     ${OUT}/RANDSRC.o  \
   ${OUT}/UNISEG2.o ${OUT}/XALG.o  \
   layer8done
@@ -1260,7 +1261,7 @@ SPADFILES= \
  ${OUTSRC}/mts.spad ${OUTSRC}/multfact.spad ${OUTSRC}/multpoly.spad \
  ${OUTSRC}/multsqfr.spad \
  ${OUTSRC}/naalgc.spad ${OUTSRC}/naalg.spad \
- ${OUTSRC}/newdata.spad ${OUTSRC}/newpoint.spad \
+ ${OUTSRC}/newdata.spad ${OUTSRC}/newpoint.spad ${OUTSRC}/newton.spad \
  ${OUTSRC}/newpoly.spad ${OUTSRC}/nlinsol.spad ${OUTSRC}/nlode.spad \
  ${OUTSRC}/npcoef.spad \
  ${OUTSRC}/nregset.spad \
@@ -1422,6 +1423,7 @@ DOCFILES= \
  ${DOC}/multsqfr.spad.dvi \
  ${DOC}/naalgc.spad.dvi ${DOC}/naalg.spad.dvi ${DOC}/ndftip.as.dvi \
  ${DOC}/nepip.as.dvi ${DOC}/newdata.spad.dvi ${DOC}/newpoint.spad.dvi \
+ ${DOC}/newton.spad.dvi \
  ${DOC}/newpoly.spad.dvi ${DOC}/nlinsol.spad.dvi ${DOC}/nlode.spad.dvi \
  ${DOC}/noptip.as.dvi ${DOC}/npcoef.spad.dvi ${DOC}/nqip.as.dvi \
  ${DOC}/nrc.as.dvi ${DOC}/nregset.spad.dvi ${DOC}/nsfip.as.dvi \
diff --git a/src/algebra/newton.spad.pamphlet b/src/algebra/newton.spad.pamphlet
new file mode 100644
index 0000000..6f588bc
--- /dev/null
+++ b/src/algebra/newton.spad.pamphlet
@@ -0,0 +1,46 @@
+\documentclass{article}
+\usepackage{amsthm,amsmath,axiom}
+\begin{document}
+\title{newton.spad}
+\author{Martin Rubey}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\tableofcontents
+\section{package NEWTON NewtonInterpolation}
+<<package NEWTON NewtonInterpolation>>=
+)abbrev package NEWTON NewtonInterpolation
+++ Description:
+++ This package exports Newton interpolation for the special case where the
+++ result is known to be in the original integral domain
+NewtonInterpolation F: Exports == Implementation where
+    F: IntegralDomain
+    Exports == with
+      newton: List F -> SparseUnivariatePolynomial F
+
+    Implementation == add
+
+      differences(yl: List F): List F == 
+        [y2-y1 for y1 in yl for y2 in rest yl]
+
+      z:SparseUnivariatePolynomial(F) := monomial(1,1)
+
+-- we assume x=[1,2,3,...,n]
+      newtonAux(k: F, fact: F, yl: List F): SparseUnivariatePolynomial(F) ==
+        if empty? rest yl 
+        then ((yl.1) exquo fact)::F::SparseUnivariatePolynomial(F)
+        else ((yl.1) exquo fact)::F::SparseUnivariatePolynomial(F) 
+             + (z-k::SparseUnivariatePolynomial(F)) _
+               * newtonAux(k+1$F, fact*k, differences yl)
+
+
+      newton yl == newtonAux(1$F, 1$F, yl)
+@
+<<*>>=
+<<package NEWTON NewtonInterpolation>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}

\start
Date: Mon, 27 Aug 2007 02:10:47 -0500
From: Tim Daly
To: list
Subject: 20070722.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 7091ec9..962132e 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070722 tpd src/interp/Makefile cleanup latex warnings
 20070721 wxh src/interp/spad.lisp make evalSharpOne declare arg specials
 20070721 tpd src/interp/setq.lisp update contributor name list
 20070721 tpd readme update contributor name list
diff --git a/src/interp/Makefile.pamphlet b/src/interp/Makefile.pamphlet
index 49f9cc4..23ec4cc 100644
--- a/src/interp/Makefile.pamphlet
+++ b/src/interp/Makefile.pamphlet
@@ -545,7 +545,8 @@ in util.lisp that emulates the new boot parser command BOOTTOCL. since
 we eventually plan to move to the new boot parser this function (and
 the push) should disappear.
 
-The load of postpar and parse (without extensions) allows the [[.${LISP}]] 
+The load of postpar and parse (without extensions) allows the 
+\verb+.${LISP}+
 form to be loaded in a virgin system. However, if depsys is recreated then
 the compiled form will get loaded.
 
@@ -2390,9 +2391,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN C-UTIL.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE C-UTIL.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in c-util.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the c-util.boot.pamphlet file. this is not automated.}
 <<c-util.lisp (OUT from IN)>>=
 ${OUT}/c-util.${LISP}: ${IN}/c-util.boot.pamphlet
 	@ echo 146 making ${OUT}/c-util.${LISP} from ${IN}/c-util.boot.pamphlet
@@ -3290,9 +3291,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN CLAM.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE CLAM.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in clam.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the clam.boot.pamphlet file. this is not automated.}
 <<clam.lisp (OUT from IN)>>=
 ${OUT}/clam.${LISP}: ${IN}/clam.boot.pamphlet
 	@ echo 221 making ${OUT}/clam.${LISP} from ${IN}/clam.boot.pamphlet
@@ -3760,9 +3761,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN G-BOOT.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE G-BOOT.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in g-boot.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the g-boot.boot.pamphlet file. this is not automated.}
 <<g-boot.lisp (OUT from IN)>>=
 ${OUT}/g-boot.${LISP}: ${IN}/g-boot.boot.pamphlet
 	@ echo 256 making ${OUT}/g-boot.${LISP} from ${IN}/g-boot.boot.pamphlet
@@ -3991,9 +3992,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN G-UTIL.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE G-UTIL.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in g-util.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the g-util.boot.pamphlet file. this is not automated.}
 <<g-util.lisp (OUT from IN)>>=
 ${OUT}/g-util.${LISP}: ${IN}/g-util.boot.pamphlet
 	@ echo 272 making ${OUT}/g-util.${LISP} from ${IN}/g-util.boot.pamphlet
@@ -5436,12 +5437,10 @@ ${DOC}/package.boot.dvi: ${IN}/package.boot.pamphlet
 @
 
 \subsection{parse.boot}
-\begin{verbatim}
-NOTE: this is used to build a bootsys on a virgin copy of the system
-notice that the file placed in ${OUT} is a .lisp file
-this is to allow the depsys to be built even if the .${O} file does
+note: this is used to build a bootsys on a virgin copy of the system
+notice that the file placed in \verb+${OUT}+ is a .lisp file
+this is to allow the depsys to be built even if the \verb+.${O}+ file does
 not exist on the new system
-\end{verbatim}
 <<parse.o (AUTO from OUT)>>=
 ${AUTO}/parse.${O}: ${OUT}/parse.${O}
 	@ echo 374 making ${AUTO}/parse.${O} from ${OUT}/parse.${O}
@@ -5468,9 +5467,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN PARSE.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE PARSE.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in parse.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the parse.boot.pamphlet file. this is not automated.}
 <<parse.lisp (OUT from IN)>>=
 ${OUT}/parse.${LISP}: ${IN}/parse.boot.pamphlet
 	@ echo 376 making ${OUT}/parse.${LISP} from ${IN}/parse.boot.pamphlet
@@ -5551,12 +5550,10 @@ ${DOC}/pathname.boot.dvi: ${IN}/pathname.boot.pamphlet
 @
 
 \subsection{postpar.boot}
-\begin{verbatim}
-NOTE: this is used to build bootsys on a virgin copy of the system
-notice that the file placed in ${OUT} is a .lisp file
-this allows the depsys to be built even if the .${O} file does
+note: this is used to build bootsys on a virgin copy of the system
+notice that the file placed in \verb+${OUT}+ is a .lisp file
+this allows the depsys to be built even if the \verb+.${O}+ file does
 not exist on the new system
-\end{verbatim}
 <<postpar.o (AUTO from OUT)>>=
 ${AUTO}/postpar.${O}: ${OUT}/postpar.${O}
 	@ echo 382 making ${AUTO}/postpar.${O} from ${OUT}/postpar.${O}
@@ -5569,9 +5566,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN POSTPAR.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE POSTPAR.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in postpar.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the postpar.boot.pamphlet file. this is not automated.}
 <<postpar.lisp (OUT from IN)>>=
 ${OUT}/postpar.${LISP}: ${IN}/postpar.boot.pamphlet
 	@ echo 383 making ${OUT}/postpar.${LISP} \
@@ -5765,9 +5762,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN SETVARS.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE SETVARS.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in setvars.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the setvars.boot.pamphlet file. this is not automated.}
 <<setvars.lisp (OUT from IN)>>=
 ${OUT}/setvars.${LISP}: ${IN}/setvars.boot.pamphlet
 	@ echo 393 making ${OUT}/setvars.${LISP} \
@@ -5915,9 +5912,9 @@ code. We need to keep the translated code around so we can bootstrap
 the system. In other words, we need this boot code translated so we
 can build the boot translator.
 
-{\bf NOTE: IF YOU CHANGE THE BOOT CODE IN SLAM.BOOT.PAMPHLET
-YOU MUST TRANSLATE THIS CODE TO LISP AND STORE THE RESULTING LISP
-CODE BACK INTO THE SLAM.BOOT.PAMPHLET FILE. THIS IS NOT AUTOMATED.}
+{\bf note: if you change the boot code in slam.boot.pamphlet
+you must translate this code to lisp and store the resulting lisp
+code back into the slam.boot.pamphlet file. this is not automated.}
 <<slam.lisp (OUT from IN)>>=
 ${OUT}/slam.${LISP}: ${IN}/slam.boot.pamphlet
 	@ echo 403 making ${OUT}/slam.${LISP} from ${IN}/slam.boot.pamphlet
@@ -8546,7 +8543,7 @@ information is useful. There are 2 cases:
 (as of 2/92: browser old parser and old compiler)
 \item adding new files
 \begin{itemize}
-\item case 1:\\
+\item case 1:
 \begin{itemize}
 \item [(a)] you have to add the file to the list of files currently there
 (e.g. see BROBJS above)

\start
Date: Mon, 27 Aug 2007 02:39:11 -0500
From: Tim Daly
To: list
Subject: 20070821.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 4b64859..e6c9731 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070821 tpd src/sman/Makefile remove ${DOC}/bookvol6.idx
 20070819 tpd src/sman/Makefile rewrite to use bookvol6
 20070819 tpd src/sman/spadclient.c removed
 20070819 tpd src/sman/sman insert src/share/command.list
diff --git a/src/sman/Makefile.pamphlet b/src/sman/Makefile.pamphlet
index ca19ad0..5c73b11 100644
--- a/src/sman/Makefile.pamphlet
+++ b/src/sman/Makefile.pamphlet
@@ -115,6 +115,7 @@ ${DOC}/bookvol6.dvi: ${IN}/bookvol6.pamphlet
 	cp ${IN}/bookvol6.pamphlet ${DOC} ; \
 	${DOCUMENT} ${NOISE} bookvol6 ; \
 	rm -f ${DOC}/bookvol6.pamphlet ; \
+	rm -f ${DOC}/bookvol6.idx ; \
 	rm -f ${DOC}/bookvol6.tex ; \
 	rm -f ${DOC}/bookvol6 )
 

\start
Date: Mon, 27 Aug 2007 02:40:29 -0500
From: Tim Daly
To: list
Subject: 20070821.02.tpd.patch applied to silver

diff --git a/changelog b/changelog
index e6c9731..282bd89 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,7 @@
+20070821 tpd src/sman/bookvol6 add axiom command
+20070821 tpd src/sman/Makefile add axiom command
+20070821 tpd src/etc/axiom remove axiom command
+20070821 tpd src/etc/Makefile remove axiom command
 20070821 tpd src/sman/Makefile remove ${DOC}/bookvol6.idx
 20070819 tpd src/sman/Makefile rewrite to use bookvol6
 20070819 tpd src/sman/spadclient.c removed
diff --git a/src/etc/Makefile.pamphlet b/src/etc/Makefile.pamphlet
index 2b113ff..624e504 100644
--- a/src/etc/Makefile.pamphlet
+++ b/src/etc/Makefile.pamphlet
@@ -9,14 +9,6 @@
 \eject
 \tableofcontents
 \eject
-\section{The axiom command}
-<<axiomcmd>>=
-${OUT}/axiom: ${IN}/axiom
-	@echo 1 making ${OUT}/axiom from ${IN}/axiom
-	@cp ${IN}/axiom ${OUT}/axiom
-	@chmod +x ${OUT}/axiom
-
-@
 \section{The databases}
 The databases are built in this Makefile even though the prerequisites
 are actually made during the previous step in the algebra directory.
@@ -91,14 +83,13 @@ DOC=${INT}/doc/src/etc
 INTERPSYS=${OBJ}/${SYS}/bin/interpsys
 
 all: ${MNT}/${SYS}/algebra/*.daase ${OUT}/asq ${LIB}/summary \
-     ${LIB}/copyright ${OUT}/axiom
+     ${LIB}/copyright 
 	@echo 6 finished ${IN}
 
 <<dbcomplete>>
 <<asq>>
 <<summary>>
 <<copyright>>
-<<axiomcmd>>
 document:
 	@echo 7 documenting ${IN}
 	@( cd ${DOC} ; \
diff --git a/src/etc/axiom b/src/etc/axiom
deleted file mode 100644
index 9034cc0..0000000
--- a/src/etc/axiom
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/bin/sh
-
-# Start everything for Axiom.
-#
-# axiom
-#      [-ht   |-noht]	    whether to use HyperDoc
-#      [-gr   |-nogr]	    whether to use Graphics
-#      [-clef |-noclef]	    whether to use Clef
-#      [-nag |-nonag]	    whether to use NAG
-#      [-iw   |-noiw]	    start in interpreter window
-#      [-ihere|-noihere]    start an interpreter buffer in the original window
-#      [-nox]		    don't use X Windows
-#      [-go  |-nogo]	    whether to start system
-#      [-ws wsname]	    use named workspace
-#      [-list]		    list workspaces only
-#      [-grprog fname]	    use named program for Graphics
-#      [-nagprog fname]	    use named program for Nag
-#      [-htprog fname]	    use named program for HyperDoc
-#      [-clefprog fname]    use named program for Clef
-#      [-sessionprog fname] use named program for session
-#      [-clientprog fname]  use named program for spadclient
-#      [-h]		    show usage
-#
-#
-
-MALLOCTYPE=3.1
-export MALLOCTYPE
-
-# NAGMAN needs to know the hostname
-HOST=`hostname`
-export HOST
-
-# 0. Basic utilities
-
-ciao() {
-	echo "Goodbye."
-	exit 1
-}
-
-needsubopt () {
-	echo "The $1 option requires an argument."
-	ciao
-}
-
-
-showuse() {
-echo "axiom"
-echo "     [-ht   |-noht]       whether to use HyperDoc"
-echo "     [-gr   |-nogr]       whether to use Graphics"
-echo "     [-clef |-noclef]     whether to use Clef"
-echo "     [-nag |-nonag]       whether to use NAG"
-echo "     [-iw   |-noiw]       start in interpreter window"
-echo "     [-ihere|-noihere]    start an interpreter buffer in the original window."
-echo "     [-nox]               don't use X Windows"
-echo "     [-go  |-nogo]        whether to start system"
-echo "     [-ws wsname]         use named workspace"
-echo "     [-list]              list workspaces only"
-#echo "     [-grprog fname]      use named program for Graphics"
-#echo "     [-nagprog fname]      use named program for Nag"
-#echo "     [-htprog fname]      use named program for HyperDoc"
-#echo "     [-clefprog fname]    use named program for Clef"
-#echo "     [-sessionprog fname] use named program for session"
-#echo "     [-clientprog fname]  use named program for spadclient"
-echo "     [-h]                 show usage"
-}
-
-# 1. Ensure the environment is set.
-
-# Just process '-h'
-
-if [ "$*" = "-h" ] ; then
-     showuse
-fi
-SPADDEFAULT=/axiom/mnt/linux
-
-if [ "$SPAD" = "" ] ; then
-  if [ "$AXIOM" = "" ] ; then
-    SPAD=$SPADDEFAULT
-    echo "AXIOM variable is not set"
-    echo "assuming AXIOM = $SPAD"
-    AXIOM=$SPAD
-    export AXIOM
-  else
-    SPAD=$AXIOM
-  fi
-  export SPAD
-else
-  if [ "$AXIOM" = "" ] ; then
-    echo "AXIOM variable is not set"
-    echo "but SPAD = $SPAD"
-    echo "Using AXIOM = $SPAD"
-    AXIOM=$SPAD
-    export AXIOM
-  else
-    if [ ! "$SPAD" = "$AXIOM" ] ; then
-       echo "ignoring SPAD variable"
-       SPAD=$AXIOM
-    fi
-  fi
-fi
-
-if [ "$AXIOMXLROOT" = "" ] ; then 
-AXIOMXLROOT=${AXIOM}/compiler
-fi
-export AXIOMXLROOT
-PATH=$AXIOM/bin:$AXIOMXLROOT/bin:${PATH}
-export PATH
-
-
-
-if [ ! -d "$SPAD" ] ; then
-  echo "The directory for Axiom, $SPAD, does not exist."
-  ciao
-fi
-
-# Name the workspace directories.
-rootwsdir=$SPAD/bin
-
-# 2. Process command line arguments.
-
-# Defaults for command-line arguments.
-list=no
-go=yes
-wsname=AXIOMsys
-
-otheropts=""
-
-while [ "$*" != "" ] ; do
-
-	case $1 in
-        -list)  list=yes
-                go=no;;
-	-go)	go=yes ;;
-	-nogo)	go=no ;;
-
-	-ws)
-		if [ "$2" = "" ] ; then needsubopt "$1" ; fi
-		shift
-		wsname="$1"
-		;;
-
-	-nagprog|-grprog|-htprog|-clefprog|-sessionprog|-clientprog|-paste|-rm|-rv)
-		if [ "$2" = "" ] ; then needsubopt "$1" ; fi
-		otheropts="$otheropts  $1 $2"
-		shift
-		;;
-	-clef|-noclef|-gr|-nogr|-ht|-noht|-iw|-noiw|-ihere|-noihere|-nox|-nag|-nonag)
-		otheropts="$otheropts $1"
-		;;
-
-	-h)
-		go=no
-		;;
-
-
-	*)	echo "Unknown option: $1"
-		echo "To use a specific workspace use, e.g.: spad -ws $1"
-		ciao
-		;;
-	esac
-
-	shift
-done
-
-# 3. List the available workspaces, if asked
-
-listwspaces()
-{
-        echo "$1"
-        ls -l $2 | grep "sys$"
-        echo ""
-}
-
-if [ $list = yes ] ; then
-          listwspaces "AXIOM workspaces in \$AXIOM/bin = $rootwsdir: " $rootwsdir
-fi
-
-# 5. Try to ensure a suitable workspace on this host.
-
-if [ `expr $wsname : '.*/.*'` = 0 ] ; then
-	serverws=$rootwsdir/$wsname
-else
-	serverws=$wsname
-fi
-
-if [ ! -f $serverws ] ; then
-	showuse
-	ciao
-fi
-
-# 6. Start processes
-
-if [ $go = no ] ; then
-	echo "Would now start the processes."
-	echo exec $SPAD/bin/sman $otheropts -ws $serverws
-	exit 0
-fi
-
-exec $SPAD/bin/sman $otheropts -ws $serverws
diff --git a/src/sman/Makefile.pamphlet b/src/sman/Makefile.pamphlet
index 5c73b11..f95a511 100644
--- a/src/sman/Makefile.pamphlet
+++ b/src/sman/Makefile.pamphlet
@@ -39,6 +39,15 @@ DOCFILES=${DOC}/bookvol6.dvi
 SMANOBJS= ${LIB}/libspad.a
 
 @
+\section{The axiom command}
+<<axiomcmd>>=
+${OUT}/axiom: ${IN}/bookvol6.pamphlet
+	@echo 1 making ${OUT}/axiom from ${IN}/bookvol6.pamphlet
+	@ (cd ${OUT} ; \
+           ${TANGLE} -R"axiomcmd" ${IN}/bookvol6.pamphlet >axiom )
+	@chmod +x ${OUT}/axiom
+
+@
 \section{session}
 <<session>>=
 ${OUTLIB}/session: ${SMANOBJS} ${MIDOBJ}/session.o
@@ -122,12 +131,14 @@ ${DOC}/bookvol6.dvi: ${IN}/bookvol6.pamphlet
 @
 <<*>>=
 <<environment>>
-all:	${OUTLIB}/session ${OUTLIB}/spadclient ${OUT}/sman ${DOCFILES}
+all:	${OUTLIB}/session ${OUTLIB}/spadclient ${OUT}/sman ${OUT}/axiom \
+        ${DOCFILES}
 	@ echo 18 finished ${IN}
 
 clean:
 	@echo 19 cleaning ${SRC}/sman
 
+<<axiomcmd>>
 <<sman>>
 <<session>>
 <<spadclient>>
diff --git a/src/sman/bookvol6.pamphlet b/src/sman/bookvol6.pamphlet
index 4ab4355..ade0c54 100644
--- a/src/sman/bookvol6.pamphlet
+++ b/src/sman/bookvol6.pamphlet
@@ -22,7 +22,7 @@ Jonathan\ Steinbach    & Robert\ Sutor    & Barry\ Trager \\
 Stephen\ Watt          & Jim\ Wen         & Clifton\ Williamson
 \end{array}
 $$
-\center{\large{VOLUME 6: SMAN}}
+\center{\large{VOLUME 6: AXIOM COMMAND}}
 \end{titlepage}
 \pagenumbering{roman}
 \begin{verbatim}
@@ -197,6 +197,208 @@ November 10, 2003 ((iHy))
 The superman process, called sman, is normally invoked from the
 axiom shell script in order to start a tree of subprocesses.
 
+\chapter{The axiom Command}
+<<axiomcmd>>=
+#!/bin/sh
+
+# Start everything for Axiom.
+#
+# axiom
+#      [-ht   |-noht]	    whether to use HyperDoc
+#      [-gr   |-nogr]	    whether to use Graphics
+#      [-clef |-noclef]	    whether to use Clef
+#      [-nag |-nonag]	    whether to use NAG
+#      [-iw   |-noiw]	    start in interpreter window
+#      [-ihere|-noihere]    start an interpreter buffer in the original window
+#      [-nox]		    don't use X Windows
+#      [-go  |-nogo]	    whether to start system
+#      [-ws wsname]	    use named workspace
+#      [-list]		    list workspaces only
+#      [-grprog fname]	    use named program for Graphics
+#      [-nagprog fname]	    use named program for Nag
+#      [-htprog fname]	    use named program for HyperDoc
+#      [-clefprog fname]    use named program for Clef
+#      [-sessionprog fname] use named program for session
+#      [-clientprog fname]  use named program for spadclient
+#      [-h]		    show usage
+#
+#
+
+MALLOCTYPE=3.1
+export MALLOCTYPE
+
+# NAGMAN needs to know the hostname
+HOST=`hostname`
+export HOST
+
+# 0. Basic utilities
+
+ciao() {
+	echo "Goodbye."
+	exit 1
+}
+
+needsubopt () {
+	echo "The $1 option requires an argument."
+	ciao
+}
+
+
+showuse() {
+echo "axiom"
+echo "     [-ht   |-noht]       whether to use HyperDoc"
+echo "     [-gr   |-nogr]       whether to use Graphics"
+echo "     [-clef |-noclef]     whether to use Clef"
+echo "     [-nag |-nonag]       whether to use NAG"
+echo "     [-iw   |-noiw]       start in interpreter window"
+echo "     [-ihere|-noihere]    start an interpreter buffer in the original window."
+echo "     [-nox]               don't use X Windows"
+echo "     [-go  |-nogo]        whether to start system"
+echo "     [-ws wsname]         use named workspace"
+echo "     [-list]              list workspaces only"
+#echo "     [-grprog fname]      use named program for Graphics"
+#echo "     [-nagprog fname]      use named program for Nag"
+#echo "     [-htprog fname]      use named program for HyperDoc"
+#echo "     [-clefprog fname]    use named program for Clef"
+#echo "     [-sessionprog fname] use named program for session"
+#echo "     [-clientprog fname]  use named program for spadclient"
+echo "     [-h]                 show usage"
+}
+
+# 1. Ensure the environment is set.
+
+# Just process '-h'
+
+if [ "$*" = "-h" ] ; then
+     showuse
+fi
+SPADDEFAULT=/axiom/mnt/linux
+
+if [ "$SPAD" = "" ] ; then
+  if [ "$AXIOM" = "" ] ; then
+    SPAD=$SPADDEFAULT
+    echo "AXIOM variable is not set"
+    echo "assuming AXIOM = $SPAD"
+    AXIOM=$SPAD
+    export AXIOM
+  else
+    SPAD=$AXIOM
+  fi
+  export SPAD
+else
+  if [ "$AXIOM" = "" ] ; then
+    echo "AXIOM variable is not set"
+    echo "but SPAD = $SPAD"
+    echo "Using AXIOM = $SPAD"
+    AXIOM=$SPAD
+    export AXIOM
+  else
+    if [ ! "$SPAD" = "$AXIOM" ] ; then
+       echo "ignoring SPAD variable"
+       SPAD=$AXIOM
+    fi
+  fi
+fi
+
+if [ "$AXIOMXLROOT" = "" ] ; then 
+AXIOMXLROOT=${AXIOM}/compiler
+fi
+export AXIOMXLROOT
+PATH=$AXIOM/bin:$AXIOMXLROOT/bin:${PATH}
+export PATH
+
+
+
+if [ ! -d "$SPAD" ] ; then
+  echo "The directory for Axiom, $SPAD, does not exist."
+  ciao
+fi
+
+# Name the workspace directories.
+rootwsdir=$SPAD/bin
+
+# 2. Process command line arguments.
+
+# Defaults for command-line arguments.
+list=no
+go=yes
+wsname=AXIOMsys
+
+otheropts=""
+
+while [ "$*" != "" ] ; do
+
+	case $1 in
+        -list)  list=yes
+                go=no;;
+	-go)	go=yes ;;
+	-nogo)	go=no ;;
+
+	-ws)
+		if [ "$2" = "" ] ; then needsubopt "$1" ; fi
+		shift
+		wsname="$1"
+		;;
+
+	-nagprog|-grprog|-htprog|-clefprog|-sessionprog|-clientprog|-paste|-rm|-rv)
+		if [ "$2" = "" ] ; then needsubopt "$1" ; fi
+		otheropts="$otheropts  $1 $2"
+		shift
+		;;
+	-clef|-noclef|-gr|-nogr|-ht|-noht|-iw|-noiw|-ihere|-noihere|-nox|-nag|-nonag)
+		otheropts="$otheropts $1"
+		;;
+
+	-h)
+		go=no
+		;;
+
+
+	*)	echo "Unknown option: $1"
+		echo "To use a specific workspace use, e.g.: spad -ws $1"
+		ciao
+		;;
+	esac
+
+	shift
+done
+
+# 3. List the available workspaces, if asked
+
+listwspaces()
+{
+        echo "$1"
+        ls -l $2 | grep "sys$"
+        echo ""
+}
+
+if [ $list = yes ] ; then
+          listwspaces "AXIOM workspaces in \$AXIOM/bin = $rootwsdir: " $rootwsdir
+fi
+
+# 5. Try to ensure a suitable workspace on this host.
+
+if [ `expr $wsname : '.*/.*'` = 0 ] ; then
+	serverws=$rootwsdir/$wsname
+else
+	serverws=$wsname
+fi
+
+if [ ! -f $serverws ] ; then
+	showuse
+	ciao
+fi
+
+# 6. Start processes
+
+if [ $go = no ] ; then
+	echo "Would now start the processes."
+	echo exec $SPAD/bin/sman $otheropts -ws $serverws
+	exit 0
+fi
+
+exec $SPAD/bin/sman $otheropts -ws $serverws
+@
 \chapter{Support Routines}
 \section{Command Completion}
 Hyperdoc has the ability to do command completion. The known commands

\start
Date: Mon, 27 Aug 2007 02:44:20 -0500
From: Tim Daly
To: list
Subject: 20070822.02.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 4d1e56e..e981cf7 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,6 @@
+20070822 tpd src/doc/spadhelp add language help
+20070822 tpd src/doc/Makefile add spadhelp
+20070822 tpd src/doc/spadhelp created
 20070822 tpd src/lib/openpty.c document the openpty.c functions
 20070821 tpd src/sman/bookvol6 document the axiom shell script
 20070821 tpd src/sman/bookvol6 add axiom command
diff --git a/src/doc/Makefile.pamphlet b/src/doc/Makefile.pamphlet
index 1120c5f..c5af55b 100644
--- a/src/doc/Makefile.pamphlet
+++ b/src/doc/Makefile.pamphlet
@@ -129,6 +129,26 @@ ${INT}/booklet.c: ${IN}/booklet.c.pamphlet
 	  ${TANGLE} ${IN}/booklet.c.pamphlet >booklet.c )
 	  
 @
+\section{The )help files}
+<<helpspad>>=
+HELPSPAD=abbreviation boot cd clear close compile display edit fin frame \
+         help history \
+         language library lisp load ltrace \
+         nclef pquit quit read \
+         savesystem set show spool synonym system trace undo what
+
+@
+<<helpspad.files>>=
+${DVI}/spadhelp/helpspad.files: ${IN}/spadhelp.pamphlet
+	@echo 9 making ${DVI}/spadhelp from ${IN}/spadhelp.pamphlet
+	@mkdir ${DVI}/spadhelp
+	@(cd ${DVI}/spadhelp ; \
+          for i in ${HELPSPAD} ; do \
+            ${TANGLE} -R"$$i" ${IN}/spadhelp.pamphlet >$$i.help ; \
+          done ; \
+          ls *.help >helpspad.files )
+
+@
 \section{The Makefile}
 We need to document the commands.
 <<*>>=
@@ -141,10 +161,12 @@ DOC=${INT}/doc
 
 FILES= ${MID}/axiom.bib ${STY}/axiom.sty ${DVI}/bookvol4.dvi \
        ${DVI}/book.dvi ${DVI}/bookvol1.dvi ${DVI}/endpaper.dvi \
-       ${DVI}/rosetta.dvi
+       ${DVI}/rosetta.dvi ${DVI}/spadhelp/helpspad.files
 
 CMDS=${OUT}/booklet
 
+<<helpspad>>
+
 all: ${FILES} ${CMDS}
 	@echo 9 finished ${IN}
 
@@ -156,6 +178,8 @@ all: ${FILES} ${CMDS}
 <<bookvol1>>
 <<Endpapers>>
 <<rosetta>>
+<<helpspad.files>>
+
 
 document:
 	@echo 10 documenting ${SRC}/doc
diff --git a/src/doc/spadhelp.pamphlet b/src/doc/spadhelp.pamphlet
new file mode 100644
index 0000000..77f0027
--- /dev/null
+++ b/src/doc/spadhelp.pamphlet
@@ -0,0 +1,2007 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/doc spadhelp}
+\author{Timothy Daly}
+\maketitle
+\begin{abstract}
+This is a collection of the help commands available to the Axiom
+command line )help command.
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{abbreviation}
+<<abbreviation>>=
+====================================================================
+A.2.  )abbreviation
+====================================================================
+ 
+User Level Required:  compiler
+ 
+Command Syntax: 
+ 
+  -  )abbreviation query  [nameOrAbbrev]
+  -  )abbreviation category  abbrev  fullname [)quiet]
+  -  )abbreviation domain  abbrev  fullname   [)quiet]
+  -  )abbreviation package  abbrev  fullname  [)quiet]
+  -  )abbreviation remove  nameOrAbbrev
+ 
+Command Description: 
+ 
+This command is used to query, set and remove abbreviations for category,
+domain and package constructors. Every constructor must have a unique
+abbreviation. This abbreviation is part of the name of the subdirectory under
+which the components of the compiled constructor are stored. Furthermore, by
+issuing this command you let the system know what file to load automatically
+if you use a new constructor. Abbreviations must start with a letter and then
+be followed by up to seven letters or digits. Any letters appearing in the
+abbreviation must be in uppercase.
+ 
+When used with the query argument, this command may be used to list the name
+associated with a particular abbreviation or the abbreviation for a
+constructor. If no abbreviation or name is given, the names and corresponding
+abbreviations for all constructors are listed.
+ 
+The following shows the abbreviation for the constructor List:
+ 
+)abbreviation query List
+ 
+The following shows the constructor name corresponding to the abbreviation
+NNI:
+ 
+)abbreviation query NNI
+ 
+The following lists all constructor names and their abbreviations.
+ 
+)abbreviation query
+ 
+To add an abbreviation for a constructor, use this command with category,
+domain or package. The following add abbreviations to the system for a
+category, domain and package, respectively:
+ 
+)abbreviation domain   SET Set
+)abbreviation category COMPCAT  ComplexCategory
+)abbreviation package  LIST2MAP ListToMap
+ 
+If the )quiet option is used, no output is displayed from this command. You
+would normally only define an abbreviation in a library source file. If this
+command is issued for a constructor that has already been loaded, the
+constructor will be reloaded next time it is referenced. In particular, you
+can use this command to force the automatic reloading of constructors.
+ 
+To remove an abbreviation, the remove argument is used. This is usually only
+used to correct a previous command that set an abbreviation for a constructor
+name. If, in fact, the abbreviation does exist, you are prompted for
+confirmation of the removal request. Either of the following commands will
+remove the abbreviation VECTOR2 and the constructor name VectorFunctions2
+from the system:
+ 
+)abbreviation remove VECTOR2
+)abbreviation remove VectorFunctions2
+ 
+Also See: 
+o )compile
+ 
+@
+
+\section{boot}
+<<boot>>=
+====================================================================
+A.3.  )boot
+====================================================================
+ 
+User Level Required:  development
+ 
+Command Syntax: 
+ 
+  -  )boot bootExpression
+ 
+Command Description: 
+ 
+This command is used by AXIOM system developers to execute expressions
+written in the BOOT language. For example,
+ 
+)boot times3(x) == 3*x
+ 
+creates and compiles the Lisp function ``times3'' obtained by translating the
+BOOT code.
+ 
+Also See: 
+o )fin
+o )lisp
+o )set
+o )system
+ 
+@
+
+\section{cd}
+<<cd>>=
+====================================================================
+A.4.  )cd
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  -  )cd directory
+ 
+Command Description: 
+ 
+This command sets the AXIOM working current directory. The current directory
+is used for looking for input files (for )read), AXIOM library source files
+(for )compile), saved history environment files (for )history )restore),
+compiled AXIOM library files (for )library), and files to edit (for )edit).
+It is also used for writing spool files (via )spool), writing history input
+files (via )history )write) and history environment files (via )history
+)save),and compiled AXIOM library files (via )compile).
+ 
+If issued with no argument, this command sets the AXIOM current directory to
+your home directory. If an argument is used, it must be a valid directory
+name. Except for the ``)'' at the beginning of the command, this has the same
+syntax as the operating system cd command.
+ 
+Also See: 
+o )compile
+o )edit
+o )history
+o )library
+o )read
+o )spool
+ 
+@
+
+\section{clear}
+<<clear>>=
+====================================================================
+A.6.  )clear
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )clear all
+  - )clear completely
+  - )clear properties all
+  - )clear properties  obj1 [obj2 ...]
+  - )clear value      all
+  - )clear value     obj1 [obj2 ...]
+  - )clear mode       all
+  - )clear mode      obj1 [obj2 ...]
+ 
+Command Description: 
+ 
+This command is used to remove function and variable declarations,
+definitions and values from the workspace. To empty the entire workspace and
+reset the step counter to 1, issue
+ 
+)clear all
+ 
+To remove everything in the workspace but not reset the step counter, issue
+ 
+)clear properties all
+ 
+To remove everything about the object x, issue
+ 
+)clear properties x
+ 
+To remove everything about the objects x, y and f, issue
+ 
+)clear properties x y f
+ 
+The word properties may be abbreviated to the single letter ``p''.
+ 
+)clear p all
+)clear p x
+)clear p x y f
+ 
+All definitions of functions and values of variables may be removed by either
+ 
+)clear value all
+)clear v all
+ 
+This retains whatever declarations the objects had. To remove definitions and
+values for the specific objects x, y and f, issue
+ 
+)clear value x y f
+)clear v x y f
+ 
+To remove the declarations of everything while leaving the definitions and
+values, issue
+ 
+)clear mode  all
+)clear m all
+ 
+To remove declarations for the specific objects x, y and f, issue
+ 
+)clear mode x y f
+)clear m x y f
+ 
+The )display names and )display properties commands may be used to see what
+is currently in the workspace.
+ 
+The command
+ 
+)clear completely
+ 
+does everything that )clear all does, and also clears the internal system
+function and constructor caches.
+ 
+Also See: 
+o )display
+o )history
+o )undo
+ 
+@
+
+\section{close}
+<<close>>=
+====================================================================
+A.5.  )close
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )close
+  - )close )quietly
+ 
+Command Description: 
+ 
+This command is used to close down interpreter client processes. Such
+processes are started by HyperDoc to run AXIOM examples when you click on
+their text. When you have finished examining or modifying the example and you
+do not want the extra window around anymore, issue
+ 
+)close
+ 
+to the AXIOM prompt in the window.
+ 
+If you try to close down the last remaining interpreter client process, AXIOM
+will offer to close down the entire AXIOM session and return you to the
+operating system by displaying something like
+ 
+   This is the last AXIOM session. Do you want to kill AXIOM?
+ 
+Type "y" (followed by the Return key) if this is what you had in mind. Type
+"n" (followed by the Return key) to cancel the command.
+ 
+You can use the )quietly option to force AXIOM to close down the interpreter
+client process without closing down the entire AXIOM session.
+ 
+Also See: 
+o )quit
+o )pquit
+ 
+@
+
+\section{compile}
+<<compile>>=
+====================================================================
+A.7.  )compile
+====================================================================
+ 
+User Level Required:  compiler
+ 
+Command Syntax: 
+ 
+  -  )compile
+  -  )compile fileName
+  -  )compile fileName.as
+  -  )compile directory/fileName.as
+  -  )compile fileName.ao
+  -  )compile directory/fileName.ao
+  -  )compile fileName.al
+  -  )compile directory/fileName.al
+  -  )compile fileName.lsp
+  -  )compile directory/fileName.lsp
+  -  )compile fileName.spad
+  -  )compile directory/fileName.spad
+  -  )compile fileName )new
+  -  )compile fileName )old
+  -  )compile fileName )translate
+  -  )compile fileName )quiet
+  -  )compile fileName )noquiet
+  -  )compile fileName )moreargs
+  -  )compile fileName )onlyargs
+  -  )compile fileName )break
+  -  )compile fileName )nobreak
+  -  )compile fileName )library
+  -  )compile fileName )nolibrary
+  -  )compile fileName )vartrace
+  -  )compile fileName )constructor nameOrAbbrev
+ 
+Command Description: 
+ 
+You use this command to invoke the new AXIOM library compiler or the old
+AXIOM system compiler. The )compile system command is actually a combination
+of AXIOM processing and a call to the AXIOM-XL compiler. It is performing
+double-duty, acting as a front-end to both the AXIOM-XL compiler and the old
+AXIOM system compiler. (The old AXIOM system compiler was written in Lisp and
+was an integral part of the AXIOM environment. The AXIOM-XL compiler is
+written in C and executed by the operating system when called from within
+AXIOM.)
+ 
+The command compiles files with file extensions .as, .ao and .al with the
+AXIOM-XL compiler and files with file extension .spad with the old AXIOM
+system compiler. It also can compile files with file extension .lsp. These
+are assumed to be Lisp files genererated by the AXIOM-XL compiler. If you
+omit the file extension, the command looks to see if you have specified the
+)new or )old option. If you have given one of these options, the
+corresponding compiler is used. Otherwise, the command first looks in the
+standard system directories for files with extension .as, .ao and .al and
+then files with extension .spad. The first file found has the appropriate
+compiler invoked on it. If the command cannot find a matching file, an error
+message is displayed and the command terminates.
+ 
+The )translate option is used to invoke a special version of the old system
+compiler that will translate a .spad file to a .as file. That is, the .spad
+file will be parsed and analyzed and a file using the new syntax will be
+created. By default, the .as file is created in the same directory as the
+.spad file. If that directory is not writable, the current directory is used.
+If the current directory is not writable, an error message is given and the
+command terminates. Note that )translate implies the )old option so the file
+extension can safely be omitted. If )translate is given, all other options
+are ignored. Please be aware that the translation is not necessarily one
+hundred percent complete or correct. You should attempt to compile the output
+with the AXIOM-XL compiler and make any necessary corrections.
+ 
+We now describe the options for the new AXIOM-XL compiler.
+ 
+The first thing )compile does is look for a source code filename among its
+arguments. Thus
+ 
+)compile mycode.as
+)compile /u/jones/as/mycode.as
+)compile mycode
+ 
+all invoke )compiler on the file /u/jones/as/mycode.as if the current AXIOM
+working directory is /u/jones/as. (Recall that you can set the working
+directory via the )cd command. If you don't set it explicitly, it is the
+directory from which you started AXIOM.)
+ 
+This is frequently all you need to compile your file. This simple command:
+ 
+  -  Invokes the AXIOM-XL compiler and produces Lisp output.
+  -  Calls the Lisp compiler if the AXIOM-XL compilation was
+  successful.
+  -  Use the )library command to tell AXIOM about
+  the contents of your compiled file and arrange to have those contents
+  loaded on demand.
+ 
+Should you not want the )library command automatically invoked, call )compile
+with the )nolibrary option. For example,
+ 
+)compile mycode.as )nolibrary
+ 
+The general description of AXIOM-XL command line arguments is in the AXIOM-XL
+documentation. The default options used by the )compile command can be viewed
+and set using the )set compiler args AXIOM system command. The current
+defaults are
+ 
+-O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom
+ 
+These options mean:
+ 
+  -  -O: perform all optimizations,
+  -  -Fasy: generate a .asy file,
+  -  -Fao: generate a .ao file,
+  -  -Flsp: generate a .lsp (Lisp)
+  file,
+  -  -laxiom: use the axiom library libaxiom.al,
+  -  -Mno-AXL_W_WillObsolete: do not display messages
+  about older generated files becoming obsolete, and
+  -  -DAxiom: define the global assertion Axiom so that the
+  AXIOM-XL libraries for generating stand-alone code are not accidentally
+  used with AXIOM.
+ 
+To supplement these default arguments, use the )moreargs option on )compile.
+For example,
+ 
+)compile mycode.as )moreargs "-v"
+ 
+uses the default arguments and appends the -v (verbose) argument flag. The
+additional argument specification must be enclosed in double quotes.
+ 
+To completely replace these default arguments for a particular use of
+)compile, use the )onlyargs option. For example,
+ 
+)compile mycode.as )onlyargs "-v -O"
+ 
+only uses the -v (verbose) and -O (optimize) arguments. The argument
+specification 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 )compile within
+your AXIOM session, use )set compiler args. For example, to use the above
+arguments for all compilations, issue
+ 
+)set compiler args "-v -O"
+ 
+Make sure you include the necessary -l and -Y arguments along with those
+needed for Lisp file creation. As above, the argument specification must be
+enclosed in double quotes.
+ 
+By default, the )library system command exposes all domains and categories it
+processes. This means that the AXIOM intepreter will consider those domains
+and categories when it is trying to resolve a reference to a function.
+Sometimes domains and categories should not be exposed. For example, a domain
+may just be used privately by another domain and may not be meant for
+top-level use. The )library command should still be used, though, so that the
+code will be loaded on demand. In this case, you should use the )nolibrary
+option on )compile and the )noexpose option in the )library command. For
+example,
+ 
+)compile mycode.as )nolibrary
+)library mycode )noexpose
+ 
+Once you have established your own collection of compiled code, you may find
+it handy to use the )dir option on the )library command. This causes )library
+to process all compiled code in the specified directory. For example,
+ 
+)library )dir /u/jones/as/quantum
+ 
+You must give an explicit directory after )dir, even if you want all compiled
+code in the current working directory processed.
+ 
+)library )dir .
+ 
+The )compile command works with several file extensions. We saw above what
+happens when it is invoked on a file with extension .as. A .ao file is a
+portable binary compiled version of a .as file, and )compile simply passes
+the .ao file onto AXIOM-XL. The generated Lisp file is compiled and )library
+is automatically called, just as if you had specified a .as file.
+ 
+A .al file is an archive file containing .ao files. The archive is created
+(on Unix systems) with the ar program. When )compile is given a .al file, it
+creates a directory whose name is based on that of the archive. For example,
+if you issue
+ 
+)compile mylib.al
+ 
+the directory mylib.axldir is created. All members of the archive are
+unarchived into the directory and )compile is called on each .ao file found.
+It is your responsibility to remove the directory and its contents, if you
+choose to do so.
+ 
+A .lsp file is a Lisp source file, presumably, in our context, generated by
+AXIOM-XL when called with the -Flsp option. When )compile is used with a .lsp
+file, the Lisp file is compiled and )library is called. You must also have
+present a .asy generated from the same source file.
+ 
+The following are descriptions of options for the old system compiler.
+ 
+You can compile category, domain, and package constructors contained in files
+with file extension .spad. You can compile individual constructors or every
+constructor in a file.
+ 
+The full filename is remembered between invocations of this command and )edit
+commands. The sequence of commands
+ 
+)compile matrix.spad
+)edit
+)compile
+ 
+will call the compiler, edit, and then call the compiler again on the file
+matrix.spad. If you do not specify a directory, the working current directory
+(see description of command )cd ) is searched for the file. If the file is
+not found, the standard system directories are searched.
+ 
+If you do not give any options, all constructors within a file are compiled.
+Each constructor should have an )abbreviation command in the file in which it
+is defined. We suggest that you place the )abbreviation commands at the top
+of the file in the order in which the constructors are defined. The list of
+commands serves as a table of contents for the file.
+ 
+The )library option causes directories containing the compiled code for each
+constructor to be created in the working current directory. The name of such
+a directory consists of the constructor abbreviation and the .NRLIB file
+extension. For example, the directory containing the compiled code for the
+MATRIX constructor is called MATRIX.NRLIB. The )nolibrary option says that
+such files should not be created. The default is )library. Note that the
+semantics of )library and )nolibrary for the new AXIOM-XL compiler and for
+the old system compiler are completely different.
+ 
+The )vartrace option causes the compiler to generate extra code for the
+constructor to support conditional tracing of variable assignments. (see
+description of command )trace ). Without this option, this code is suppressed
+and one cannot use the )vars option for the trace command.
+ 
+The )constructor option is used to specify a particular constructor to
+compile. All other constructors in the file are ignored. The constructor name
+or abbreviation follows )constructor. Thus either
+ 
+)compile matrix.spad )constructor RectangularMatrix
+ 
+or
+ 
+)compile matrix.spad )constructor RMATRIX
+ 
+compiles the RectangularMatrix constructor defined in matrix.spad.
+ 
+The )break and )nobreak options determine what the old system compiler does
+when it encounters an error. )break is the default and it indicates that
+processing should stop at the first error. The value of the )set break
+variable then controls what happens.
+ 
+Also See: 
+o )abbreviation
+o )edit
+o )library
+
+@ 
+\section{display}
+<<display>>=
+====================================================================
+A.8.  )display
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  -  )display all
+  -  )display properties
+  -  )display properties all
+  -  )display properties [obj1 [obj2 ...]]
+  -  )display value all
+  -  )display value [obj1 [obj2 ...]]
+  -  )display mode all
+  -  )display mode [obj1 [obj2 ...]]
+  -  )display names
+  -  )display operations opName
+ 
+Command Description: 
+ 
+This command is used to display the contents of the workspace and signatures
+of functions with a given name. (A signature gives the argument and return
+types of a function.) 
+ 
+The command
+ 
+)display names
+ 
+lists the names of all user-defined objects in the workspace. This is useful
+if you do not wish to see everything about the objects and need only be
+reminded of their names.
+ 
+The commands
+ 
+)display all
+)display properties
+)display properties all
+ 
+all do the same thing: show the values and types and declared modes of all
+variables in the workspace. If you have defined functions, their signatures
+and definitions will also be displayed.
+ 
+To show all information about a particular variable or user functions, for
+example, something named d, issue
+ 
+)display properties d
+ 
+To just show the value (and the type) of d, issue
+ 
+)display value d
+ 
+To just show the declared mode of d, issue
+ 
+)display mode d
+ 
+All modemaps for a given operation may be displayed by using )display
+operations. A modemap is a collection of information about a particular
+reference to an operation. This includes the types of the arguments and the
+return value, the location of the implementation and any conditions on the
+types. The modemap may contain patterns. The following displays the modemaps
+for the operation FromcomplexComplexCategory:
+ 
+)d op complex
+ 
+Also See: 
+o )clear
+o )history
+o )set
+o )show
+o )what
+ 
+@ 
+\section{edit}
+<<edit>>=
+====================================================================
+A.9.  )edit
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )edit [filename]
+ 
+Command Description: 
+ 
+This command is used to edit files. It works in conjunction with the )read
+and )compile commands to remember the name of the file on which you are
+working. By specifying the name fully, you can edit any file you wish. Thus
+ 
+)edit /u/julius/matrix.input
+ 
+will place you in an editor looking at the file /u/julius/matrix.input. By
+default, the editor is vi, but if you have an EDITOR shell environment
+variable defined, that editor will be used. When AXIOM is running under the X
+Window System, it will try to open a separate xterm running your editor if it
+thinks one is necessary. For example, under the Korn shell, if you issue
+ 
+export EDITOR=emacs
+ 
+then the emacs editor will be used by )edit.
+ 
+If you do not specify a file name, the last file you edited, read or compiled
+will be used. If there is no ``last file'' you will be placed in the editor
+editing an empty unnamed file.
+ 
+It is possible to use the )system command to edit a file directly. For
+example,
+ 
+)system emacs /etc/rc.tcpip
+ 
+calls emacs to edit the file.
+ 
+Also See: 
+o )system
+o )compile
+o )read
+ 
+
+@ 
+\section{fin}
+<<fin>>=
+====================================================================
+A.10.  )fin
+====================================================================
+ 
+User Level Required:  development
+ 
+Command Syntax: 
+ 
+  -  )fin
+ 
+Command Description: 
+ 
+This command is used by AXIOM developers to leave the AXIOM system and return
+to the underlying Lisp system. To return to AXIOM, issue the ``(|spad|)''
+function call to Lisp.
+ 
+Also See: 
+o )pquit
+o )quit
+ 
+
+@ 
+\section{frame}
+<<frame>>=
+====================================================================
+A.11.  )frame
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )frame  new  frameName
+  - )frame  drop  [frameName]
+  - )frame  next
+  - )frame  last
+  - )frame  names
+  - )frame  import frameName [objectName1 [objectName2 ...]]
+  - )set message frame on | off
+  - )set message prompt frame
+ 
+Command Description: 
+ 
+A frame can be thought of as a logical session within the physical session
+that you get when you start the system. You can have as many frames as you
+want, within the limits of your computer's storage, paging space, and so on.
+Each frame has its own step number, environment and history. You can have a
+variable named a in one frame and it will have nothing to do with anything
+that might be called a in any other frame.
+ 
+Some frames are created by the HyperDoc program and these can have pretty
+strange names, since they are generated automatically. To find out the names
+of all frames, issue
+ 
+)frame names
+ 
+It will indicate the name of the current frame.
+ 
+You create a new frame ``quark'' by issuing
+ 
+)frame new quark
+ 
+The history facility can be turned on by issuing either )set history on or
+)history )on. If the history facility is on and you are saving history
+information in a file rather than in the AXIOM environment then a history
+file with filename quark.axh will be created as you enter commands. If you
+wish to go back to what you were doing in the ``initial'' frame, use
+ 
+)frame next
+ 
+or
+ 
+)frame last
+ 
+to cycle through the ring of available frames to get back to ``initial''.
+ 
+If you want to throw away a frame (say ``quark''), issue
+ 
+)frame drop quark
+ 
+If you omit the name, the current frame is dropped.
+ 
+If you do use frames with the history facility on and writing to a file, you
+may want to delete some of the older history files. These are directories, so
+you may want to issue a command like rm -r quark.axh to the operating system.
+ 
+You can bring things from another frame by using )frame import. For example,
+to bring the f and g from the frame ``quark'' to the current frame, issue
+ 
+)frame import quark f g
+ 
+If you want everything from the frame ``quark'', issue
+ 
+)frame import quark
+ 
+You will be asked to verify that you really want everything.
+ 
+There are two )set flags to make it easier to tell where you are.
+ 
+)set message frame on | off
+ 
+will print more messages about frames when it is set on. By default, it is
+off.
+ 
+)set message prompt frame
+ 
+will give a prompt that looks like
+ 
+initial (1) ->
+ 
+when you start up. In this case, the frame name and step make up the prompt.
+ 
+Also See: 
+o )history
+o )set
+ 
+@ 
+\section{help}
+<<help>>=
+====================================================================
+A.12.  )help
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )help
+  - )help commandName
+ 
+Command Description: 
+ 
+This command displays help information about system commands. If you issue
+ 
+)help
+ 
+then this very text will be shown. You can also give the name or abbreviation
+of a system command to display information about it. For example,
+ 
+)help clear
+ 
+will display the description of the )clear system command.
+ 
+All this material is available in the AXIOM User Guide and in HyperDoc. In
+HyperDoc, choose the Commands item from the Reference menu.
+ 
+====================================================================
+A.1.  Introduction
+====================================================================
+ 
+ 
+System commands are used to perform AXIOM environment management. Among the
+commands are those that display what has been defined or computed, set up
+multiple logical AXIOM environments (frames), clear definitions, read files
+of expressions and commands, show what functions are available, and terminate
+AXIOM.
+ 
+Some commands are restricted: the commands
+ 
+)set userlevel interpreter
+)set userlevel compiler
+)set userlevel development
+ 
+set the user-access level to the three possible choices. All commands are
+available at development level and the fewest are available at interpreter
+level. The default user-level is interpreter. In addition to the )set command
+(discussed in description of command )set ) you can use the HyperDoc settings
+facility to change the user-level. Click on [Settings] here to immediately go
+to the settings facility. 
+ 
+Each command listing begins with one or more syntax pattern descriptions plus
+examples of related commands. The syntax descriptions are intended to be easy
+to read and do not necessarily represent the most compact way of specifying
+all possible arguments and options; the descriptions may occasionally be
+redundant.
+ 
+All system commands begin with a right parenthesis which should be in the
+first available column of the input line (that is, immediately after the
+input prompt, if any). System commands may be issued directly to AXIOM or be
+included in .input files.
+ 
+A system command argument is a word that directly follows the command name
+and is not followed or preceded by a right parenthesis. A system command
+option follows the system command and is directly preceded by a right
+parenthesis. Options may have arguments: they directly follow the option.
+This example may make it easier to remember what is an option and what is an
+argument:
+ 
+         )syscmd arg1 arg2 )opt1 opt1arg1 opt1arg2 )opt2 opt2arg1 ...
+ 
+In the system command descriptions, optional arguments and options are
+enclosed in brackets (``['' and ``]''). If an argument or option name is in
+italics, it is meant to be a variable and must have some actual value
+substituted for it when the system command call is made. For example, the
+syntax pattern description
+ 
+)read fileName [)quietly]
+ 
+would imply that you must provide an actual file name for fileName but need
+not use the )quietly option. Thus
+ 
+)read matrix.input
+ 
+is a valid instance of the above pattern.
+ 
+System command names and options may be abbreviated and may be in upper or
+lower case. The case of actual arguments may be significant, depending on the
+particular situation (such as in file names). System command names and
+options may be abbreviated to the minimum number of starting letters so that
+the name or option is unique. Thus
+ 
+)s Integer
+ 
+is not a valid abbreviation for the )set command, because both )set and )show
+begin with the letter ``s''. Typically, two or three letters are sufficient
+for disambiguating names. In our descriptions of the commands, we have used
+no abbreviations for either command names or options.
+ 
+In some syntax descriptions we use a vertical line ``|'' to indicate that you
+must specify one of the listed choices. For example, in
+ 
+)set output fortran on | off
+ 
+only on and off are acceptable words for following boot. We also sometimes
+use ``...'' to indicate that additional arguments or options of the listed
+form are allowed. Finally, in the syntax descriptions we may also list the
+syntax of related commands.
+ 
+@ 
+\section{history}
+<<history>>=
+====================================================================
+A.13.  )history
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )history )on
+  - )history )off
+  - )history )write historyInputFileName
+  - )history )show [n] [both]
+  - )history )save savedHistoryName
+  - )history )restore [savedHistoryName]
+  - )history )reset
+  - )history )change n
+  - )history )memory
+  - )history )file
+  - %
+  - %%(n)
+  - )set history on | off
+ 
+Command Description: 
+ 
+The history facility within AXIOM allows you to restore your environment to
+that of another session and recall previous computational results. Additional
+commands allow you to review previous input lines and to create an .input
+file of the lines typed to AXIOM.
+ 
+AXIOM saves your input and output if the history facility is turned on (which
+is the default). This information is saved if either of
+ 
+)set history on
+)history )on
+ 
+has been issued. Issuing either
+ 
+)set history off
+)history )off
+ 
+will discontinue the recording of information.
+ 
+Whether the facility is disabled or not, the value of % in AXIOM always
+refers to the result of the last computation. If you have not yet entered
+anything, % evaluates to an object of type Variable('%). The function %% may
+be used to refer to other previous results if the history facility is
+enabled. In that case, %%(n) is the output from step n if n > 0. If n < 0,
+the step is computed relative to the current step. Thus %%(-1) is also the
+previous step, %%(-2), is the step before that, and so on. If an invalid step
+number is given, AXIOM will signal an error.
+ 
+The environment information can either be saved in a file or entirely in
+memory (the default). Each frame ( description of command )frame ) has its
+own history database. When it is kept in a file, some of it may also be kept
+in memory for efficiency. When the information is saved in a file, the name
+of the file is of the form FRAME.axh where ``FRAME'' is the name of the
+current frame. The history file is placed in the current working directory
+(see description of command )cd ). Note that these history database files are
+not text files (in fact, they are directories themselves), and so are not in
+human-readable format.
+ 
+The options to the )history command are as follows:
+ 
+  )change n
+    will set the number of steps that are saved in memory to n. This option
+    only has effect when the history data is maintained in a file. If you
+    have issued )history )memory (or not changed the default) there is no
+    need to use )history )change.
+ 
+  )on
+    will start the recording of information. If the workspace is not empty,
+    you will be asked to confirm this request. If you do so, the workspace
+    will be cleared and history data will begin being saved. You can also
+    turn the facility on by issuing )set history on.
+ 
+  )off
+    will stop the recording of information. The )history )show command will
+    not work after issuing this command. Note that this command may be issued
+    to save time, as there is some performance penalty paid for saving the
+    environment data. You can also turn the facility off by issuing )set
+    history off.
+ 
+  )file
+    indicates that history data should be saved in an external file on disk.
+ 
+  )memory
+    indicates that all history data should be kept in memory rather than
+    saved in a file. Note that if you are computing with very large objects
+    it may not be practical to kept this data in memory.
+ 
+  )reset
+    will flush the internal list of the most recent workspace calculations so
+    that the data structures may be garbage collected by the underlying Lisp
+    system. Like )history )change, this option only has real effect when
+    history data is being saved in a file.
+ 
+  )restore [savedHistoryName]
+    completely clears the environment and restores it to a saved session, if
+    possible. The )save option below allows you to save a session to a file
+    with a given name. If you had issued )history )save jacobi the command
+    )history )restore jacobi would clear the current workspace and load the
+    contents of the named saved session. If no saved session name is
+    specified, the system looks for a file called last.axh.
+ 
+  )save savedHistoryName
+    is used to save a snapshot of the environment in a file. This file is
+    placed in the current working directory (see description of command )cd
+    ). Use )history )restore to restore the environment to the state
+    preserved in the file. This option also creates an input file containing
+    all the lines of input since you created the workspace frame (for
+    example, by starting your AXIOM session) or last did a )clear all or
+    )clear completely.
+ 
+  )show [n] [both]
+    can show previous input lines and output results. )show will display up
+    to twenty of the last input lines (fewer if you haven't typed in twenty
+    lines). )show n will display up to n of the last input lines. )show both
+    will display up to five of the last input lines and output results. )show
+    n both will display up to n of the last input lines and output results.
+ 
+  )write historyInputFile
+    creates an .input file with the input lines typed since the start of the
+    session/frame or the last )clear all or )clear completely. If
+    historyInputFileName does not contain a period (``.'') in the filename,
+    .input is appended to it. For example, )history )write chaos and )history
+    )write chaos.input both write the input lines to a file called
+    chaos.input in your current working directory. If you issued one or more
+    )undo commands, )history )write eliminates all input lines backtracked
+    over as a result of )undo. You can edit this file and then use )read to
+    have AXIOM process the contents.
+ 
+Also See: 
+o )frame
+o )read
+o )set
+o )undo
+ 
+@ 
+
+\section{language}
+<<language>>=
+The Axiom Interactive Language has the following features.
+More information is available by typing
+  )help feature
+
+@
+
+\section{library}
+<<library>>=
+====================================================================
+A.14.  )library
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )library libName1  [libName2 ...]
+  - )library )dir dirName
+  - )library )only objName1  [objlib2 ...]
+  - )library )noexpose
+ 
+Command Description: 
+ 
+This command replaces the )load system command that was available in AXIOM
+releases before version 2.0. The )library command makes available to AXIOM
+the compiled objects in the libraries listed.
+ 
+For example, if you )compile dopler.as in your home directory, issue )library
+dopler to have AXIOM look at the library, determine the category and domain
+constructors present, update the internal database with various properties of
+the constructors, and arrange for the constructors to be automatically loaded
+when needed. If the )noexpose option has not been given, the constructors
+will be exposed (that is, available) in the current frame.
+ 
+If you compiled a file with the old system compiler, you will have an NRLIB
+present, for example, DOPLER.NRLIB, where DOPLER is a constructor
+abbreviation. The command )library DOPLER will then do the analysis and
+database updates as above.
+ 
+To tell the system about all libraries in a directory, use )library )dir
+dirName where dirName is an explicit directory. You may specify ``.'' as the
+directory, which means the current directory from which you started the
+system or the one you set via the )cd command. The directory name is required.
+ 
+You may only want to tell the system about particular constructors within a
+library. In this case, use the )only option. The command )library dopler
+)only Test1 will only cause the Test1 constructor to be analyzed, autoloaded,
+etc..
+ 
+Finally, each constructor in a library are usually automatically exposed when
+the )library command is used. Use the )noexpose option if you not want them
+exposed. At a later time you can use )set expose add constructor to expose
+any hidden constructors.
+ 
+Note for AXIOM beta testers: At various times this command was called )local
+and )with before the name )library became the official name.
+ 
+Also See: 
+o )cd
+o )compile
+o )frame
+o )set
+ 
+@ 
+\section{lisp}
+<<lisp>>=
+====================================================================
+A.15.  )lisp
+====================================================================
+ 
+User Level Required:  development
+ 
+Command Syntax: 
+ 
+  -  )lisp [lispExpression]
+ 
+Command Description: 
+ 
+This command is used by AXIOM system developers to have single expressions
+evaluated by the Lisp system on which AXIOM is built. The lispExpression is
+read by the Lisp reader and evaluated. If this expression is not complete
+(unbalanced parentheses, say), the reader will wait until a complete
+expression is entered.
+ 
+Since this command is only useful for evaluating single expressions, the )fin
+command may be used to drop out of AXIOM into Lisp.
+ 
+Also See: 
+o )system
+o )boot
+o )fin
+ 
+@ 
+\section{load}
+<<load>>=
+====================================================================
+A.16.  )load
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Description: 
+ 
+This command is obsolete. Use )library instead.
+ 
+@ 
+\section{ltrace}
+<<ltrace>>=
+====================================================================
+A.17.  )ltrace
+====================================================================
+ 
+User Level Required:  development
+ 
+Command Syntax: 
+ 
+This command has the same arguments as options as the )trace command.
+ 
+Command Description: 
+ 
+This command is used by AXIOM system developers to trace Lisp or BOOT
+functions. It is not supported for general use.
+ 
+Also See: 
+o )boot
+o )lisp
+o )trace
+ 
+@ 
+\section{nclef}
+<<nclef>>=
+
+Entering printable keys generally inserts new text into the buffer (unless
+in overwrite mode, see below).  Other special keys can be used to modify
+the text in the buffer.  In the description of the keys below, ^n means
+Control-n, or holding the CONTROL key down while pressing "n".  Errors
+will ring the terminal bell.
+
+^A/^E	: Move cursor to beginning/end of the line.
+^F/^B   : Move cursor forward/backward one character.
+^D	: Delete the character under the cursor.
+^H, DEL : Delete the character to the left of the cursor.
+^K	: Kill from the cursor to the end of line.
+^L	: Redraw current line.
+^O	: Toggle overwrite/insert mode. Initially in insert mode. Text
+	  added in overwrite mode (including yanks) overwrite
+	  existing text, while insert mode does not overwrite.
+^P/^N   : Move to previous/next item on history list.
+^R/^S   : Perform incremental reverse/forward search for string on
+	  the history list.  Typing normal characters adds to the current
+	  search string and searches for a match. Typing ^R/^S marks
+	  the start of a new search, and moves on to the next match.
+	  Typing ^H or DEL deletes the last character from the search 
+	  string, and searches from the starting location of the last search.  
+	  Therefore, repeated DEL's appear to unwind to the match nearest 
+	  the point at which the last ^R or ^S was typed.  If DEL is 
+	  repeated until the search string is empty the search location 
+	  begins from the start of the history list.  Typing ESC or 
+	  any other editing character accepts the current match and 
+	  loads it into the buffer, terminating the search.
+^T	: Toggle the characters under and to the left of the cursor.
+^Y	: Yank previously killed text back at current location.  Note that
+	  this will overwrite or insert, depending on the current mode.
+^U      : Show help (this text).
+TAB	: Perform command completion based on word to the left of the cursor. 
+          Words are deemed to contain only the alphanumeric and the % ! ? _  
+          characters.
+NL, CR  : returns current buffer to the program.
+
+DOS and ANSI terminal arrow key sequences are recognized, and act like:
+
+  up    : same as ^P
+  down  : same as ^N
+  left  : same as ^B
+  right : same as ^F
+
+@ 
+\section{pquit}
+<<pquit>>=
+====================================================================
+A.18.  )pquit
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )pquit
+ 
+Command Description: 
+ 
+This command is used to terminate AXIOM and return to the operating system.
+Other than by redoing all your computations or by using the )history )restore
+command to try to restore your working environment, you cannot return to
+AXIOM in the same state.
+ 
+)pquit differs from the )quit in that it always asks for confirmation that
+you want to terminate AXIOM (the ``p'' is for ``protected''). When you enter
+the )pquit command, AXIOM responds
+ 
+      Please enter y or yes if you really want to leave the interactive 
+                environment and return to the operating system:
+ 
+If you respond with y or yes, you will see the message
+ 
+            You are now leaving the AXIOM interactive environment. 
+    Issue the command axiom to the operating system to start a new session.
+ 
+and AXIOM will terminate and return you to the operating system (or the
+environment from which you invoked the system). If you responded with
+something other than y or yes, then the message
+ 
+        You have chosen to remain in the AXIOM interactive environment.
+ 
+will be displayed and, indeed, AXIOM would still be running.
+ 
+Also See: 
+o )fin
+o )history
+o )close
+o )quit
+o )system
+ 
+@ 
+\section{quit}
+<<quit>>=
+====================================================================
+A.19.  )quit
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )quit
+  - )set quit protected | unprotected
+ 
+Command Description: 
+ 
+This command is used to terminate AXIOM and return to the operating system.
+Other than by redoing all your computations or by using the )history )restore
+command to try to restore your working environment, you cannot return to
+AXIOM in the same state.
+ 
+)quit differs from the )pquit in that it asks for confirmation only if the
+command
+ 
+)set quit protected
+ 
+has been issued. Otherwise, )quit will make AXIOM terminate and return you to
+the operating system (or the environment from which you invoked the system).
+ 
+The default setting is )set quit protected so that )quit and )pquit behave in
+the same way. If you do issue
+ 
+)set quit unprotected
+ 
+we suggest that you do not (somehow) assign )quit to be executed when you
+press, say, a function key.
+ 
+Also See: 
+o )fin
+o )history
+o )close
+o )pquit
+o )system
+ 
+@ 
+\section{read}
+<<read>>=
+====================================================================
+A.20.  )read
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  -  )read [fileName]
+  -  )read [fileName] [)quiet] [)ifthere]
+ 
+Command Description: 
+ 
+This command is used to read .input files into AXIOM. The command
+ 
+)read matrix.input
+ 
+will read the contents of the file matrix.input into AXIOM. The ``.input''
+file extension is optional. See the AXIOM User Guide index for more
+information about .input files.
+ 
+This command remembers the previous file you edited, read or compiled. If you
+do not specify a file name, the previous file will be read.
+ 
+The )ifthere option checks to see whether the .input file exists. If it does
+not, the )read command does nothing. If you do not use this option and the
+file does not exist, you are asked to give the name of an existing .input
+file.
+ 
+The )quiet option suppresses output while the file is being read.
+ 
+Also See: 
+o )compile
+o )edit
+o )history
+ 
+@ 
+\section{savesystem}
+<<savesystem>>=
+AXIOM Help Information. Section numbers refer to the book 
+AXIOM: The System for Scientific Computation. 
+ 
+====================================================================
+A.8.  )savesystem
+====================================================================
+ 
+ 
+ 
+ 
+ 
+User Level Required:  interpreter
+ 
+ 
+Command Syntax: 
+ 
+  - )savesystem filename
+ 
+Command Description: 
+ 
+ This command is used to save an AXIOM image to disk.  This creates an
+executable file which, when started, has everything loaded into it
+that was there when the image was saved.  Thus, after executing commands
+which cause the loading of some packages, the command:
+ 
+)savesystem /tmp/savesys
+
+will create an image that can be restarted  with the UNIX command:
+
+axiom -ws /tmp/savesys
+
+This new system will not need to reload the packages and domains that
+were already loaded when the system was saved.
+
+There is currently a restriction that only systems started with the 
+command "AXIOMsys" may be saved.
+
+@ 
+\section{set}
+<<set>>=
+====================================================================
+A.21.  )set
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  -  )set
+  -  )set label1 [... labelN]
+  -  )set label1 [... labelN] newValue
+ 
+Command Description: 
+ 
+The )set command is used to view or set system variables that control what
+messages are displayed, the type of output desired, the status of the history
+facility, the way AXIOM user functions are cached, and so on. Since this
+collection is very large, we will not discuss them here. Rather, we will show
+how the facility is used. We urge you to explore the )set options to
+familiarize yourself with how you can modify your AXIOM working environment.
+There is a HyperDoc version of this same facility available from the main
+HyperDoc menu. Click [here] to go to it. 
+ 
+The )set command is command-driven with a menu display. It is
+tree-structured. To see all top-level nodes, issue )set by itself.
+ 
+)set
+ 
+Variables with values have them displayed near the right margin. Subtrees of
+selections have ``...'' displayed in the value field. For example, there are
+many kinds of messages, so issue )set message to see the choices.
+ 
+)set message
+ 
+The current setting for the variable that displays whether computation times
+are displayed is visible in the menu displayed by the last command. To see
+more information, issue
+ 
+)set message time
+ 
+This shows that time printing is on now. To turn it off, issue
+ 
+)set message time off
+ 
+As noted above, not all settings have so many qualifiers. For example, to
+change the )quit command to being unprotected (that is, you will not be
+prompted for verification), you need only issue
+ 
+)set quit unprotected
+ 
+Also See: 
+o )quit
+ 
+@ 
+\section{show}
+<<show>>=
+====================================================================
+A.22.  )show
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )show nameOrAbbrev
+  - )show nameOrAbbrev )operations
+  - )show nameOrAbbrev )attributes
+ 
+Command Description: 
+This command displays information about AXIOM domain, package and category
+constructors. If no options are given, the )operations option is assumed. For
+example,
+ 
+)show POLY
+)show POLY )operations
+)show Polynomial
+)show Polynomial )operations
+ 
+each display basic information about the Polynomial domain constructor and
+then provide a listing of operations. Since Polynomial requires a Ring (for
+example, Integer) as argument, the above commands all refer to a unspecified
+ring R. In the list of operations, $ means Polynomial(R).
+ 
+The basic information displayed includes the signature of the constructor
+(the name and arguments), the constructor abbreviation, the exposure status
+of the constructor, and the name of the library source file for the
+constructor.
+ 
+If operation information about a specific domain is wanted, the full or
+abbreviated domain name may be used. For example,
+ 
+)show POLY INT
+)show POLY INT )operations
+)show Polynomial Integer
+)show Polynomial Integer )operations
+ 
+are among the combinations that will display the operations exported by the
+domain Polynomial(Integer) (as opposed to the general domain constructor
+Polynomial). Attributes may be listed by using the )attributes option.
+ 
+Also See: 
+o )display
+o )set
+o )what
+ 
+@ 
+\section{spool}
+<<spool>>=
+====================================================================
+A.23.  )spool
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )spool [fileName]
+  - )spool
+ 
+Command Description: 
+ 
+This command is used to save (spool) all AXIOM input and output into a file,
+called a spool file. You can only have one spool file active at a time. To
+start spool, issue this command with a filename. For example,
+ 
+)spool integrate.out
+ 
+To stop spooling, issue )spool with no filename.
+ 
+If the filename is qualified with a directory, then the output will be placed
+in that directory. If no directory information is given, the spool file will
+be placed in the current directory. The current directory is the directory
+from which you started AXIOM or is the directory you specified using the )cd
+command.
+ 
+Also See: 
+o )cd
+ 
+@ 
+\section{synonym}
+<<synonym>>=
+====================================================================
+A.24.  )synonym
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )synonym
+  - )synonym synonym fullCommand
+  - )what synonyms
+ 
+Command Description: 
+ 
+This command is used to create short synonyms for system command expressions.
+For example, the following synonyms might simplify commands you often use.
+ 
+)synonym save         history )save
+)synonym restore      history )restore
+)synonym mail         system mail
+)synonym ls           system ls
+)synonym fortran      set output fortran
+ 
+Once defined, synonyms can be used in place of the longer command
+expressions. Thus
+ 
+)fortran on
+ 
+is the same as the longer
+ 
+)set fortran output on
+ 
+To list all defined synonyms, issue either of
+ 
+)synonyms
+)what synonyms
+ 
+To list, say, all synonyms that contain the substring ``ap'', issue
+ 
+)what synonyms ap
+ 
+Also See: 
+o )set
+o )what
+ 
+@ 
+\section{system}
+<<system>>=
+====================================================================
+A.25.  )system
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )system cmdExpression
+ 
+Command Description: 
+ 
+This command may be used to issue commands to the operating system while
+remaining in AXIOM. The cmdExpression is passed to the operating system for
+execution.
+ 
+To get an operating system shell, issue, for example, )system sh. When you
+enter the key combination, Ctrl-D (pressing and holding the Ctrl key and then
+pressing the D key) the shell will terminate and you will return to AXIOM. We
+do not recommend this way of creating a shell because Lisp may field some
+interrupts instead of the shell. If possible, use a shell running in another
+window.
+ 
+If you execute programs that misbehave you may not be able to return to
+AXIOM. If this happens, you may have no other choice than to restart AXIOM
+and restore the environment via )history )restore, if possible.
+ 
+Also See: 
+o )boot
+o )fin
+o )lisp
+o )pquit
+o )quit
+ 
+@ 
+\section{trace}
+<<trace>>=
+====================================================================
+A.26.  )trace
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )trace
+  - )trace )off
+ 
+  - )trace function [options]
+  - )trace constructor [options]
+  - )trace domainOrPackage [options]
+ 
+where options can be one or more of
+ 
+  - )after S-expression
+  - )before S-expression
+  - )break after
+  - )break before
+  - )cond S-expression
+  - )count
+  - )count n
+  - )depth n
+  - )local op1 [... opN]
+  - )nonquietly
+  - )nt
+  - )off
+  - )only listOfDataToDisplay
+  - )ops
+  - )ops op1 [... opN ]
+  - )restore
+  - )stats
+  - )stats reset
+  - )timer
+  - )varbreak
+  - )varbreak var1 [... varN ]
+  - )vars
+  - )vars var1 [... varN ]
+  - )within executingFunction
+ 
+Command Description: 
+ 
+This command is used to trace the execution of functions that make up the
+AXIOM system, functions defined by users, and functions from the system
+library. Almost all options are available for each type of function but
+exceptions will be noted below.
+ 
+To list all functions, constructors, domains and packages that are traced,
+simply issue
+ 
+)trace
+ 
+To untrace everything that is traced, issue
+ 
+)trace )off
+ 
+When a function is traced, the default system action is to display the
+arguments to the function and the return value when the function is exited.
+Note that if a function is left via an action such as a THROW, no return
+value will be displayed. Also, optimization of tail recursion may decrease
+the number of times a function is actually invoked and so may cause less
+trace information to be displayed. Other information can be displayed or
+collected when a function is traced and this is controlled by the various
+options. Most options will be of interest only to AXIOM system developers. If
+a domain or package is traced, the default action is to trace all functions
+exported.
+ 
+Individual interpreter, lisp or boot functions can be traced by listing their
+names after )trace. Any options that are present must follow the functions to
+be traced.
+ 
+)trace f
+ 
+traces the function f. To untrace f, issue
+ 
+)trace f )off
+ 
+Note that if a function name contains a special character, it will be
+necessary to escape the character with an underscore
+ 
+)trace _/D_,1
+ 
+To trace all domains or packages that are or will be created from a
+particular constructor, give the constructor name or abbreviation after
+)trace.
+ 
+)trace MATRIX
+)trace List Integer
+ 
+The first command traces all domains currently instantiated with Matrix. If
+additional domains are instantiated with this constructor (for example, if
+you have used Matrix(Integer) and Matrix(Float)), they will be automatically
+traced. The second command traces List(Integer). It is possible to trace
+individual functions in a domain or package. See the )ops option below.
+ 
+The following are the general options for the )trace command.
+ 
+  )break after
+    causes a Lisp break loop to be entered after exiting the traced function.
+ 
+  )break before
+    causes a Lisp break loop to be entered before entering the traced
+    function.
+ 
+  )break
+    is the same as )break before.
+ 
+  )count
+    causes the system to keep a count of the number of times the traced
+    function is entered. The total can be displayed with )trace )stats and
+    cleared with )trace )stats reset.
+ 
+  )count n
+    causes information about the traced function to be displayed for the
+    first n executions. After the nth execution, the function is untraced.
+ 
+  )depth n
+    causes trace information to be shown for only n levels of recursion of
+    the traced function. The command
+ 
+    )trace fib )depth 10
+ 
+    will cause the display of only 10 levels of trace information for the
+    recursive execution of a user function fib.
+ 
+  )math
+    causes the function arguments and return value to be displayed in the
+    AXIOM monospace two-dimensional math format.
+ 
+  )nonquietly
+    causes the display of additional messages when a function is traced.
+ 
+  )nt
+    This suppresses all normal trace information. This option is useful if
+    the )count or )timer options are used and you are interested in the
+    statistics but not the function calling information.
+ 
+  )off
+    causes untracing of all or specific functions. Without an argument, all
+    functions, constructors, domains and packages are untraced. Otherwise,
+    the given functions and other objects are untraced. To immediately
+    retrace the untraced functions, issue )trace )restore.
+ 
+  )only listOfDataToDisplay
+    causes only specific trace information to be shown. The items are listed
+    by using the following abbreviations:
+ 
+    a        display all arguments
+    v        display return value
+    1        display first argument
+    2        display second argument
+    15       display the 15th argument, and so on
+ 
+  )restore
+    causes the last untraced functions to be retraced. If additional options
+    are present, they are added to those previously in effect.
+ 
+  )stats
+    causes the display of statistics collected by the use of the )count and
+    )timer options.
+ 
+  )stats reset
+    resets to 0 the statistics collected by the use of the )count and )timer
+    options.
+ 
+  )timer
+    causes the system to keep a count of execution times for the traced
+    function. The total can be displayed with )trace )stats and cleared with
+    )trace )stats reset.
+ 
+  )varbreak var1 [... varN]
+    causes a Lisp break loop to be entered after the assignment to any of the
+    listed variables in the traced function.
+ 
+  )vars
+    causes the display of the value of any variable after it is assigned in
+    the traced function. Note that library code must have been compiled (see
+    description of command )compile ) using the )vartrace option in order to
+    support this option.
+ 
+  )vars var1 [... varN]
+    causes the display of the value of any of the specified variables after
+    they are assigned in the traced function. Note that library code must
+    have been compiled (see description of command )compile ) using the
+    )vartrace option in order to support this option.
+ 
+  )within executingFunction
+    causes the display of trace information only if the traced function is
+    called when the given executingFunction is running.
+ 
+The following are the options for tracing constructors, domains and packages.
+ 
+  )local [op1 [... opN]]
+    causes local functions of the constructor to be traced. Note that to
+    untrace an individual local function, you must use the fully qualified
+    internal name, using the escape character _ before the semicolon.
+ 
+    )trace FRAC )local
+    )trace FRAC_;cancelGcd )off
+ 
+  )ops op1 [... opN]
+    By default, all operations from a domain or package are traced when the
+    domain or package is traced. This option allows you to specify that only
+    particular operations should be traced. The command
+ 
+    )trace Integer )ops min max _+ _-
+ 
+    traces four operations from the domain Integer. Since + and - are special
+    characters, it is necessary to escape them with an underscore.
+ 
+Also See: 
+o )boot
+o )lisp
+o )ltrace
+ 
+@ 
+\section{undo}
+<<undo>>=
+====================================================================
+A.27.  )undo
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )undo
+  - )undo integer
+  - )undo integer [option]
+  - )undo )redo
+ 
+where option is one of
+ 
+  - )after
+  - )before
+ 
+Command Description: 
+ 
+This command is used to restore the state of the user environment to an
+earlier point in the interactive session. The argument of an )undo is an
+integer which must designate some step number in the interactive session.
+ 
+)undo n
+)undo n )after
+ 
+These commands return the state of the interactive environment to that
+immediately after step n. If n is a positive number, then n refers to step
+nummber n. If n is a negative number, it refers to the nth previous command
+(that is, undoes the effects of the last -n commands).
+ 
+A )clear all resets the )undo facility. Otherwise, an )undo undoes the effect
+of )clear with options properties, value, and mode, and that of a previous
+undo. If any such system commands are given between steps n and n + 1 (n >
+0), their effect is undone for )undo m for any 0 < m <= n .
+ 
+The command )undo is equivalent to )undo -1 (it undoes the effect of the
+previous user expression). The command )undo 0 undoes any of the above system
+commands issued since the last user expression.
+ 
+)undo n )before
+ 
+This command returns the state of the interactive environment to that
+immediately before step n. Any )undo or )clear system commands given before
+step n will not be undone.
+ 
+)undo )redo
+ 
+This command reads the file redo.input. created by the last )undo command.
+This file consists of all user input lines, excluding those backtracked over
+due to a previous )undo.
+ 
+Also See: 
+o )history
+The command )history )write will eliminate the ``undone'' command lines of
+your program.
+ 
+@ 
+\section{what}
+<<what>>=
+====================================================================
+A.28.  )what
+====================================================================
+ 
+User Level Required:  interpreter
+ 
+Command Syntax: 
+ 
+  - )what categories pattern1 [pattern2 ...]
+  - )what commands   pattern1 [pattern2 ...]
+  - )what domains    pattern1 [pattern2 ...]
+  - )what operations pattern1 [pattern2 ...]
+  - )what packages   pattern1 [pattern2 ...]
+  - )what synonym    pattern1 [pattern2 ...]
+  - )what things     pattern1 [pattern2 ...]
+  - )apropos         pattern1 [pattern2 ...]
+ 
+Command Description: 
+ 
+This command is used to display lists of things in the system. The patterns
+are all strings and, if present, restrict the contents of the lists. Only
+those items that contain one or more of the strings as substrings are
+displayed. For example,
+ 
+)what synonym
+ 
+displays all command synonyms,
+ 
+)what synonym ver
+ 
+displays all command synonyms containing the substring ``ver'',
+ 
+)what synonym ver pr
+ 
+displays all command synonyms containing the substring ``ver'' or the
+substring ``pr''. Output similar to the following will be displayed
+ 
+---------------- System Command Synonyms -----------------
+ 
+
+user-defined synonyms satisfying patterns:
+      ver pr
+ 
+
+  )apr ........................... )what things
+  )apropos ....................... )what things
+  )prompt ........................ )set message prompt
+  )version ....................... )lisp *yearweek*
+ 
+Several other things can be listed with the )what command:
+ 
+  categories displays a list of category constructors.
+  commands  displays a list of  system commands available  at your
+    user-level. Your user-level is set via the )set userlevel command. To get
+    a description of a particular command, such as ``)what'', issue )help
+    what.
+  domains   displays a list of domain constructors.
+  operations displays a list of operations in  the system library.
+    It is recommended that you qualify this command with one or more
+    patterns, as there are thousands of operations available. For example,
+    say you are looking for functions that involve computation of
+    eigenvalues. To find their names, try )what operations eig. A rather
+    large list of operations is loaded into the workspace when this command
+    is first issued. This list will be deleted when you clear the workspace
+    via )clear all or )clear completely. It will be re-created if it is
+    needed again.
+  packages  displays a list of package constructors.
+  synonym  lists system command synonyms.
+  things    displays all  of the  above types for  items containing
+    the pattern strings as substrings. The command synonym )apropos is
+    equivalent to )what things.
+ 
+Also See: 
+o )display
+o )set
+o )show
+ 
+@
+\section{license}
+<<license>>=
+Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+All rights reserved.
+Text for this document is released under the license:
+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} Jenks, R.J. and Sutor, R.S. 
+``Axiom -- The Scientific Computation System''
+Springer-Verlag New York (1992)
+ISBN 0-387-97855-0
+\end{thebibliography}
+\end{document}

\start
Date: Mon, 27 Aug 2007 02:45:34 -0500
From: Tim Daly
To: list
Subject: 20070823.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index e981cf7..87548f8 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,5 @@
+20070823 tpd src/doc/spadhelp add additional spadhelp files
+20070823 tpd src/doc/Makefile add additional spadhelp files
 20070822 tpd src/doc/spadhelp add language help
 20070822 tpd src/doc/Makefile add spadhelp
 20070822 tpd src/doc/spadhelp created
diff --git a/src/doc/Makefile.pamphlet b/src/doc/Makefile.pamphlet
index c5af55b..7556528 100644
--- a/src/doc/Makefile.pamphlet
+++ b/src/doc/Makefile.pamphlet
@@ -130,23 +130,28 @@ ${INT}/booklet.c: ${IN}/booklet.c.pamphlet
 	  
 @
 \section{The )help files}
-<<helpspad>>=
-HELPSPAD=abbreviation boot cd clear close compile display edit fin frame \
-         help history \
-         language library lisp load ltrace \
-         nclef pquit quit read \
-         savesystem set show spool synonym system trace undo what
+This list is the same as the list at the end of the help section
+in spadhelp.pamphlet.
+<<spadhelp>>=
+SPADHELP=\
+abbreviations assignment boot       blocks     cd         clear      \
+clef          close      collection compile    display    edit       \
+fin           for        frame      help       history    if         \
+iterate       leave      library    lisp       load       ltrace     \
+parallel      pquit      quit       read       repeat     savesystem \
+set           show       spool      suchthat   synonym    system     \
+syntax        trace      undo       what       while
 
 @
-<<helpspad.files>>=
-${DVI}/spadhelp/helpspad.files: ${IN}/spadhelp.pamphlet
+<<spadhelp.files>>=
+${DVI}/spadhelp/spadhelp.files: ${IN}/spadhelp.pamphlet
 	@echo 9 making ${DVI}/spadhelp from ${IN}/spadhelp.pamphlet
 	@mkdir ${DVI}/spadhelp
 	@(cd ${DVI}/spadhelp ; \
-          for i in ${HELPSPAD} ; do \
+          for i in ${SPADHELP} ; do \
             ${TANGLE} -R"$$i" ${IN}/spadhelp.pamphlet >$$i.help ; \
           done ; \
-          ls *.help >helpspad.files )
+          ls *.help >spadhelp.files )
 
 @
 \section{The Makefile}
@@ -161,11 +166,11 @@ DOC=${INT}/doc
 
 FILES= ${MID}/axiom.bib ${STY}/axiom.sty ${DVI}/bookvol4.dvi \
        ${DVI}/book.dvi ${DVI}/bookvol1.dvi ${DVI}/endpaper.dvi \
-       ${DVI}/rosetta.dvi ${DVI}/spadhelp/helpspad.files
+       ${DVI}/rosetta.dvi ${DVI}/spadhelp/spadhelp.files
 
 CMDS=${OUT}/booklet
 
-<<helpspad>>
+<<spadhelp>>
 
 all: ${FILES} ${CMDS}
 	@echo 9 finished ${IN}
@@ -178,7 +183,7 @@ all: ${FILES} ${CMDS}
 <<bookvol1>>
 <<Endpapers>>
 <<rosetta>>
-<<helpspad.files>>
+<<spadhelp.files>>
 
 
 document:
diff --git a/src/doc/spadhelp.pamphlet b/src/doc/spadhelp.pamphlet
index 77f0027..54ea77c 100644
--- a/src/doc/spadhelp.pamphlet
+++ b/src/doc/spadhelp.pamphlet
@@ -11,8 +11,8 @@ command line )help command.
 \eject
 \tableofcontents
 \eject
-\section{abbreviation}
-<<abbreviation>>=
+\section{command abbreviations}
+<<abbreviations>>=
 ====================================================================
 A.2.  )abbreviation
 ====================================================================
@@ -85,7 +85,163 @@ o )compile
  
 @
 
-\section{boot}
+\section{syntax assignment}
+<<assignment>>=
+
+Immediate, Delayed, and Multiple Assignment
+
+====================================================================
+Immediate Assignment
+====================================================================
+
+A variable in Axiom refers to a value. A variable has a name beginning
+with an uppercase or lowercase alphabetic character, "%", or "!".
+Successive characters (if any) can be any of the above, digits, or "?".
+Case is distinguished. The following are all examples of valid, distinct
+variable names:
+
+  a       tooBig?     a1B2c3%!?
+  A       %j          numberOfPoints
+  beta6   %J          numberofpoints
+
+The ":=" operator is the immediate assignment operator. Use it to 
+associate a value with a variable. The syntax for immediate assignment
+for a single variable is:
+
+   variable := expression
+
+The value returned by an immediate assignment is the value of expression.
+
+  a := 1
+    1             
+           Type: PositiveInteger
+
+The right-hand side of the expression is evaluated, yielding 1. The value
+is then assigned to a.
+
+  b := a
+    1             
+           Type: PositiveInteger
+
+The right-hand side of the expression is evaluated, yieldig 1. This value
+is then assigned to b. Thus a and b both have the value 1 after the sequence
+of assignments.
+
+  a := 2
+    2
+           Type: PositiveInteger
+
+What is the value of b if a is assigned the value 2?
+
+  b
+    1
+           Type: PositiveInteger
+
+The value of b is left unchanged.
+
+This is what we mean when we say this kind of assignment is immediate.
+The variable b has no dependency on a after the initial assignment. This
+is the usual notion of assignment in programming languages such as C,
+Pascal, and Fortran.
+
+====================================================================
+Delayed Assignment
+====================================================================
+
+Axiom provides delayed assignment with "==". This implements a delayed
+evaluation of the right-hand side and dependency checking. The syntax for
+delayed assignment is
+
+   variable == expression
+
+The value returned by a delayed assignment is the unique value of Void.
+
+  a == 1
+           Type: Void
+
+  b == a
+           Type: Void
+
+Using a and b as above, these are the corresponding delayed assignments.
+
+  a
+   Compiling body of rule a to compute value of type PositiveInteger
+   1
+           Type: PositiveInteger
+
+The right-hand side of each delayed assignment is left unevaluated until
+the variables on the left-hand sides are evaluated. 
+
+  b
+   Compiling body of rule b to compute value of type PositiveInteger
+   1
+           Type: PositiveInteger
+
+This gives the same results as before. But if we change a to 2
+
+  a == 2
+   Compiled code for a has been cleared.
+   Compiled code for b has been cleared.
+   1 old definition(s) deleted for function or rule a
+           Type: Void
+
+Then a evaluates to 2, as expected
+
+  a
+   Compiling body of rule a to compute value of type PositiveInteger
+   2
+           Type: PositiveInteger
+
+but the value of b reflects the change to a
+
+  b
+   Compiling body of rule b to compute value of type PositiveInteger
+   2
+           Type: PositiveInteger
+
+====================================================================
+Multiple Immediate Assignments
+====================================================================
+
+It is possible to set several variables at the same time by using a
+tuple of variables and a tuple of expressions. A tuple is a collection
+of things separated by commas, often surrounded by parentheses. The
+syntax for multiple immediate assignment is
+
+ ( var1, var2, ..., varN ) := ( expr1, expr2, ..., exprN )
+
+The value returned by an immediate assignment is the value of exprN.
+
+ ( x, y ) := ( 1, 2 )
+   2
+           Type: PositiveInteger
+
+This sets x to 1 and y to 2. Multiple immediate assignments are parallel
+in the sense that the expressions on the right are all evaluated before
+any assignments on the left are made. However, the order of evaluation
+of these expressions is undefined.
+
+ ( x, y ) := ( y, x )
+   1
+           Type: PositiveInteger
+
+  x
+   2
+           Type: PositiveInteger
+
+The variable x now has the previous value of y.
+
+  y
+   1
+           Type: PositiveInteger
+
+The variable y now has the previous value of x.
+
+There is no syntactic form for multiple delayed assignments. 
+
+@
+
+\section{command boot}
 <<boot>>=
 ====================================================================
 A.3.  )boot
@@ -115,7 +271,95 @@ o )system
  
 @
 
-\section{cd}
+\section{syntax blocks}
+<<blocks>>=
+====================================================================
+Blocks
+====================================================================
+
+A block is a sequence of expressions evaluated in the order that they
+appear, except as modified by control expressions such as leave, return,
+iterate, and if-then-else constructions. The value of a block is the
+value of the expression last evaluated in the block.
+
+To leave a block early, use "=>". For example, 
+
+    i < 0 => x
+
+The expression before the "=>" must evaluate to true or false. The
+expression following the "=>" is the return value of the block.
+
+A block can be constructed in two ways:
+
+  1. the expressions can be separated by semicolons and the resulting
+     expression surrounded by parentheses, and
+  2. the expressions can be written on succeeding lines with each line
+     indented the same number of spaces (which must be greater than zero).
+     A block entered in this form is called a pile
+
+Only the first form is available if you are entering expressions directly
+to Axiom. Both forms are available in .input files. The syntax for a simple
+block of expressions entered interactively is
+
+  ( expression1 ; expression2 ; ... ; expressionN )
+
+The value returned by a block is the value of an "=>" expression, or
+expressionN if no "=>" is encountered.
+
+In .input files, blocks can also be written in piles. The examples
+given here are assumed to come from .input files.
+
+  a := 
+    i := gcd(234,672)
+    i := 2*i**5 - i + 1
+    1 / i
+
+      1
+    -----
+    23323
+              Type: Fraction Integer
+
+In this example, we assign a rational number to a using a block consisting
+of three expressions. This block is written as a pile. Each expression in
+the pile has the same indentation, in this case two spaces to the right of
+the first line.
+
+  a := ( i := gcd(234,672); i := 2*i**5 - i + 1; 1 / i )
+
+      1
+    -----
+    23323
+              Type: Fraction Integer
+
+Here is the same block written on one line. This is how you are required
+to enter it at the input prompt.
+
+  ( a := 1; b := 2; c := 3; [a,b,c] )
+    [1,2,3]
+              Type: List PositiveInteger
+
+AAxiom gives you two ways of writing a block and the preferred way in
+an .input file is to use a pile. Roughly speaking, a pile is a block
+whose consituent expressions are indented the same amount. You begin a
+pile by starting a new line for the first expression, indenting it to
+the right of the previous line. You then enter the second expression on
+a new line, vertically aligning it with the first line. And so on. If
+you need to enter an inner pile, further indent its lines to the right
+of the outer pile. Axiom knows where a pile ends. It ends when a subsequent
+line is indented to the left of the pile or the end of the file.
+
+Also See: 
+o )help if
+o )help repeat
+o )help while
+o )help for
+o )help suchthat
+o )help parallel
+o )help lists
+
+@
+
+\section{command cd}
 <<cd>>=
 ====================================================================
 A.4.  )cd
@@ -152,7 +396,7 @@ o )spool
  
 @
 
-\section{clear}
+\section{command clear}
 <<clear>>=
 ====================================================================
 A.6.  )clear
@@ -236,7 +480,56 @@ o )undo
  
 @
 
-\section{close}
+\section{system clef}
+<<clef>>=
+
+Entering printable keys generally inserts new text into the buffer (unless
+in overwrite mode, see below).  Other special keys can be used to modify
+the text in the buffer.  In the description of the keys below, ^n means
+Control-n, or holding the CONTROL key down while pressing "n".  Errors
+will ring the terminal bell.
+
+^A/^E	: Move cursor to beginning/end of the line.
+^F/^B   : Move cursor forward/backward one character.
+^D	: Delete the character under the cursor.
+^H, DEL : Delete the character to the left of the cursor.
+^K	: Kill from the cursor to the end of line.
+^L	: Redraw current line.
+^O	: Toggle overwrite/insert mode. Initially in insert mode. Text
+	  added in overwrite mode (including yanks) overwrite
+	  existing text, while insert mode does not overwrite.
+^P/^N   : Move to previous/next item on history list.
+^R/^S   : Perform incremental reverse/forward search for string on
+	  the history list.  Typing normal characters adds to the current
+	  search string and searches for a match. Typing ^R/^S marks
+	  the start of a new search, and moves on to the next match.
+	  Typing ^H or DEL deletes the last character from the search 
+	  string, and searches from the starting location of the last search.  
+	  Therefore, repeated DEL's appear to unwind to the match nearest 
+	  the point at which the last ^R or ^S was typed.  If DEL is 
+	  repeated until the search string is empty the search location 
+	  begins from the start of the history list.  Typing ESC or 
+	  any other editing character accepts the current match and 
+	  loads it into the buffer, terminating the search.
+^T	: Toggle the characters under and to the left of the cursor.
+^Y	: Yank previously killed text back at current location.  Note that
+	  this will overwrite or insert, depending on the current mode.
+^U      : Show help (this text).
+TAB	: Perform command completion based on word to the left of the cursor. 
+          Words are deemed to contain only the alphanumeric and the % ! ? _  
+          characters.
+NL, CR  : returns current buffer to the program.
+
+DOS and ANSI terminal arrow key sequences are recognized, and act like:
+
+  up    : same as ^P
+  down  : same as ^N
+  left  : same as ^B
+  right : same as ^F
+
+@ 
+
+\section{command close}
 <<close>>=
 ====================================================================
 A.5.  )close
@@ -278,7 +571,78 @@ o )pquit
  
 @
 
-\section{compile}
+\section{syntax collection}
+<<collection>>=
+====================================================================
+Collection -- Creating Lists and Streams with Iterators
+====================================================================
+
+All of the loop expressions which do not use the repeat leave or
+iterate words can be used to create lists and streams. For example:
+
+This creates a simple list of the integers from 1 to 10:
+
+  list := [i for i in 1..10]
+   [1,2,3,4,5,6,7,8,9,10]
+                      Type: List PositiveInteger
+
+Create a stream of the integers greater than or equal to 1:
+
+  stream := [i for i in 1..]
+   [1,2,3,4,5,6,7,...]
+                      Type: Stream PositiveInteger
+
+This is a list of the prime numbers between 1 and 10, inclusive:
+
+  [i for i in 1..10 | prime? i]
+   [2,3,5,7]
+                      Type: List PositiveInteger
+
+This is a stream of the prime integers greater than or equal to 1:
+  
+  [i for i in 1.. | prime? i]
+   [2,3,5,7,11,13,17,...]
+                      Type: Stream PositiveInteger
+
+This is a list of the integers between 1 and 10, inclusive, whose
+squares are less than 700:
+
+  [i for i in 1..10 while i*i < 700]
+   [1,2,3,4,5,6,7,8,9,10]
+                      Type: List PositiveInteger
+
+This is a stream of the integers greater than or equal to 1 whose
+squares are less than 700:
+
+  [i for i in 1.. while i*i < 700]
+   [1,2,3,4,5,6,7,...]
+                      Type: Stream PositiveInteger
+
+The general syntax of a collection is
+
+  [ collectExpression iterator1 iterator2 ... iteratorN ]
+
+where each iterator is either a for or a while clause. The loop 
+terminates immedidately when the end test of any iterator succeeds
+or when a return expression is evaluated in collectExpression. The
+value returned by the collection is either a list or a stream of
+elements, one for each iteration of the collectExpression.
+
+Be careful when you use while to create a stream. By default Axiom
+tries to compute and display the first ten elements of a stream. If
+the while condition is not satisfied quickly, Axiom can spend a long
+(potentially infinite) time trying to compute the elements. Use
+
+  )set streams calculate 
+
+to change the defaults to something else. This also affects the number
+of terms computed and displayed for power series. For the purposes of
+these examples we have use this system command to display fewer than
+ten terms.
+
+@
+
+\section{command compile}
 <<compile>>=
 ====================================================================
 A.7.  )compile
@@ -533,7 +897,8 @@ o )edit
 o )library
 
 @ 
-\section{display}
+
+\section{command display}
 <<display>>=
 ====================================================================
 A.8.  )display
@@ -608,7 +973,8 @@ o )show
 o )what
  
 @ 
-\section{edit}
+
+\section{command edit}
 <<edit>>=
 ====================================================================
 A.9.  )edit
@@ -656,7 +1022,8 @@ o )read
  
 
 @ 
-\section{fin}
+
+\section{command fin}
 <<fin>>=
 ====================================================================
 A.10.  )fin
@@ -680,7 +1047,213 @@ o )quit
  
 
 @ 
-\section{frame}
+
+\section{syntax for}
+<<for>>=
+====================================================================
+for loops
+====================================================================
+
+Axiom provide the for and in keywords in repeat loops, allowing you
+to integrate across all elements of a list, or to have a variable take
+on integral values from a lower bound to an upper bound. We shall refer
+to these modifying clauses of repeat loops as for clauses. These clauses
+can be present in addition to while clauses (See )help while). As with
+all other types of repeat loops, leave (see )help leave) can be used to 
+prematurely terminate evaluation of the loop.
+
+The syntax for a simple loop using for is
+
+  for iterator repeat loopbody
+
+The iterator has several forms. Each form has an end test which is
+evaluted before loopbody is evaluated. A for loop terminates immediately
+when the end test succeeds (evaluates to true) or when a leave or return
+expression is evaluated in loopbody. The value returned by the loop is 
+the unique value of Void.
+
+====================================================================
+for i in n..m repeat
+====================================================================
+
+If for is followed by a variable name, the in keyword and then an integer
+segment of the form n..m, the end test for this loop is the predicate 
+i > m. The body of the loop is evaluated m-n+1 times if this number is
+greater than 0. If this number is less than or equal to 0, the loop body
+is not evaluated at all.
+
+The variable i has the value n, n+1, ..., m for successive iterations
+of the loop body. The loop variable is a local variable within the loop
+body. Its value is not available outside the loop body and its value and
+type within the loop body completely mask any outer definition of a
+variable with the same name.
+
+  for i in 10..12 repeat output(i**3)
+   1000
+   1331
+   1728
+                      Type: Void
+
+The loop prints the values of 10^3, 11^3, and 12^3.
+
+  a := [1,2,3]
+   [1,2,3]
+                      Type: List PositiveInteger
+
+  for i in 1..#a repeat output(a.i)
+   1
+   2
+   3
+                      Type: Void
+
+Iterate across this list using "." to access the elements of a list
+and the # operation to count its elements.
+
+This type of iteration is applicable to anything that uses ".". You 
+can also use it with functions that use indices to extract elements.
+
+   m := matrix [[1,2],[4,3],[9,0]]
+    +-    -+
+    | 1  2 |
+    | 4  3 |
+    | 9  0 |
+    +-    -+
+                      Type: Matrix Integer
+
+Define m to be a matrix.
+
+   for i in 1..nrows(m) repeat output row(m.i)
+    [1,2]
+    [4,3]
+    [9,0]
+                      Type: Void
+
+Display the rows of m.
+
+You can iterate with for-loops.
+
+   for i in 1..5 repeat
+     if odd?(i) then iterate
+     output(i)
+    2
+    4
+                      Type: Void
+
+Display the even integers in a segment.
+
+====================================================================
+for i in n..m by s repeat
+====================================================================
+
+By default, the difference between values taken on by a variable in
+loops such as 
+
+  for i in n..m repeat ...
+
+is 1. It is possible to supply another, possibly negative, step value
+by using the by keyword along with for and in. Like the upper and lower
+bounds, the step value following the by keyword must be an integer. Note
+that the loop
+
+  for i in 1..2 by 0 repeat output(i)
+
+will not terminate by itself, as the step value does not change the
+index from its initial value of 1.
+
+  for i in 1..5 by 2 repeat output(i)
+   1
+   3
+   5
+                      Type: Void
+
+This expression displays the odd integers between two bounds.
+
+  for i in 5..1 by -2 repeat output(i)
+   5
+   3
+   1
+                      Type: Void
+
+Use this to display the numbers in reverse order.
+
+====================================================================
+for i in n.. repeat
+====================================================================
+
+If the value after the ".." is omitted, the loop has no end test. A
+potentially infinite loop is thus created. The variable is given the
+successive values n, n+1, n+2, ... and the loop is terminated only
+if a leave or return expression is evaluated in the loop body. However,
+you may also add some other modifying clause on the repeat, for example,
+a while clause, to stop the loop.
+
+  for i in 15.. while not prime?(i) repeat output(i)
+   15
+   16
+                      Type: Void
+
+This loop displays the integers greater than or equal to 15 and less
+than the first prime number greater than 15.
+
+====================================================================
+for x in l repeat
+====================================================================
+
+Another variant of the for loop has the form:
+
+  for x in list repeat loopbody
+
+This form is used when you want to iterate directly over the elements
+of a list. In this form of the for loop, the variable x takes on the
+value of each successive element in l. The end test is most simply
+stated in English: "are there no more x in l?"
+
+  l := [0, -5, 3]
+   [0, -5, 3]
+                      Type: List Integer
+
+  for x in l repeat output(x)
+   0
+   -5
+   3
+                      Type: Void
+
+This displays all of the elements of the list l, one per line.
+
+Since the list constructing expression 
+
+  expand [n..m]
+
+creates the list
+
+  [n, n+1, ..., m]
+
+you might be tempted to think that the loops
+
+  for i in n..m repeat output(i)
+
+and
+
+  for x in expand [n..m] repeat output(x)
+
+are equivalent. The second form first creates the expanded list
+(no matter how large it might be) and then does the iteration. The
+first form potentially runs in much less space, as the index variable
+i is simply incremented once per loop and the list is not actually
+created. Using the first form is much more efficient.
+
+Of course, sometimes you really want to iterate across a specific list.
+This displays each of the factors of 2400000:
+
+  for f in factors(factor(2400000)) repeat output(f)
+   [factor= 2, exponent= 8]
+   [factor= 3, exponent= 1]
+   [factor= 5, exponent= 5]
+                      Type: Void
+
+@
+
+\section{command frame}
 <<frame>>=
 ====================================================================
 A.11.  )frame
@@ -775,7 +1348,8 @@ o )history
 o )set
  
 @ 
-\section{help}
+
+\section{command help}
 <<help>>=
 ====================================================================
 A.12.  )help
@@ -787,6 +1361,7 @@ Command Syntax:
  
   - )help
   - )help commandName
+  - )help syntax
  
 Command Description: 
  
@@ -800,6 +1375,12 @@ of a system command to display information about it. For example,
 )help clear
  
 will display the description of the )clear system command.
+
+The command 
+
+)help syntax
+
+will give further information about the Axiom language syntax.
  
 All this material is available in the AXIOM User Guide and in HyperDoc. In
 HyperDoc, choose the Commands item from the Reference menu.
@@ -885,9 +1466,23 @@ only on and off are acceptable words for following boot. We also sometimes
 use ``...'' to indicate that additional arguments or options of the listed
 form are allowed. Finally, in the syntax descriptions we may also list the
 syntax of related commands.
- 
+
+====================================================================
+Other help topics
+====================================================================
+Available help topics are: 
+
+abbreviations assignment boot       blocks     cd         clear      
+clef          close      collection compile    display    edit       
+fin           for        frame      help       history    if         
+iterate       leave      library    lisp       load       ltrace     
+parallel      pquit      quit       read       repeat     savesystem 
+set           show       spool      suchthat   synonym    system     
+syntax        trace      undo       what       while
+
 @ 
-\section{history}
+
+\section{command history}
 <<history>>=
 ====================================================================
 A.13.  )history
@@ -1028,15 +1623,210 @@ o )undo
  
 @ 
 
-\section{language}
-<<language>>=
-The Axiom Interactive Language has the following features.
-More information is available by typing
-  )help feature
+\section{syntax if}
+<<if>>=
+====================================================================
+If-then-else
+====================================================================
+
+Like many other programming languages, Axiom uses the three keywords
+if, then, and else to form conditional expressions. The else part of
+the conditional is optional. The expression between the if and then
+keywords is a predicate: an expression that evaluates to or is
+convertible to either true or false, that is, a Boolean.
+
+The syntax for conditional expressions is
+
+   if predicate then expression1 else expression2
+
+where the "else expression2" part is optional. The value returned from
+a conditional expression is expression1 if the predicate evaluates to
+true and expression2 otherwise. If no else clause is given, the value
+is always the unique value of Void.
+
+An if-then-else expression always returns a value. If the else clause
+is missing then the entire expression returns the unique value of Void.
+If both clauses are present, the type of the value returned by if is
+obtained by resolving the types of the values of the two clauses.
+
+The predicate must evaluate to, or be convertible to, an object of type
+Boolean: true or false. By default, the equal sign "=" creates an equation.
+
+   x + 1 = y
+    x + 1 = y
+                Type: Equation Polynomial Integer
+
+This is an equation, not a boolean condition. In particular, it is
+an object of type Equation Polynomial Integer.
+
+However, for predicates in if expressions, Axiom places a default 
+target type of Boolean on the predicate and equality testing is performed.
+Thus you need not qualify the "=" in any way. In other contexts you may
+need to tell Axiom that you want to test for equality rather than create
+an equation. In these cases, use "@" and a target type of Boolean.
+
+The compound symbol meaning "not equal" in Axiom is "~=". This can be
+used directly without a package call or a target specification. The
+expression "a ~= b" is directly translated to "not(a = b)".
+
+Many other functions have return values of type Boolean. These include
+<, <=, >, >=, ~=, and member?. By convention, operations with names
+ending in "?" return Boolean values.
+
+The usual rules for piles are suspended for conditional expressions. In
+.input files, the then and else keywords can begin in the same column
+as the corresponding if by may also appear to the right. Each of the
+following styles of writing if-then-else expressions is acceptable:
+
+  if i>0 then output("positive") else output("nonpositive")
+
+  if i>0 then output("positive")
+    else output("nonpositive")
+
+  if i>0 then output("positive")
+  else output("nonpositive")
+
+  if i>0 
+  then output("positive")
+  else output("nonpositive")
+
+  if i>0 
+    then output("positive")
+    else output("nonpositive")
+
+A block can follow the then or else keywords. In the following two 
+assignments to a, the then and else clauses each are followed by two
+line piles. The value returned in each is the value of the second line.
+
+  a :=
+    if i > 0 then
+      j := sin(i * pi())
+      exp(j + 1/j)
+    else
+      j := cos(i * 0.5 * pi())
+      log(abs(j)**5 + i)
+
+
+  a :=
+    if i > 0 
+      then
+        j := sin(i * pi())
+        exp(j + 1/j)
+      else
+        j := cos(i * 0.5 * pi())
+        log(abs(j)**5 + i)
+
+These are both equivalent to the following:
+
+  a := 
+    if i > 0 then (j := sin(i * pi()); exp(j + 1/j))
+    else (j := cos(i * 0.5 * pi()); log(abs(j)**5 + i))
 
 @
 
-\section{library}
+\section{syntax iterate}
+<<iterate>>=
+====================================================================
+iterate in loops
+====================================================================
+
+Axiom provides an iterate expression that skips over the remainder
+of a loop body and starts the next loop execution. We first initialize
+a counter.
+
+  i := 0
+   0
+                      Type: NonNegativeInteger
+
+Display the even integers from 2 to 5:
+
+  repeat
+    i := i + 1
+    if i > 5 then leave
+    if odd?(i) then iterate
+    output(i)
+   2
+   4
+                      Type: Void
+
+@
+
+\section{syntax leave}
+<<leave>>=
+====================================================================
+leave in loops
+====================================================================
+
+The leave keyword is often more useful in terminating a loop. A
+leave causes control to transfer to the expression immediately following
+the loop. As loops always return the unique value of Void, you cannot
+return a value with leave. That is, leave takes no argument.
+
+  f() ==
+    i := 1
+    repeat
+      if factorial(i) > 1000 then leave
+      i := i + 1
+    i
+                      Type: Void
+
+This example is a modification of the last example in the previous
+section. Instead of using return we'll use leave.
+
+  f()
+   7
+                      Type: PositiveInteger
+
+The loop terminates when factorial(i) gets big enough. The last line
+of the function evaluates to the corresponding "good" value of i
+and the function terminates, returning that value.
+
+You can only use leave to terminate the evaluation of one loop. Lets
+consider a loop within a loop, that is, a loop with a nested loop. 
+First, we initialize two counter variables.
+
+  (i,j) := (1,1)
+   1
+                      Type: PositiveInteger
+
+  repeat
+    repeat
+      if (i + j) > 10 then leave
+      j := j + 1
+    if (i + j) > 10 then leave
+    i := i + 1
+                      Type: Void
+
+Nested loops must have multiple leave expressions at the appropriate
+nesting level. How would you rewrite this so (i + j) > 10 is only
+evaluated once?
+
+====================================================================
+leave vs => in loop bodies
+====================================================================
+
+Compare the following two loops:
+
+  i := 1                      i := 1
+  repeat                      repeat
+    i := i + 1                  i := i + 1
+    i > 3 => i                  if i > 3 then leave
+    output(i)                   output(i)
+
+In the example on the left, the values 2 and 3 for i are displayed but
+then the "=>" does not allow control to reach the call to output again.
+The loop will not terminate until you run out of space or interrupt the
+execution. The variable i will continue to be incremented because the
+"=>" only means to leave the block, not the loop.
+
+In the example on the right, upon reaching 4, the leave will be executed,
+and both the block and the loop will terminate. This is one of the reasons
+why both "=>" and leave are provided. Using a while clase with the "=>"
+lets you simulate the action of leave.
+
+@
+
+\section{command library}
 <<library>>=
 ====================================================================
 A.14.  )library
@@ -1094,7 +1884,8 @@ o )frame
 o )set
  
 @ 
-\section{lisp}
+
+\section{command lisp}
 <<lisp>>=
 ====================================================================
 A.15.  )lisp
@@ -1123,7 +1914,8 @@ o )boot
 o )fin
  
 @ 
-\section{load}
+
+\section{command load}
 <<load>>=
 ====================================================================
 A.16.  )load
@@ -1136,7 +1928,8 @@ Command Description:
 This command is obsolete. Use )library instead.
  
 @ 
-\section{ltrace}
+
+\section{command ltrace}
 <<ltrace>>=
 ====================================================================
 A.17.  )ltrace
@@ -1159,55 +1952,115 @@ o )lisp
 o )trace
  
 @ 
-\section{nclef}
-<<nclef>>=
 
-Entering printable keys generally inserts new text into the buffer (unless
-in overwrite mode, see below).  Other special keys can be used to modify
-the text in the buffer.  In the description of the keys below, ^n means
-Control-n, or holding the CONTROL key down while pressing "n".  Errors
-will ring the terminal bell.
 
-^A/^E	: Move cursor to beginning/end of the line.
-^F/^B   : Move cursor forward/backward one character.
-^D	: Delete the character under the cursor.
-^H, DEL : Delete the character to the left of the cursor.
-^K	: Kill from the cursor to the end of line.
-^L	: Redraw current line.
-^O	: Toggle overwrite/insert mode. Initially in insert mode. Text
-	  added in overwrite mode (including yanks) overwrite
-	  existing text, while insert mode does not overwrite.
-^P/^N   : Move to previous/next item on history list.
-^R/^S   : Perform incremental reverse/forward search for string on
-	  the history list.  Typing normal characters adds to the current
-	  search string and searches for a match. Typing ^R/^S marks
-	  the start of a new search, and moves on to the next match.
-	  Typing ^H or DEL deletes the last character from the search 
-	  string, and searches from the starting location of the last search.  
-	  Therefore, repeated DEL's appear to unwind to the match nearest 
-	  the point at which the last ^R or ^S was typed.  If DEL is 
-	  repeated until the search string is empty the search location 
-	  begins from the start of the history list.  Typing ESC or 
-	  any other editing character accepts the current match and 
-	  loads it into the buffer, terminating the search.
-^T	: Toggle the characters under and to the left of the cursor.
-^Y	: Yank previously killed text back at current location.  Note that
-	  this will overwrite or insert, depending on the current mode.
-^U      : Show help (this text).
-TAB	: Perform command completion based on word to the left of the cursor. 
-          Words are deemed to contain only the alphanumeric and the % ! ? _  
-          characters.
-NL, CR  : returns current buffer to the program.
+\section{syntax parallel}
+<<parallel>>=
+====================================================================
+parallel iteration
+====================================================================
 
-DOS and ANSI terminal arrow key sequences are recognized, and act like:
+Sometimes you want to iterate across two lists in parallel, or perhaps
+you want to traverse a list while incrementing a variable.
 
-  up    : same as ^P
-  down  : same as ^N
-  left  : same as ^B
-  right : same as ^F
+The general syntax of a repeat loop is
 
-@ 
-\section{pquit}
+ iterator1, iterator2, ..., iteratorN repeat loopbody
+
+where each iterator is either a for or a while clause. The loop 
+terminates immediately when the end test of any iterator succeeds or 
+when a leave or return expression is evaluated in loopbody. The value
+returned by the loop is the unique value of Void.
+
+  l := [1,3,5,7]
+   [1,3,5,7]
+                      Type: List PositiveInteger
+
+  m := [100,200]
+   [100,200]
+                      Type: List PositiveInteger
+
+  sum := 0
+   0
+                      Type: NonNegativeInteger
+
+Here we write a loop to iterate across two lists, computing the sum
+of the pairwise product of the elements:
+
+  for x in l for y in m repeat
+    sum := sum + x*y
+                      Type: Void
+
+The last two elements of l are not used in the calculation because
+m has two fewer elements than l.
+
+  sum
+   700
+                      Type: NonNegativeInteger
+
+This is the "dot product".
+
+Next we write a loop to compute the sum of the products of the loop
+elements with their positions in the loop.
+
+  l := [2,3,5,7,11,13,17,19,23,29,31,37]
+   [2,3,5,7,11,13,17,19,23,29,31,37]
+                      Type: List PositiveInteger
+
+  sum := 0
+   0
+                      Type: NonNegativeInteger
+
+  for i in 0.. for x in l repeat sum := i * x
+                      Type: Void
+
+Here looping stops when the list l is exhaused, even though the
+for i in 0.. specifies no terminating condition.
+
+  sum 
+   407
+                      Type: NonNegativeInteger
+
+When "|" is used to qualify any of the for clauses in a parallel 
+iteration, the variables in the predicates can be from an outer
+scope or from a for clause in or to the left of the modified clause.
+
+This is correct:
+ 
+  for i in 1..10 repeat
+    for j in 200..300 | ood? (i+j) repeat
+      output [i,j]
+
+But this is not correct. The variable j has not been defined outside
+the inner loop:
+
+  for i in 1..01 | odd? (i+j) repeat -- wrong, j not defined
+    for j in 200..300 repeat
+      output [i,j]
+
+It is possible to mix several of repeat modifying clauses on a loop:
+
+  for i in 1..10
+    for j in 151..160 | odd? j
+      while i + j < 160 repeat
+        output [i,j]
+   [1,151]
+   [3,153]
+                      Type: Void
+
+Here are useful rules for composing loop expressions:
+
+ 1. while predicates can only refer to variables that are global (or
+    in an outer scope) or that are defined in for clauses to the left
+    of the predicate.
+ 2. A "such that" predicate (somthing following "|") must directly
+    follow a for clause and can only refer to variables that are
+    global (or in an outer scope) or defined in the modified for clause
+    or any for clause to the left.
+
+@
+
+\section{command pquit}
 <<pquit>>=
 ====================================================================
 A.18.  )pquit
@@ -1254,7 +2107,8 @@ o )quit
 o )system
  
 @ 
-\section{quit}
+
+\section{command quit}
 <<quit>>=
 ====================================================================
 A.19.  )quit
@@ -1298,7 +2152,8 @@ o )pquit
 o )system
  
 @ 
-\section{read}
+
+\section{command read}
 <<read>>=
 ====================================================================
 A.20.  )read
@@ -1337,19 +2192,199 @@ o )edit
 o )history
  
 @ 
-\section{savesystem}
-<<savesystem>>=
-AXIOM Help Information. Section numbers refer to the book 
-AXIOM: The System for Scientific Computation. 
+
+\section{syntax repeat}
+<<repeat>>=
+====================================================================
+Repeat Loops
+====================================================================
+
+A loop is an expression that contains another expression, called the loop
+body, which is to be evaluated zero or more times. All loops contain the
+repeat keyword and return the unique value of Void. Loops can contain
+inner loops to any depth.
+
+The most basic loop is of the form
  
+  repeat loopbody
+
+Unless loopbody contains a leave or return expression, the loop repeats
+foreer. The value returned by the loop is the unique value of Void.
+
+Axiom tries to determine completely the type of every object in a loop
+and then to translate the loop body to Lisp or even to machine code. This
+translation is called compilation.
+
+If Axiom decides that it cannot compile the loop, it issues a message
+stating the problem and then the following message:
+
+  We will attemp to step through and interpret the code
+
+It is still possible that Axiom can evalute the loop but in interpret-code
+mode.
+
+====================================================================
+Return in Loops
+====================================================================
+
+A return expression is used to exit a function with a particular value.
+In particular, if a return is in a loop within the function, the loop
+is terminated whenever the return is evaluated. 
+
+  f() ==
+    i := 1
+    repeat
+      if factorial(i) > 1000 then return i
+      i := i + 1
+                      Type: Void
+
+  f()
+                      Type: Void
+
+When factorial(i) is big enough, control passes from inside the loop
+all the way outside the function, returning the value of i (so we think).
+What went wrong? Isn't it obvious that this function should return an
+integer? Well, Axiom makes no attempt to analyze the structure of a
+loop to determine if it always returns a value because, in general, this
+is impossible. So Axiom has this simple rule: the type of the function is
+determined by the type of its body, in this case a block. The normal value
+of a block is the value of its last expression, in this case, a loop. And
+the value of every loop is the unique value of Void. So the return type
+of f is Void.
+
+There are two ways to fix this. The best way is for you to tell Axiom
+what the return type of f is. You do this by giving f a declaration
+
+   f:() -> Integer
+
+prior to calling for its value. This tells Axiom "trust me -- an integer
+is returned". Another way is to add a dummy expression as follows.
+
+  f() ==
+    i := 1
+    repeat
+      if factorial(i) > 1000 then return i
+      i := i + 1
+    0
+                      Type: Void
+
+Note that the dummy expression will never be evaluated but it is the
+last expression in the function and will determine the return type.
+
+  f()
+   7
+                      Type: PositiveInteger
+
+====================================================================
+leave in loops
+====================================================================
+
+The leave keyword is often more useful in terminating a loop. A
+leave causes control to transfer to the expression immediately following
+the loop. As loops always return the unique value of Void, you cannot
+return a value with leave. That is, leave takes no argument.
+
+  f() ==
+    i := 1
+    repeat
+      if factorial(i) > 1000 then leave
+      i := i + 1
+    i
+                      Type: Void
+
+This example is a modification of the last example in the previous
+section. Instead of using return we'll use leave.
+
+  f()
+   7
+                      Type: PositiveInteger
+
+The loop terminates when factorial(i) gets big enough. The last line
+of the function evaluates to the corresponding "good" value of i
+and the function terminates, returning that value.
+
+You can only use leave to terminate the evaluation of one loop. Lets
+consider a loop within a loop, that is, a loop with a nested loop. 
+First, we initialize two counter variables.
+
+  (i,j) := (1,1)
+   1
+                      Type: PositiveInteger
+
+  repeat
+    repeat
+      if (i + j) > 10 then leave
+      j := j + 1
+    if (i + j) > 10 then leave
+    i := i + 1
+                      Type: Void
+
+Nested loops must have multiple leave expressions at the appropriate
+nesting level. How would you rewrite this so (i + j) > 10 is only
+evaluated once?
+
+====================================================================
+leave vs => in loop bodies
+====================================================================
+
+Compare the following two loops:
+
+  i := 1                      i := 1
+  repeat                      repeat
+    i := i + 1                  i := i + 1
+    i > 3 => i                  if i > 3 then leave
+    output(i)                   output(i)
+
+In the example on the left, the values 2 and 3 for i are displayed but
+then the "=>" does not allow control to reach the call to output again.
+The loop will not terminate until you run out of space or interrupt the
+execution. The variable i will continue to be incremented because the
+"=>" only means to leave the block, not the loop.
+
+In the example on the right, upon reaching 4, the leave will be executed,
+and both the block and the loop will terminate. This is one of the reasons
+why both "=>" and leave are provided. Using a while clase with the "=>"
+lets you simulate the action of leave.
+
+====================================================================
+iterate in loops
+====================================================================
+
+Axiom provides an iterate expression that skips over the remainder
+of a loop body and starts the next loop execution. We first initialize
+a counter.
+
+  i := 0
+   0
+                      Type: NonNegativeInteger
+
+Display the even integers from 2 to 5:
+
+  repeat
+    i := i + 1
+    if i > 5 then leave
+    if odd?(i) then iterate
+    output(i)
+   2
+   4
+                      Type: Void
+
+Also See: 
+o )help blocks
+o )help if
+o )help while
+o )help for
+o )help suchthat
+o )help parallel
+o )help lists
+
+@
+\section{command savesystem}
+<<savesystem>>=
 ====================================================================
 A.8.  )savesystem
 ====================================================================
  
- 
- 
- 
- 
 User Level Required:  interpreter
  
  
@@ -1377,7 +2412,8 @@ There is currently a restriction that only systems started with the
 command "AXIOMsys" may be saved.
 
 @ 
-\section{set}
+
+\section{command set}
 <<set>>=
 ====================================================================
 A.21.  )set
@@ -1433,7 +2469,8 @@ Also See:
 o )quit
  
 @ 
-\section{show}
+
+\section{command show}
 <<show>>=
 ====================================================================
 A.22.  )show
@@ -1485,7 +2522,8 @@ o )set
 o )what
  
 @ 
-\section{spool}
+
+\section{command spool}
 <<spool>>=
 ====================================================================
 A.23.  )spool
@@ -1518,7 +2556,50 @@ Also See:
 o )cd
  
 @ 
-\section{synonym}
+
+\section{syntax suchthat}
+<<suchthat>>=
+====================================================================
+Such that predicates
+====================================================================
+
+A for loop can be followed by a "|" and then a predicate. The predicate
+qualifies the use of the values from the iterator that follows the for.
+Think of the vertical bar "|" as the phrase "such that".
+
+  for n in 0..4 | odd? n repeat output n
+   1
+   3
+                      Type: Void
+
+This loop expression prints out the integers n in the given segment
+such that n is odd.
+
+A for loop can also be written
+
+  for iterator | predicate repeat loopbody
+
+which is equivalent to:
+
+  for iterator repeat if predicate then loopbody else iterate
+
+The predicate need not refer only to the variable in the for clause.
+Any variable in an outer scope can be part of the predicate.
+
+  for i in 1..50 repeat
+    for j in 1..50 | factorial(i+j) < 25 repeat
+      output [i,j]
+   [1,1]
+   [1,2]
+   [1,3]
+   [2,1]
+   [2,2]
+   [3,1]
+                      Type: Void
+
+@
+
+\section{command synonym}
 <<synonym>>=
 ====================================================================
 A.24.  )synonym
@@ -1566,7 +2647,8 @@ o )set
 o )what
  
 @ 
-\section{system}
+
+\section{command system}
 <<system>>=
 ====================================================================
 A.25.  )system
@@ -1603,7 +2685,33 @@ o )pquit
 o )quit
  
 @ 
-\section{trace}
+
+\section{syntax syntax}
+<<syntax>>=
+
+The Axiom Interactive Language has the following features documented here.
+
+More information is available by typing
+
+  )help feature
+
+where feature is one of:
+
+  assignment -- Immediate and delayed assignments
+  blocks     -- Blocks of expressions
+  collection -- creating lists with iterators
+  for        -- for loops
+  if         -- If-then-else statements
+  iterate    -- using iterate in loops
+  leave      -- using leave in loops
+  parallel   -- parallel iterations
+  repeat     -- repeat loops
+  suchthat   -- suchthat predicates
+  while      -- while loops
+
+@
+
+\section{command trace}
 <<trace>>=
 ====================================================================
 A.26.  )trace
@@ -1823,7 +2931,8 @@ o )lisp
 o )ltrace
  
 @ 
-\section{undo}
+
+\section{command undo}
 <<undo>>=
 ====================================================================
 A.27.  )undo
@@ -1884,7 +2993,8 @@ The command )history )write will eliminate the ``undone'' command lines of
 your program.
  
 @ 
-\section{what}
+
+\section{command what}
 <<what>>=
 ====================================================================
 A.28.  )what
@@ -1964,6 +3074,80 @@ o )set
 o )show
  
 @
+
+\section{syntax while}
+<<while>>=
+====================================================================
+while loops
+====================================================================
+
+The repeat in a loop can be modified by adding one or more while 
+clauses. Each clause contains a predicate immediately following the
+while keyword. The predicate is tested before the evaluation of the 
+body of the loop. The loop body is evaluated whenever the predicate
+in a while clause is true.
+
+The syntax for a simple loop using while is
+
+  while predicate repeat loopbody
+
+The predicate is evaluated before loopbody is evaluated. A while loop
+terminates immediately when predicate evaluates to false or when a
+leave or return expression is evaluted. See )help repeat for more
+information on leave and return.
+
+Here is a simple example of using while in a loop. We first initialize
+the counter.
+
+  i := 1
+   1
+                      Type: PositiveInteger
+
+  while i < 1 repeat
+    output "hello"
+    i := i + 1
+                      Type: Void
+
+The steps involved in computing this example are
+ (1) set i to 1
+ (2) test the condition i < 1 and determine that it is not true
+ (3) do not evaluate the loop body and therefore do not display "hello"
+
+  (x, y) := (1, 1)
+   1
+                      Type: PositiveInteger
+
+If you have multiple predicates to be tested use the logical and
+operation to separate them. Axiom evaluates these predicates from
+left to right.
+
+  while x < 4 and y < 10 repeat
+    output [x,y]
+    x := x + 1
+    y := y + 2
+   [1,1]
+   [2,3]
+   [3,5]
+                      Type: Void
+
+
+A leave expression can be included in a loop body to terminate a loop
+even if the predicate in any while clauses are not false.
+
+  (x, y) := (1, 1)
+   1
+                      Type: PositiveInteger
+
+  while x < 4 and y < 10 repeat
+    if x + y > 7 then leave
+    output [x,y]
+    x := x + 1
+    y := y + 2
+   [1,1]
+   [2,3]
+                      Type: Void
+
+@
 \section{license}
 <<license>>=
 Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.

\start
Date: Mon, 27 Aug 2007 02:49:23 -0500
From: Tim Daly
To: list
Subject: 20070826.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index eaa591a..fbb5d26 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,25 @@
+20070825 tpd doc/src/algebra/spadhelp add all abbreviation files
+20070825 tpd src/doc/spadhelp add all abbreviations
+20070825 tpd src/doc/spadhelp add DoubleFloat
+20070825 tpd src/algebra/Makefile add DoubleFloat.help 
+20070825 tpd src/algebra/sf.spad add DoubleFloat.help 
+20070825 tpd src/algebra/sf.spad add DoubleFloat.input
+20070825 tpd src/doc/spadhelp add EqTable
+20070825 tpd src/algebra/Makefile add EqTable.help 
+20070825 tpd src/algebra/table.spad add EqTable.help 
+20070825 tpd src/algebra/table.spad add EqTable.input
+20070825 tpd src/doc/spadhelp add DistributedMultivariatePolynomial
+20070825 tpd src/algebra/Makefile add DMP.help 
+20070825 tpd src/algebra/gdpoly.spad add DMP.help 
+20070825 tpd src/algebra/gdpoly.spad add DMP.input
+20070825 tpd src/doc/spadhelp add GeneralDistributedMultivariatePolynomial
+20070825 tpd src/algebra/Makefile add GDMP.help 
+20070825 tpd src/algebra/gdpoly.spad add GDMP.help 
+20070825 tpd src/algebra/gdpoly.spad add GDMP.input
+20070825 tpd src/algebra/carten.spad fix help typo
+20070825 tpd src/algebra/gaussian.spad fix help typo
+20070825 tpd src/algebra/derham.spad fix help typo
+20070825 tpd src/algebra/cycles.spad fix help typo
 20070824 tpd src/doc/spadhelp          add DecimalExpansion
 20070824 tpd src/algebra/Makefile      add DecimalExpansion.help 
 20070824 tpd src/algebra/radix.spad    add DecimalExpansion.help 
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index 3fa3009..542e42d 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -2026,7 +2026,11 @@ SPADHELP=\
  ${HELP}/CharacterClass.help   ${HELP}/CliffordAlgebra.help \
  ${HELP}/Complex.help          ${HELP}/ContinuedFraction.help \
  ${HELP}/CycleIndicators.help  ${HELP}/DeRhamComplex.help \
- ${HELP}/DecimalExpansion.help 
+ ${HELP}/DecimalExpansion.help ${HELP}/DoubleFloat.help \
+ ${HELP}/EqTable.help \
+ ${HELP}/DistributedMultivariatePolynomial.help \
+ ${HELP}/GeneralDistributedMultivariatePolynomial.help \
+ ${HELP}/HomogeneousDistributedMultivariatePolynomial.help
 
 @
 The algebra files contain input chunks in regress format.
@@ -2044,7 +2048,11 @@ REGRESS=\
  CharacterClass.regress   CliffordAlgebra.regress \
  Complex.regress          ContinuedFraction.regress \
  CycleIndicators.regress  DeRhamComplex.regress \
- DecimalExpansion.regress
+ DecimalExpansion.regress DoubleFloat.regress \
+ EqTable.regress \
+ DistributedMultivariatePolynomial.regress \
+ GeneralDistributedMultivariatePolynomial.regress \
+ HomogeneousDistributedMultivariatePolynomial.regress 
 
 %.regress: %.input
 	@ echo algebra regression testing $*
@@ -2061,6 +2069,7 @@ ${HELP}/AssociationList.help: ${IN}/list.spad.pamphlet
 	@echo 7000 create AssociationList.help from ${IN}/list.spad.pamphlet
 	@${TANGLE} -R"AssociationList.help" ${IN}/list.spad.pamphlet \
             >${HELP}/AssociationList.help
+	@cp ${HELP}/AssociationList.help ${HELP}/ALIST.help
 	@${TANGLE} -R"AssociationList.input" ${IN}/list.spad.pamphlet \
             >${INPUT}/AssociationList.input
 
@@ -2068,6 +2077,7 @@ ${HELP}/BalancedBinaryTree.help: ${IN}/tree.spad.pamphlet
 	@echo 7001 create BalancedBinaryTree.help from ${IN}/tree.spad.pamphlet
 	@${TANGLE} -R"BalancedBinaryTree.help" ${IN}/tree.spad.pamphlet \
             >${HELP}/BalancedBinaryTree.help
+	@cp ${HELP}/BalancedBinaryTree.help ${HELP}/BBTREE.help
 	@${TANGLE} -R"BalancedBinaryTree.input" ${IN}/tree.spad.pamphlet \
             >${INPUT}/BalancedBinaryTree.input
 
@@ -2075,6 +2085,7 @@ ${HELP}/BasicOperator.help: ${IN}/op.spad.pamphlet
 	@echo 7002 create BasicOperator.help from ${IN}/op.spad.pamphlet
 	@${TANGLE} -R"BasicOperator.help" ${IN}/op.spad.pamphlet \
             >${HELP}/BasicOperator.help
+	@cp ${HELP}/BasicOperator.help ${HELP}/BOP.help
 	@${TANGLE} -R"BasicOperator.input" ${IN}/op.spad.pamphlet \
             >${INPUT}/BasicOperator.input
 
@@ -2082,6 +2093,7 @@ ${HELP}/BinaryExpansion.help: ${IN}/radix.spad.pamphlet
 	@echo 7003 create BinaryExpansion.help from ${IN}/radix.spad.pamphlet
 	@${TANGLE} -R"BinaryExpansion.help" ${IN}/radix.spad.pamphlet \
             >${HELP}/BinaryExpansion.help
+	@cp ${HELP}/BinaryExpansion.help ${HELP}/BINARY.help
 	@${TANGLE} -R"BinaryExpansion.input" ${IN}/radix.spad.pamphlet \
             >${INPUT}/BinaryExpansion.input
 
@@ -2089,6 +2101,7 @@ ${HELP}/BinarySearchTree.help: ${IN}/tree.spad.pamphlet
 	@echo 7004 create BinarySearchTree.help from ${IN}/tree.spad.pamphlet
 	@${TANGLE} -R"BinarySearchTree.help" ${IN}/tree.spad.pamphlet \
             >${HELP}/BinarySearchTree.help
+	@cp ${HELP}/BinarySearchTree.help ${HELP}/BSTREE.help
 	@${TANGLE} -R"BinarySearchTree.input" ${IN}/tree.spad.pamphlet \
             >${INPUT}/BinarySearchTree.input
 
@@ -2096,6 +2109,7 @@ ${HELP}/CardinalNumber.help: ${IN}/card.spad.pamphlet
 	@echo 7005 create CardinalNumber.help from ${IN}/card.spad.pamphlet
 	@${TANGLE} -R"CardinalNumber.help" ${IN}/card.spad.pamphlet \
             >${HELP}/CardinalNumber.help
+	@cp ${HELP}/CardinalNumber.help ${HELP}/CARD.help
 	@${TANGLE} -R"CardinalNumber.input" ${IN}/card.spad.pamphlet \
             >${INPUT}/CardinalNumber.input
 
@@ -2103,6 +2117,7 @@ ${HELP}/CartesianTensor.help: ${IN}/carten.spad.pamphlet
 	@echo 7006 create CartesianTensor.help from ${IN}/carten.spad.pamphlet
 	@${TANGLE} -R"CartesianTensor.help" ${IN}/carten.spad.pamphlet \
             >${HELP}/CartesianTensor.help
+	@cp ${HELP}/CartesianTensor.help ${HELP}/CARTEN.help
 	@${TANGLE} -R"CartesianTensor.input" ${IN}/carten.spad.pamphlet \
             >${INPUT}/CartesianTensor.input
 
@@ -2110,6 +2125,7 @@ ${HELP}/Character.help: ${IN}/string.spad.pamphlet
 	@echo 7007 create Character.help from ${IN}/string.spad.pamphlet
 	@${TANGLE} -R"Character.help" ${IN}/string.spad.pamphlet \
             >${HELP}/Character.help
+	@cp ${HELP}/Character.help ${HELP}/CHAR.help
 	@${TANGLE} -R"Character.input" ${IN}/string.spad.pamphlet \
             >${INPUT}/Character.input
 
@@ -2117,6 +2133,7 @@ ${HELP}/CharacterClass.help: ${IN}/string.spad.pamphlet
 	@echo 7008 create CharacterClass.help from ${IN}/string.spad.pamphlet
 	@${TANGLE} -R"CharacterClass.help" ${IN}/string.spad.pamphlet \
             >${HELP}/CharacterClass.help
+	@cp ${HELP}/CharacterClass.help ${HELP}/CCLASS.help
 	@${TANGLE} -R"CharacterClass.input" ${IN}/string.spad.pamphlet \
             >${INPUT}/CharacterClass.input
 
@@ -2125,6 +2142,7 @@ ${HELP}/CliffordAlgebra.help: ${IN}/clifford.spad.pamphlet
           ${IN}/clifford.spad.pamphlet
 	@${TANGLE} -R"CliffordAlgebra.help" ${IN}/clifford.spad.pamphlet \
             >${HELP}/CliffordAlgebra.help
+	@cp ${HELP}/CliffordAlgebra.help ${HELP}/CLIF.help
 	@${TANGLE} -R"CliffordAlgebra.input" ${IN}/clifford.spad.pamphlet \
             >${INPUT}/CliffordAlgebra.input
 
@@ -2132,6 +2150,7 @@ ${HELP}/Complex.help: ${IN}/gaussian.spad.pamphlet
 	@echo 7010 create Complex.help from ${IN}/gaussian.spad.pamphlet
 	@${TANGLE} -R"Complex.help" ${IN}/gaussian.spad.pamphlet \
             >${HELP}/Complex.help
+	@cp ${HELP}/Complex.help ${HELP}/COMPLEX.help
 	@${TANGLE} -R"Complex.input" ${IN}/gaussian.spad.pamphlet \
             >${INPUT}/Complex.input
 
@@ -2140,6 +2159,7 @@ ${HELP}/ContinuedFraction.help: ${IN}/contfrac.spad.pamphlet
             ${IN}/contfrac.spad.pamphlet
 	@${TANGLE} -R"ContinuedFraction.help" ${IN}/contfrac.spad.pamphlet \
             >${HELP}/ContinuedFraction.help
+	@cp ${HELP}/ContinuedFraction.help ${HELP}/CONTFRAC.help
 	@${TANGLE} -R"ContinuedFraction.input" ${IN}/contfrac.spad.pamphlet \
             >${INPUT}/ContinuedFraction.input
 
@@ -2148,6 +2168,7 @@ ${HELP}/CycleIndicators.help: ${IN}/cycles.spad.pamphlet
             ${IN}/cycles.spad.pamphlet
 	@${TANGLE} -R"CycleIndicators.help" ${IN}/cycles.spad.pamphlet \
             >${HELP}/CycleIndicators.help
+	@cp ${HELP}/CycleIndicators.help ${HELP}/CYCLES.help
 	@${TANGLE} -R"CycleIndicators.input" ${IN}/cycles.spad.pamphlet \
             >${INPUT}/CycleIndicators.input
 
@@ -2155,6 +2176,7 @@ ${HELP}/DeRhamComplex.help: ${IN}/derham.spad.pamphlet
 	@echo 7013 create DeRhamComplex.help from ${IN}/derham.spad.pamphlet
 	@${TANGLE} -R"DeRhamComplex.help" ${IN}/derham.spad.pamphlet \
             >${HELP}/DeRhamComplex.help
+	@cp ${HELP}/DeRhamComplex.help ${HELP}/DERHAM.help
 	@${TANGLE} -R"DeRhamComplex.input" ${IN}/derham.spad.pamphlet \
             >${INPUT}/DeRhamComplex.input
 
@@ -2162,9 +2184,64 @@ ${HELP}/DecimalExpansion.help: ${IN}/radix.spad.pamphlet
 	@echo 7014 create DecimalExpansion.help from ${IN}/radix.spad.pamphlet
 	@${TANGLE} -R"DecimalExpansion.help" ${IN}/radix.spad.pamphlet \
             >${HELP}/DecimalExpansion.help
+	@cp ${HELP}/DecimalExpansion.help ${HELP}/DECIMAL.help
 	@${TANGLE} -R"DecimalExpansion.input" ${IN}/radix.spad.pamphlet \
             >${INPUT}/DecimalExpansion.input
 
+${HELP}/DistributedMultivariatePolynomial.help: \
+            ${IN}/gdpoly.spad.pamphlet
+	@echo 7015 create DistributedMultivariatePolynomial.help \
+            from ${IN}/gdpoly.spad.pamphlet
+	@${TANGLE} -R"DistributedMultivariatePolynomial.help" \
+           ${IN}/gdpoly.spad.pamphlet \
+            >${HELP}/DistributedMultivariatePolynomial.help
+	@cp ${HELP}/DistributedMultivariatePolynomial.help ${HELP}/DMP.help
+	@${TANGLE} -R"DistributedMultivariatePolynomial.input" \
+           ${IN}/gdpoly.spad.pamphlet \
+            >${INPUT}/DistributedMultivariatePolynomial.input
+
+${HELP}/DoubleFloat.help: ${IN}/sf.spad.pamphlet
+	@echo 7016 create DoubleFloat.help from ${IN}/sf.spad.pamphlet
+	@${TANGLE} -R"DoubleFloat.help" ${IN}/sf.spad.pamphlet \
+            >${HELP}/DoubleFloat.help
+	@cp ${HELP}/DoubleFloat.help ${HELP}/DFLOAT.help
+	@${TANGLE} -R"DoubleFloat.input" ${IN}/sf.spad.pamphlet \
+            >${INPUT}/DoubleFloat.input
+
+${HELP}/EqTable.help: ${IN}/table.spad.pamphlet
+	@echo 7017 create EqTable.help from ${IN}/table.spad.pamphlet
+	@${TANGLE} -R"EqTable.help" ${IN}/table.spad.pamphlet \
+            >${HELP}/EqTable.help
+	@cp ${HELP}/EqTable.help ${HELP}/EQTBL.help
+	@${TANGLE} -R"EqTable.input" ${IN}/table.spad.pamphlet \
+            >${INPUT}/EqTable.input
+
+${HELP}/GeneralDistributedMultivariatePolynomial.help: \
+            ${IN}/gdpoly.spad.pamphlet
+	@echo 7018 create GeneralDistributedMultivariatePolynomial.help \
+            from ${IN}/gdpoly.spad.pamphlet
+	@${TANGLE} -R"GeneralDistributedMultivariatePolynomial.help" \
+           ${IN}/gdpoly.spad.pamphlet \
+            >${HELP}/GeneralDistributedMultivariatePolynomial.help
+	@cp ${HELP}/GeneralDistributedMultivariatePolynomial.help \
+             ${HELP}/GDMP.help
+	@${TANGLE} -R"GeneralDistributedMultivariatePolynomial.input" \
+           ${IN}/gdpoly.spad.pamphlet \
+            >${INPUT}/GeneralDistributedMultivariatePolynomial.input
+
+${HELP}/HomogeneousDistributedMultivariatePolynomial.help: \
+            ${IN}/gdpoly.spad.pamphlet
+	@echo 7019 create HomogeneousDistributedMultivariatePolynomial.help \
+            from ${IN}/gdpoly.spad.pamphlet
+	@${TANGLE} -R"HomogeneousDistributedMultivariatePolynomial.help" \
+           ${IN}/gdpoly.spad.pamphlet \
+            >${HELP}/HomogeneousDistributedMultivariatePolynomial.help
+	@cp ${HELP}/HomogeneousDistributedMultivariatePolynomial.help \
+             ${HELP}/HDMP.help
+	@${TANGLE} -R"HomogeneousDistributedMultivariatePolynomial.input" \
+           ${IN}/gdpoly.spad.pamphlet \
+            >${INPUT}/HomogeneousDistributedMultivariatePolynomial.input
+
 @
 
 \section{The Makefile}
diff --git a/src/algebra/carten.spad.pamphlet b/src/algebra/carten.spad.pamphlet
index 5bcaa75..85f7027 100644
--- a/src/algebra/carten.spad.pamphlet
+++ b/src/algebra/carten.spad.pamphlet
@@ -574,7 +574,7 @@ contract(epsilon*Tm*epsilon, 1,2) = 2 * determinant m
 @
 <<CartesianTensor.help>>=
 ====================================================================
-CartesianTensor
+CartesianTensor examples
 ====================================================================
 
 CartesianTensor(i0,dim,R) provides Cartesian tensors with components
diff --git a/src/algebra/cycles.spad.pamphlet b/src/algebra/cycles.spad.pamphlet
index c831683..ccc8311 100644
--- a/src/algebra/cycles.spad.pamphlet
+++ b/src/algebra/cycles.spad.pamphlet
@@ -477,8 +477,8 @@ eval(Integers, sf3221)
 @
 <<CycleIndicators.help>>=
 ====================================================================
-\section{CycleIndicators}
-\label{CycleIndicatorsXmpPage}
+CycleIndicators examples
+====================================================================
 
 This section is based upon the paper J. H. Redfield, ``The Theory of
 Group-Reduced Distributions'', American J. Math.,49 (1927) 433-455,
diff --git a/src/algebra/derham.spad.pamphlet b/src/algebra/derham.spad.pamphlet
index 47d2db1..1055a99 100644
--- a/src/algebra/derham.spad.pamphlet
+++ b/src/algebra/derham.spad.pamphlet
@@ -637,7 +637,7 @@ gamma := alpha * beta
 @
 <<DeRhamComplex.help>>=
 ====================================================================
-DeRhamComplex
+DeRhamComplex examples
 ====================================================================
 
 The domain constructor DeRhamComplex creates the class of differential
diff --git a/src/algebra/gaussian.spad.pamphlet b/src/algebra/gaussian.spad.pamphlet
index 744488b..d74aecc 100644
--- a/src/algebra/gaussian.spad.pamphlet
+++ b/src/algebra/gaussian.spad.pamphlet
@@ -688,7 +688,7 @@ factor complex(2,0)
 @
 <<Complex.help>>=
 ====================================================================
-Complex
+Complex examples
 ====================================================================
 
 The Complex constructor implements complex objects over a commutative
diff --git a/src/algebra/gdpoly.spad.pamphlet b/src/algebra/gdpoly.spad.pamphlet
index 6c3ae4f..dd3f68a 100644
--- a/src/algebra/gdpoly.spad.pamphlet
+++ b/src/algebra/gdpoly.spad.pamphlet
@@ -10,6 +10,216 @@
 \tableofcontents
 \eject
 \section{domain GDMP GeneralDistributedMultivariatePolynomial}
+<<GeneralDistributedMultivariatePolynomial.input>>=
+-- gdpoly.spad.pamphlet GeneralDistributedMultivariatePolynomial.input
+)spool GeneralDistributedMultivariatePolynomial.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 10
+(d1,d2,d3) : DMP([z,y,x],FRAC INT) 
+--R 
+--R                                                                   Type: Void
+--E 1
+
+--S 2 of 10
+d1 := -4*z + 4*y**2*x + 16*x**2 + 1 
+--R 
+--R
+--R                 2       2
+--R   (2)  - 4z + 4y x + 16x  + 1
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 2
+
+--S 3 of 10
+d2 := 2*z*y**2 + 4*x + 1 
+--R 
+--R
+--R            2
+--R   (3)  2z y  + 4x + 1
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 3
+
+--S 4 of 10
+d3 := 2*z*x**2 - 2*y**2 - x 
+--R 
+--R
+--R            2     2
+--R   (4)  2z x  - 2y  - x
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 4
+
+--S 5 of 10
+groebner [d1,d2,d3]
+--R 
+--R
+--R   (5)
+--R        1568  6   1264  5    6   4   182  3   2047  2    103      2857
+--R   [z - ---- x  - ---- x  + --- x  + --- x  - ---- x  - ---- x - -----,
+--R        2745       305      305      549       610      2745     10980
+--R     2    112  6    84  5   1264  4    13  3    84  2   1772       2
+--R    y  + ---- x  - --- x  - ---- x  - --- x  + --- x  + ---- x + ----,
+--R         2745      305       305      549      305      2745     2745
+--R     7   29  6   17  4   11  3    1  2   15     1
+--R    x  + -- x  - -- x  - -- x  + -- x  + -- x + -]
+--R          4      16       8      32      16     4
+--R       Type: List DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 5
+
+--S 6 of 10
+(n1,n2,n3) : HDMP([z,y,x],FRAC INT)
+--R 
+--R                                                                   Type: Void
+--E 6
+
+--S 7 of 10
+n1 := d1
+--R 
+--R
+--R          2       2
+--R   (7)  4y x + 16x  - 4z + 1
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 7
+
+--S 8 of 10
+n2 := d2
+--R 
+--R
+--R            2
+--R   (8)  2z y  + 4x + 1
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 8
+
+--S 9 of 10
+n3 := d3
+--R 
+--R
+--R            2     2
+--R   (9)  2z x  - 2y  - x
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 9
+
+--S 10 of 10
+groebner [n1,n2,n3]
+--R 
+--R
+--R   (10)
+--R     4     3   3  2   1     1   4   29  3   1  2   7        9     1
+--R   [y  + 2x  - - x  + - z - -, x  + -- x  - - y  - - z x - -- x - -,
+--R               2      2     8        4      8      4       16     4
+--R       2        1   2      2       1     2    2   1
+--R    z y  + 2x + -, y x + 4x  - z + -, z x  - y  - - x,
+--R                2                  4              2
+--R     2     2     2   1     3
+--R    z  - 4y  + 2x  - - z - - x]
+--R                     4     2
+--RType: List HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 10
+)spool
+)lisp (bye)
+@
+
+<<GeneralDistributedMultivariatePolynomial.help>>=
+====================================================================
+MultivariatePolynomial
+DistributedMultivariatePolynomial
+HomogeneousDistributedMultivariatePolynomial
+GeneralDistributedMultivariatePolynomial
+====================================================================
+
+DistributedMultivariatePolynomial which is abbreviated as DMP and 
+HomogeneousDistributedMultivariatePolynomial, which is abbreviated
+as HDMP, are very similar to MultivariatePolynomial except that 
+they are represented and displayed in a non-recursive manner.
+
+  (d1,d2,d3) : DMP([z,y,x],FRAC INT) 
+                      Type: Void
+
+The constructor DMP orders its monomials lexicographically while
+HDMP orders them by total order refined by reverse lexicographic
+order.
+
+  d1 := -4*z + 4*y**2*x + 16*x**2 + 1 
+            2       2
+   - 4z + 4y x + 16x  + 1
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  d2 := 2*z*y**2 + 4*x + 1 
+       2
+   2z y  + 4x + 1
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  d3 := 2*z*x**2 - 2*y**2 - x 
+       2     2
+   2z x  - 2y  - x
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+These constructors are mostly used in Groebner basis calculations.
+
+  groebner [d1,d2,d3]
+        1568  6   1264  5    6   4   182  3   2047  2    103      2857
+   [z - ---- x  - ---- x  + --- x  + --- x  - ---- x  - ---- x - -----,
+        2745       305      305      549       610      2745     10980
+     2    112  6    84  5   1264  4    13  3    84  2   1772       2
+    y  + ---- x  - --- x  - ---- x  - --- x  + --- x  + ---- x + ----,
+         2745      305       305      549      305      2745     2745
+     7   29  6   17  4   11  3    1  2   15     1
+    x  + -- x  - -- x  - -- x  + -- x  + -- x + -]
+          4      16       8      32      16     4
+       Type: List DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  (n1,n2,n3) : HDMP([z,y,x],FRAC INT)
+                      Type: Void
+
+  n1 := d1
+     2       2
+   4y x + 16x  - 4z + 1
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  n2 := d2
+       2
+   2z y  + 4x + 1
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  n3 := d3
+       2     2
+   2z x  - 2y  - x
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+Note that we get a different Groebner basis when we use the HDMP
+polynomials, as expected.
+
+  groebner [n1,n2,n3]
+     4     3   3  2   1     1   4   29  3   1  2   7        9     1
+   [y  + 2x  - - x  + - z - -, x  + -- x  - - y  - - z x - -- x - -,
+               2      2     8        4      8      4       16     4
+       2        1   2      2       1     2    2   1
+    z y  + 2x + -, y x + 4x  - z + -, z x  - y  - - x,
+                2                  4              2
+     2     2     2   1     3
+    z  - 4y  + 2x  - - z - - x]
+                     4     2
+      Type: List HomogeneousDistributedMultivariatePolynomial([z,y,x],
+                                                           Fraction Integer)
+
+GeneralDistributedMultivariatePolynomial is somewhat more flexible in
+the sense that as well as accepting a list of variables to specify the
+variable ordering, it also takes a predicate on exponent vectors to
+specify the term ordering.  With this polynomial type the user can
+experiment with the effect of using completely arbitrary term orderings.  
+This flexibility is mostly important for algorithms such as Groebner 
+basis calculations which can be very sensitive to term ordering.
+
+See Also:
+o )help Polynomial
+o )help UnivariatePolynomial
+o )help MultivariatePolynomial
+o )help HomogeneousDistributedMultivariatePolynomial
+o )help DistributedMultivariatePolynomial
+o )show GeneralDistributedMultivariatePolynomial
+o $AXIOM/doc/src/algebra/gdpoly.spad.dvi
+
+@
 <<domain GDMP GeneralDistributedMultivariatePolynomial>>=
 )abbrev domain GDMP GeneralDistributedMultivariatePolynomial
 ++ Author: Barry Trager
@@ -262,6 +472,216 @@ GeneralDistributedMultivariatePolynomial(vl,R,E): public == private where
 
 @
 \section{domain DMP DistributedMultivariatePolynomial}
+<<DistributedMultivariatePolynomial.input>>=
+-- gdpoly.spad.pamphlet DistributedMultivariatePolynomial.input
+)spool DistributedMultivariatePolynomial.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 10
+(d1,d2,d3) : DMP([z,y,x],FRAC INT) 
+--R 
+--R                                                                   Type: Void
+--E 1
+
+--S 2 of 10
+d1 := -4*z + 4*y**2*x + 16*x**2 + 1 
+--R 
+--R
+--R                 2       2
+--R   (2)  - 4z + 4y x + 16x  + 1
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 2
+
+--S 3 of 10
+d2 := 2*z*y**2 + 4*x + 1 
+--R 
+--R
+--R            2
+--R   (3)  2z y  + 4x + 1
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 3
+
+--S 4 of 10
+d3 := 2*z*x**2 - 2*y**2 - x 
+--R 
+--R
+--R            2     2
+--R   (4)  2z x  - 2y  - x
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 4
+
+--S 5 of 10
+groebner [d1,d2,d3]
+--R 
+--R
+--R   (5)
+--R        1568  6   1264  5    6   4   182  3   2047  2    103      2857
+--R   [z - ---- x  - ---- x  + --- x  + --- x  - ---- x  - ---- x - -----,
+--R        2745       305      305      549       610      2745     10980
+--R     2    112  6    84  5   1264  4    13  3    84  2   1772       2
+--R    y  + ---- x  - --- x  - ---- x  - --- x  + --- x  + ---- x + ----,
+--R         2745      305       305      549      305      2745     2745
+--R     7   29  6   17  4   11  3    1  2   15     1
+--R    x  + -- x  - -- x  - -- x  + -- x  + -- x + -]
+--R          4      16       8      32      16     4
+--R       Type: List DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 5
+
+--S 6 of 10
+(n1,n2,n3) : HDMP([z,y,x],FRAC INT)
+--R 
+--R                                                                   Type: Void
+--E 6
+
+--S 7 of 10
+n1 := d1
+--R 
+--R
+--R          2       2
+--R   (7)  4y x + 16x  - 4z + 1
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 7
+
+--S 8 of 10
+n2 := d2
+--R 
+--R
+--R            2
+--R   (8)  2z y  + 4x + 1
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 8
+
+--S 9 of 10
+n3 := d3
+--R 
+--R
+--R            2     2
+--R   (9)  2z x  - 2y  - x
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 9
+
+--S 10 of 10
+groebner [n1,n2,n3]
+--R 
+--R
+--R   (10)
+--R     4     3   3  2   1     1   4   29  3   1  2   7        9     1
+--R   [y  + 2x  - - x  + - z - -, x  + -- x  - - y  - - z x - -- x - -,
+--R               2      2     8        4      8      4       16     4
+--R       2        1   2      2       1     2    2   1
+--R    z y  + 2x + -, y x + 4x  - z + -, z x  - y  - - x,
+--R                2                  4              2
+--R     2     2     2   1     3
+--R    z  - 4y  + 2x  - - z - - x]
+--R                     4     2
+--RType: List HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 10
+)spool
+)lisp (bye)
+@
+
+<<DistributedMultivariatePolynomial.help>>=
+====================================================================
+MultivariatePolynomial
+DistributedMultivariatePolynomial
+HomogeneousDistributedMultivariatePolynomial
+GeneralDistributedMultivariatePolynomial
+====================================================================
+
+DistributedMultivariatePolynomial which is abbreviated as DMP and 
+HomogeneousDistributedMultivariatePolynomial, which is abbreviated
+as HDMP, are very similar to MultivariatePolynomial except that 
+they are represented and displayed in a non-recursive manner.
+
+  (d1,d2,d3) : DMP([z,y,x],FRAC INT) 
+                      Type: Void
+
+The constructor DMP orders its monomials lexicographically while
+HDMP orders them by total order refined by reverse lexicographic
+order.
+
+  d1 := -4*z + 4*y**2*x + 16*x**2 + 1 
+            2       2
+   - 4z + 4y x + 16x  + 1
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  d2 := 2*z*y**2 + 4*x + 1 
+       2
+   2z y  + 4x + 1
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  d3 := 2*z*x**2 - 2*y**2 - x 
+       2     2
+   2z x  - 2y  - x
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+These constructors are mostly used in Groebner basis calculations.
+
+  groebner [d1,d2,d3]
+        1568  6   1264  5    6   4   182  3   2047  2    103      2857
+   [z - ---- x  - ---- x  + --- x  + --- x  - ---- x  - ---- x - -----,
+        2745       305      305      549       610      2745     10980
+     2    112  6    84  5   1264  4    13  3    84  2   1772       2
+    y  + ---- x  - --- x  - ---- x  - --- x  + --- x  + ---- x + ----,
+         2745      305       305      549      305      2745     2745
+     7   29  6   17  4   11  3    1  2   15     1
+    x  + -- x  - -- x  - -- x  + -- x  + -- x + -]
+          4      16       8      32      16     4
+       Type: List DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  (n1,n2,n3) : HDMP([z,y,x],FRAC INT)
+                      Type: Void
+
+  n1 := d1
+     2       2
+   4y x + 16x  - 4z + 1
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  n2 := d2
+       2
+   2z y  + 4x + 1
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  n3 := d3
+       2     2
+   2z x  - 2y  - x
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+Note that we get a different Groebner basis when we use the HDMP
+polynomials, as expected.
+
+  groebner [n1,n2,n3]
+     4     3   3  2   1     1   4   29  3   1  2   7        9     1
+   [y  + 2x  - - x  + - z - -, x  + -- x  - - y  - - z x - -- x - -,
+               2      2     8        4      8      4       16     4
+       2        1   2      2       1     2    2   1
+    z y  + 2x + -, y x + 4x  - z + -, z x  - y  - - x,
+                2                  4              2
+     2     2     2   1     3
+    z  - 4y  + 2x  - - z - - x]
+                     4     2
+      Type: List HomogeneousDistributedMultivariatePolynomial([z,y,x],
+                                                           Fraction Integer)
+
+GeneralDistributedMultivariatePolynomial is somewhat more flexible in
+the sense that as well as accepting a list of variables to specify the
+variable ordering, it also takes a predicate on exponent vectors to
+specify the term ordering.  With this polynomial type the user can
+experiment with the effect of using completely arbitrary term orderings.  
+This flexibility is mostly important for algorithms such as Groebner 
+basis calculations which can be very sensitive to term ordering.
+
+See Also:
+o )help Polynomial
+o )help UnivariatePolynomial
+o )help MultivariatePolynomial
+o )help HomogeneousDistributedMultivariatePolynomial
+o )help GeneralDistributedMultivariatePolynomial
+o )show DistributedMultivariatePolynomial
+o $AXIOM/doc/src/algebra/gdpoly.spad.dvi
+
+@
 <<domain DMP DistributedMultivariatePolynomial>>=
 )abbrev domain DMP DistributedMultivariatePolynomial
 ++ Author: Barry Trager
@@ -297,6 +717,216 @@ DistributedMultivariatePolynomial(vl,R): public == private where
 
 @
 \section{domain HDMP HomogeneousDistributedMultivariatePolynomial}
+<<HomogeneousDistributedMultivariatePolynomial.input>>=
+-- gdpoly.spad.pamphlet HomogeneousDistributedMultivariatePolynomial.input
+)spool HomogeneousDistributedMultivariatePolynomial.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 10
+(d1,d2,d3) : DMP([z,y,x],FRAC INT) 
+--R 
+--R                                                                   Type: Void
+--E 1
+
+--S 2 of 10
+d1 := -4*z + 4*y**2*x + 16*x**2 + 1 
+--R 
+--R
+--R                 2       2
+--R   (2)  - 4z + 4y x + 16x  + 1
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 2
+
+--S 3 of 10
+d2 := 2*z*y**2 + 4*x + 1 
+--R 
+--R
+--R            2
+--R   (3)  2z y  + 4x + 1
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 3
+
+--S 4 of 10
+d3 := 2*z*x**2 - 2*y**2 - x 
+--R 
+--R
+--R            2     2
+--R   (4)  2z x  - 2y  - x
+--R            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 4
+
+--S 5 of 10
+groebner [d1,d2,d3]
+--R 
+--R
+--R   (5)
+--R        1568  6   1264  5    6   4   182  3   2047  2    103      2857
+--R   [z - ---- x  - ---- x  + --- x  + --- x  - ---- x  - ---- x - -----,
+--R        2745       305      305      549       610      2745     10980
+--R     2    112  6    84  5   1264  4    13  3    84  2   1772       2
+--R    y  + ---- x  - --- x  - ---- x  - --- x  + --- x  + ---- x + ----,
+--R         2745      305       305      549      305      2745     2745
+--R     7   29  6   17  4   11  3    1  2   15     1
+--R    x  + -- x  - -- x  - -- x  + -- x  + -- x + -]
+--R          4      16       8      32      16     4
+--R       Type: List DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 5
+
+--S 6 of 10
+(n1,n2,n3) : HDMP([z,y,x],FRAC INT)
+--R 
+--R                                                                   Type: Void
+--E 6
+
+--S 7 of 10
+n1 := d1
+--R 
+--R
+--R          2       2
+--R   (7)  4y x + 16x  - 4z + 1
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 7
+
+--S 8 of 10
+n2 := d2
+--R 
+--R
+--R            2
+--R   (8)  2z y  + 4x + 1
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 8
+
+--S 9 of 10
+n3 := d3
+--R 
+--R
+--R            2     2
+--R   (9)  2z x  - 2y  - x
+--R Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 9
+
+--S 10 of 10
+groebner [n1,n2,n3]
+--R 
+--R
+--R   (10)
+--R     4     3   3  2   1     1   4   29  3   1  2   7        9     1
+--R   [y  + 2x  - - x  + - z - -, x  + -- x  - - y  - - z x - -- x - -,
+--R               2      2     8        4      8      4       16     4
+--R       2        1   2      2       1     2    2   1
+--R    z y  + 2x + -, y x + 4x  - z + -, z x  - y  - - x,
+--R                2                  4              2
+--R     2     2     2   1     3
+--R    z  - 4y  + 2x  - - z - - x]
+--R                     4     2
+--RType: List HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+--E 10
+)spool
+)lisp (bye)
+@
+
+<<HomogeneousDistributedMultivariatePolynomial.help>>=
+====================================================================
+MultivariatePolynomial
+DistributedMultivariatePolynomial
+HomogeneousDistributedMultivariatePolynomial
+GeneralDistributedMultivariatePolynomial
+====================================================================
+
+DistributedMultivariatePolynomial which is abbreviated as DMP and 
+HomogeneousDistributedMultivariatePolynomial, which is abbreviated
+as HDMP, are very similar to MultivariatePolynomial except that 
+they are represented and displayed in a non-recursive manner.
+
+  (d1,d2,d3) : DMP([z,y,x],FRAC INT) 
+                      Type: Void
+
+The constructor DMP orders its monomials lexicographically while
+HDMP orders them by total order refined by reverse lexicographic
+order.
+
+  d1 := -4*z + 4*y**2*x + 16*x**2 + 1 
+            2       2
+   - 4z + 4y x + 16x  + 1
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  d2 := 2*z*y**2 + 4*x + 1 
+       2
+   2z y  + 4x + 1
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  d3 := 2*z*x**2 - 2*y**2 - x 
+       2     2
+   2z x  - 2y  - x
+            Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+These constructors are mostly used in Groebner basis calculations.
+
+  groebner [d1,d2,d3]
+        1568  6   1264  5    6   4   182  3   2047  2    103      2857
+   [z - ---- x  - ---- x  + --- x  + --- x  - ---- x  - ---- x - -----,
+        2745       305      305      549       610      2745     10980
+     2    112  6    84  5   1264  4    13  3    84  2   1772       2
+    y  + ---- x  - --- x  - ---- x  - --- x  + --- x  + ---- x + ----,
+         2745      305       305      549      305      2745     2745
+     7   29  6   17  4   11  3    1  2   15     1
+    x  + -- x  - -- x  - -- x  + -- x  + -- x + -]
+          4      16       8      32      16     4
+       Type: List DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  (n1,n2,n3) : HDMP([z,y,x],FRAC INT)
+                      Type: Void
+
+  n1 := d1
+     2       2
+   4y x + 16x  - 4z + 1
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  n2 := d2
+       2
+   2z y  + 4x + 1
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+  n3 := d3
+       2     2
+   2z x  - 2y  - x
+ Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
+
+Note that we get a different Groebner basis when we use the HDMP
+polynomials, as expected.
+
+  groebner [n1,n2,n3]
+     4     3   3  2   1     1   4   29  3   1  2   7        9     1
+   [y  + 2x  - - x  + - z - -, x  + -- x  - - y  - - z x - -- x - -,
+               2      2     8        4      8      4       16     4
+       2        1   2      2       1     2    2   1
+    z y  + 2x + -, y x + 4x  - z + -, z x  - y  - - x,
+                2                  4              2
+     2     2     2   1     3
+    z  - 4y  + 2x  - - z - - x]
+                     4     2
+      Type: List HomogeneousDistributedMultivariatePolynomial([z,y,x],
+                                                           Fraction Integer)
+
+GeneralDistributedMultivariatePolynomial is somewhat more flexible in
+the sense that as well as accepting a list of variables to specify the
+variable ordering, it also takes a predicate on exponent vectors to
+specify the term ordering.  With this polynomial type the user can
+experiment with the effect of using completely arbitrary term orderings.  
+This flexibility is mostly important for algorithms such as Groebner 
+basis calculations which can be very sensitive to term ordering.
+
+See Also:
+o )help Polynomial
+o )help UnivariatePolynomial
+o )help MultivariatePolynomial
+o )help DistributedMultivariatePolynomial
+o )help GeneralDistributedMultivariatePolynomial
+o )show HomogeneousDistributedMultivariatePolynomial
+o $AXIOM/doc/src/algebra/gdpoly.spad.dvi
+
+@
 <<domain HDMP HomogeneousDistributedMultivariatePolynomial>>=
 )abbrev domain HDMP HomogeneousDistributedMultivariatePolynomial
 ++ Author: Barry Trager
@@ -376,3 +1006,4 @@ HomogeneousDistributedMultivariatePolynomial(vl,R): public == private where
 \bibitem{1} nothing
 \end{thebibliography}
 \end{document}
+
diff --git a/src/algebra/sf.spad.pamphlet b/src/algebra/sf.spad.pamphlet
index f8a13b3..8ed563d 100644
--- a/src/algebra/sf.spad.pamphlet
+++ b/src/algebra/sf.spad.pamphlet
@@ -770,6 +770,183 @@ complex number.)
 
 
 \end{quote}
+<<DoubleFloat.input>>=
+-- sf.spad.pamphlet DoubleFloat.input
+)spool DoubleFloat.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 10
+2.71828
+--R 
+--R
+--R   (1)  2.71828
+--R                                                                  Type: Float
+--E 1
+
+--S 2 of 10
+2.71828@DoubleFloat
+--R 
+--R
+--R   (2)  2.71828
+--R                                                            Type: DoubleFloat
+--E 2
+
+--S 3 of 10
+2.71828 :: DoubleFloat
+--R 
+--R
+--R   (3)  2.71828
+--R                                                            Type: DoubleFloat
+--E 3
+
+--S 4 of 10
+eApprox : DoubleFloat := 2.71828
+--R 
+--R
+--R   (4)  2.71828
+--R                                                            Type: DoubleFloat
+--E 4
+
+--S 5 of 10
+avg : List DoubleFloat -> DoubleFloat
+--R 
+--R                                                                   Type: Void
+--E 5
+
+--S 6 of 10
+avg l ==
+  empty? l => 0 :: DoubleFloat
+  reduce(_+,l) / #l
+--R 
+--R                                                                   Type: Void
+--E 6
+
+--S 7 of 10
+avg []
+--R 
+--R   Compiling function avg with type List DoubleFloat -> DoubleFloat 
+--R
+--R   (7)  0.
+--R                                                            Type: DoubleFloat
+--E 7
+
+--S 8 of 10
+avg [3.4,9.7,-6.8]
+--R 
+--R
+--R   (8)  2.1000000000000001
+--R                                                            Type: DoubleFloat
+--E 8
+
+--S 9 of 10
+cos(3.1415926)$DoubleFloat
+--R 
+--R
+--R   (9)  -0.99999999999999856
+--R                                                            Type: DoubleFloat
+--E 9
+
+--S 10 of 10
+cos(3.1415926 :: DoubleFloat)
+--R 
+--R
+--R   (10)  -0.99999999999999856
+--R                                                            Type: DoubleFloat
+--E 10
+)spool
+)lisp (bye)
+@
+
+<<DoubleFloat.help>>=
+====================================================================
+DoubleFloat examples
+====================================================================
+
+Axiom provides two kinds of floating point numbers.  The domain Float
+(abbreviation FLOAT) implements a model of arbitrary precision
+floating point numbers.  The domain DoubleFloat (abbreviation DFLOAT)
+is intended to make available hardware floating point arithmetic in
+Axiom.  The actual model of floating point DoubleFloat that provides
+is system-dependent.  For example, on the IBM system 370 Axiom uses
+IBM double precision which has fourteen hexadecimal digits of
+precision or roughly sixteen decimal digits.  Arbitrary precision
+floats allow the user to specify the precision at which arithmetic
+operations are computed.  Although this is an attractive facility, it
+comes at a cost. Arbitrary-precision floating-point arithmetic
+typically takes twenty to two hundred times more time than hardware
+floating point.
+
+The usual arithmetic and elementary functions are available for
+DoubleFloat.  By default, floating point numbers that you enter into
+Axiom are of type Float.
+
+  2.71828
+   2.71828 
+                      Type: Float
+
+You must therefore tell Axiom that you want to use DoubleFloat values
+and operations.  The following are some conservative guidelines for
+getting Axiom to use DoubleFloat.
+
+To get a value of type DoubleFloat, use a target with @, ...
+
+  2.71828@DoubleFloat
+   2.71828 
+                      Type: DoubleFloat
+
+a conversion, ...
+
+  2.71828 :: DoubleFloat
+   2.71828 
+                      Type: DoubleFloat
+
+or an assignment to a declared variable.  It is more efficient if you
+use a target rather than an explicit or implicit conversion.
+
+  eApprox : DoubleFloat := 2.71828
+   2.71828 
+                      Type: DoubleFloat
+
+You also need to declare functions that work with DoubleFloat.
+
+  avg : List DoubleFloat -> DoubleFloat
+                      Type: Void
+
+  avg l ==
+    empty? l => 0 :: DoubleFloat
+    reduce(_+,l) / #l
+                      Type: Void
+
+  avg []
+   0.
+                      Type: DoubleFloat
+
+  avg [3.4,9.7,-6.8]
+   2.1000000000000001
+                      Type: DoubleFloat
+
+Use package-calling for operations from DoubleFloat unless the
+arguments themselves are already of type DoubleFloat.
+
+  cos(3.1415926)$DoubleFloat
+   -0.99999999999999856
+                      Type: DoubleFloat
+
+  cos(3.1415926 :: DoubleFloat)
+   -0.99999999999999856
+                      Type: DoubleFloat
+
+By far, the most common usage of DoubleFloat is for functions to be
+graphed.
+
+
+See Also:
+0 )help Float
+o )show DoubleFloat
+o $AXIOM/doc/src/algebra/sf.spad.dvi
+
+@
 <<domain DFLOAT DoubleFloat>>=
 )abbrev domain DFLOAT DoubleFloat
 ++ Author: Michael Monagan
diff --git a/src/algebra/table.spad.pamphlet b/src/algebra/table.spad.pamphlet
index 4d07304..fc97720 100644
--- a/src/algebra/table.spad.pamphlet
+++ b/src/algebra/table.spad.pamphlet
@@ -115,6 +115,109 @@ Table(Key: SetCategory, Entry: SetCategory):Exports == Implementation where
 
 @
 \section{domain EQTBL EqTable}
+<<EqTable.input>>=
+-- table.spad.pamphlet EqTable.input
+)spool EqTable.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 6
+e: EqTable(List Integer, Integer) := table()
+--R 
+--R
+--R   (1)  table()
+--R                                          Type: EqTable(List Integer,Integer)
+--E 1
+
+--S 2 of 6
+l1 := [1,2,3]
+--R 
+--R
+--R   (2)  [1,2,3]
+--R                                                   Type: List PositiveInteger
+--E 2
+
+--S 3 of 6
+l2 := [1,2,3]
+--R 
+--R
+--R   (3)  [1,2,3]
+--R                                                   Type: List PositiveInteger
+--E 3
+
+--S 4 of 6
+e.l1 := 111
+--R 
+--R
+--R   (4)  111
+--R                                                        Type: PositiveInteger
+--E 4
+
+--S 5 of 6
+e.l2 := 222
+--R 
+--R
+--R   (5)  222
+--R                                                        Type: PositiveInteger
+--E 5
+
+--S 6 of 6
+e.l1
+--R 
+--R
+--R   (6)  111
+--R                                                        Type: PositiveInteger
+--E 6
+)spool
+)lisp (bye)
+@
+<<EqTable.help>>=
+====================================================================
+EqTable examples
+====================================================================
+
+The EqTable domain provides tables where the keys are compared using
+eq?.  Keys are considered equal only if they are the same instance of
+a structure.  This is useful if the keys are themselves updatable
+structures.  Otherwise, all operations are the same as for type Table.
+
+The operation table is here used to create a table where the keys are
+lists of integers.
+
+  e: EqTable(List Integer, Integer) := table()
+   table()
+                    Type: EqTable(List Integer,Integer)
+
+These two lists are equal according to =, but not according to eq?.
+
+  l1 := [1,2,3]
+   [1,2,3]
+                    Type: List PositiveInteger
+
+  l2 := [1,2,3]
+   [1,2,3]
+                    Type: List PositiveInteger
+Because the two lists are not eq?, separate values can be stored under
+each.
+
+  e.l1 := 111
+   111
+                    Type: PositiveInteger
+
+  e.l2 := 222
+   222
+                    Type: PositiveInteger
+
+  e.l1
+   111
+                    Type: PositiveInteger
+
+See Also:
+o )help Table
+o )show EqTable
+o $AXIOM/doc/src/algebra/table.spad.dvi
+
+@
 <<domain EQTBL EqTable>>=
 )abbrev domain EQTBL EqTable
 ++ Author: Stephen M. Watt
diff --git a/src/doc/spadhelp.pamphlet b/src/doc/spadhelp.pamphlet
index f0e163d..6e03ff3 100644
--- a/src/doc/spadhelp.pamphlet
+++ b/src/doc/spadhelp.pamphlet
@@ -1482,12 +1482,17 @@ syntax        trace      undo       what       while
 
 Available algebra help topics are:
 
-AssociationList   BalancedBinaryTree   BasicOperator
-BinaryExpansion   BinarySearchTree     CardinalNumber
-CartesianTensor   Character            CharacterClass
-CliffordAlgebra   Complex              ContinuedFraction
-CycleIndicators   DeRhamComplex        DecimalExpansion
-
+AssociationList (ALIST)    BalancedBinaryTree (BBTREE)
+BasicOperator (BOP)        BinaryExpansion (BINARY)
+BinarySearchTree (BSTREE)  CardinalNumber (CARD)
+CartesianTensor (CARTEN)   Character (CHAR)
+CharacterClass (CCLASS)    CliffordAlgebra (CLIF)
+Complex (COMPLEX)          ContinuedFraction (CONTFRAC)
+CycleIndicators (CYCLES)   DeRhamComplex (DERHAM)
+DecimalExpansion (DECIMAL) DistributedMultivariatePolynomial (DMP)
+DoubleFloat (DFLOAT)       EqTable (EQTBL)
+GeneralDistributedMultivariatePolynomial (GDMP)
+HomogeneousDistributedMultivariatePolynomial (HDMP)
 
 @ 
 
\start
Date: Mon, 27 Aug 2007 02:50:55 -0500
From: Tim Daly
To: list
Subject: 20070826.02.tpd.patch applied to silver

diff --git a/changelog b/changelog
index fbb5d26..1aaaa04 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,15 @@
+20070826 tpd src/doc/spadhelp add Expression
+20070826 tpd src/algebra/Makefile add Expression.help 
+20070826 tpd src/algebra/expr.spad add Expression.help 
+20070826 tpd src/algebra/expr.spad add Expression.input
+20070826 tpd src/doc/spadhelp add Edit
+20070826 tpd src/algebra/Makefile add Exit.help 
+20070826 tpd src/algebra/void.spad add Exit.help 
+20070826 tpd src/algebra/void.spad add Exit.input
+20070826 tpd src/doc/spadhelp add Equation
+20070826 tpd src/algebra/Makefile add Equation.help 
+20070826 tpd src/algebra/equation2.spad add Equation.help 
+20070826 tpd src/algebra/equation2.spad add Equation.input
 20070825 tpd doc/src/algebra/spadhelp add all abbreviation files
 20070825 tpd src/doc/spadhelp add all abbreviations
 20070825 tpd src/doc/spadhelp add DoubleFloat
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index 542e42d..5cfb29e 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -2027,7 +2027,7 @@ SPADHELP=\
  ${HELP}/Complex.help          ${HELP}/ContinuedFraction.help \
  ${HELP}/CycleIndicators.help  ${HELP}/DeRhamComplex.help \
  ${HELP}/DecimalExpansion.help ${HELP}/DoubleFloat.help \
- ${HELP}/EqTable.help \
+ ${HELP}/EqTable.help          ${HELP}/Equation.help \
  ${HELP}/DistributedMultivariatePolynomial.help \
  ${HELP}/GeneralDistributedMultivariatePolynomial.help \
  ${HELP}/HomogeneousDistributedMultivariatePolynomial.help
@@ -2049,7 +2049,7 @@ REGRESS=\
  Complex.regress          ContinuedFraction.regress \
  CycleIndicators.regress  DeRhamComplex.regress \
  DecimalExpansion.regress DoubleFloat.regress \
- EqTable.regress \
+ EqTable.regress          Equation.regress \
  DistributedMultivariatePolynomial.regress \
  GeneralDistributedMultivariatePolynomial.regress \
  HomogeneousDistributedMultivariatePolynomial.regress 
@@ -2242,6 +2242,14 @@ ${HELP}/HomogeneousDistributedMultivariatePolynomial.help: \
            ${IN}/gdpoly.spad.pamphlet \
             >${INPUT}/HomogeneousDistributedMultivariatePolynomial.input
 
+${HELP}/Equation.help: ${IN}/equation2.spad.pamphlet
+	@echo 7020 create Equation.help from ${IN}/equation2.spad.pamphlet
+	@${TANGLE} -R"Equation.help" ${IN}/equation2.spad.pamphlet \
+            >${HELP}/Equation.help
+	@cp ${HELP}/Equation.help ${HELP}/EQTBL.help
+	@${TANGLE} -R"Equation.input" ${IN}/equation2.spad.pamphlet \
+            >${INPUT}/Equation.input
+
 @
 
 \section{The Makefile}
diff --git a/src/algebra/equation2.spad.pamphlet b/src/algebra/equation2.spad.pamphlet
index 8ae385b..ecabdd9 100644
--- a/src/algebra/equation2.spad.pamphlet
+++ b/src/algebra/equation2.spad.pamphlet
@@ -10,6 +10,161 @@
 \tableofcontents
 \eject
 \section{domain EQ Equation}
+<<Equation.input>>=
+-- equation2.spad.pamphlet Equation.input
+)spool Equation.output
+)set message test on
+)set message auto off
+)clear all
+eq1 := 3*x + 4*y = 5 
+ 
+
+   (1)  4y + 3x= 5
+                                            Type: Equation Polynomial Integer
+eq2 := 2*x + 2*y = 3 
+ 
+
+   (2)  2y + 2x= 3
+                                            Type: Equation Polynomial Integer
+lhs eq1
+ 
+
+   (3)  4y + 3x
+                                                     Type: Polynomial Integer
+rhs eq1
+ 
+
+   (4)  5
+                                                     Type: Polynomial Integer
+eq1 + eq2 
+ 
+
+   (5)  6y + 5x= 8
+                                            Type: Equation Polynomial Integer
+eq1 * eq2 
+ 
+
+          2             2
+   (6)  8y  + 14x y + 6x = 15
+                                            Type: Equation Polynomial Integer
+2*eq2 - eq1
+ 
+
+   (7)  x= 1
+                                            Type: Equation Polynomial Integer
+eq1**2
+ 
+
+           2             2
+   (8)  16y  + 24x y + 9x = 25
+                                            Type: Equation Polynomial Integer
+if x+1 = y then "equal" else "unequal"
+ 
+
+   (9)  "unequal"
+                                                                 Type: String
+eqpol := x+1 = y 
+ 
+
+   (10)  x + 1= y
+                                            Type: Equation Polynomial Integer
+if eqpol then "equal" else "unequal"
+ 
+
+   (11)  "unequal"
+                                                                 Type: String
+eqpol::Boolean
+ 
+
+   (12)  false
+                                                                Type: Boolean
+)spool
+)lisp (bye)
+@
+<<Equation.help>>=
+====================================================================
+Equation examples
+====================================================================
+
+The Equation domain provides equations as mathematical objects.  These
+are used, for example, as the input to various solve operations.
+
+Equations are created using the equals symbol, =.
+
+  eq1 := 3*x + 4*y = 5 
+   4y + 3x= 5
+                         Type: Equation Polynomial Integer
+
+  eq2 := 2*x + 2*y = 3 
+   2y + 2x= 3
+                         Type: Equation Polynomial Integer
+
+The left- and right-hand sides of an equation are accessible using
+the operations lhs and rhs.
+
+  lhs eq1
+   4y + 3x
+                         Type: Polynomial Integer
+
+  rhs eq1
+   5
+                         Type: Polynomial Integer
+
+Arithmetic operations are supported and operate on both sides of the
+equation.
+
+  eq1 + eq2 
+   6y + 5x= 8
+                         Type: Equation Polynomial Integer
+
+  eq1 * eq2 
+     2             2
+   8y  + 14x y + 6x = 15
+                         Type: Equation Polynomial Integer
+
+  2*eq2 - eq1
+   x= 1
+                         Type: Equation Polynomial Integer
+
+Equations may be created for any type so the arithmetic operations
+will be defined only when they make sense.  For example, exponentiation 
+is not defined for equations involving non-square matrices.
+
+  eq1**2
+      2             2
+   16y  + 24x y + 9x = 25
+                          Type: Equation Polynomial Integer
+
+Note that an equals symbol is also used to test for equality of values
+in certain contexts.  For example, x+1 and y are unequal as polynomials.
+
+  if x+1 = y then "equal" else "unequal"
+   "unequal"
+                           Type: String
+
+  eqpol := x+1 = y 
+   x + 1= y
+                           Type: Equation Polynomial Integer
+
+If an equation is used where a Boolean value is required, then
+it is evaluated using the equality test from the operand type.
+
+  if eqpol then "equal" else "unequal"
+   "unequal"
+                           Type: String
+
+If one wants a Boolean value rather than an equation, all one has to
+do is ask!
+
+  eqpol::Boolean
+   false
+                           Type: Boolean
+
+See Also:
+o )show Equation
+o $AXIOM/doc/src/algebra/equation2.spad.dvi
+
+@
 <<domain EQ Equation>>=
 )abbrev domain EQ Equation
 --FOR THE BENEFIT  OF LIBAX0 GENERATION
diff --git a/src/doc/spadhelp.pamphlet b/src/doc/spadhelp.pamphlet
index 6e03ff3..ed3bde9 100644
--- a/src/doc/spadhelp.pamphlet
+++ b/src/doc/spadhelp.pamphlet
@@ -1491,6 +1491,7 @@ Complex (COMPLEX)          ContinuedFraction (CONTFRAC)
 CycleIndicators (CYCLES)   DeRhamComplex (DERHAM)
 DecimalExpansion (DECIMAL) DistributedMultivariatePolynomial (DMP)
 DoubleFloat (DFLOAT)       EqTable (EQTBL)
+Equation (EQ)
 GeneralDistributedMultivariatePolynomial (GDMP)
 HomogeneousDistributedMultivariatePolynomial (HDMP)
 

\start
Date: Mon, 27 Aug 2007 03:01:04 -0500
From: Tim Daly
To: list
Subject: 20070826.03.tpd.patch applied to silver

diff --git a/Makefile b/Makefile
index 86c7905..7458a7b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION="Axiom (May 2007)"
+VERSION="Axiom (Sept 2007)"
 SPD=$(shell pwd)
 SYS=$(notdir $(AXIOM))
 SPAD=${SPD}/mnt/${SYS}
diff --git a/Makefile.pamphlet b/Makefile.pamphlet
index 2109665..af8ef5f 100644
--- a/Makefile.pamphlet
+++ b/Makefile.pamphlet
@@ -292,7 +292,7 @@ The DOCUMENT variable is now set to replace the direct call
 to the document command. This will allow it to be
 changed on the command line.
 <<environment>>=
-VERSION="Axiom (May 2007)"
+VERSION="Axiom (Sept 2007)"
 SPD=$(shell pwd)
 SYS=$(notdir $(AXIOM))
 SPAD=${SPD}/mnt/${SYS}
diff --git a/changelog b/changelog
index 1aaaa04..edb5476 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,6 @@
+20070826 tpd --patch-51 (Sept 2007) release
+20070826 tpd Makefile.pamphlet update version to Sept 2007
+20070826 tpd Makefile update version to Sept 2007
 20070826 tpd src/doc/spadhelp add Expression
 20070826 tpd src/algebra/Makefile add Expression.help 
 20070826 tpd src/algebra/expr.spad add Expression.help 

\start
Date: Mon, 27 Aug 2007 02:41:38 -0500
From: Tim Daly
To: list
Subject: 20070822.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 282bd89..180fc5c 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070821 tpd src/sman/bookvol6 document the axiom shell script
 20070821 tpd src/sman/bookvol6 add axiom command
 20070821 tpd src/sman/Makefile add axiom command
 20070821 tpd src/etc/axiom remove axiom command
diff --git a/src/sman/bookvol6.pamphlet b/src/sman/bookvol6.pamphlet
index ade0c54..d80388b 100644
--- a/src/sman/bookvol6.pamphlet
+++ b/src/sman/bookvol6.pamphlet
@@ -25,47 +25,50 @@ $$
 \center{\large{VOLUME 6: AXIOM COMMAND}}
 \end{titlepage}
 \pagenumbering{roman}
-\begin{verbatim}
+
 Portions Copyright (c) 2005 Timothy Daly
 
 The Blue Bayou image Copyright (c) 2004 Jocelyn Guidry
 
 Portions Copyright (c) 2004 Martin Dunstan
 
-Portions Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
-All rights reserved.
+Portions Copyright (c) 1991-2002, The Numerical ALgorithms Group 
+Ltd. All rights reserved.
 
 This book and the Axiom software is licensed as follows:
 
-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.
-
-\end{verbatim}
+Redistribution and use in source and binary forms, with or 
+without modification, are permitted provided that the following 
+conditions are met:
+\begin{itemize}
+\item Redistributions of source code must retain the above 
+      copyright notice, this list of conditions and the following 
+      disclaimer.
+
+\item 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.
+
+\item 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.
+\end{itemize}
+
+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.
 
 Inclusion of names in the list of credits is based on historical
 information and is as accurate as possible. Inclusion of names
@@ -194,86 +197,408 @@ November 10, 2003 ((iHy))
 \pagenumbering{arabic}
 \setcounter{chapter}{0} % Chapter 1
 \chapter{Overview}
-The superman process, called sman, is normally invoked from the
-axiom shell script in order to start a tree of subprocesses.
+The axiom system consists of a set of processes managed by the
+superman process.  The superman process, called sman, is normally
+invoked from the axiom shell script in order to start a tree of
+subprocesses.
+
+The {\tt axiom} command is a shell script that collects the 
+command line options for the {\tt sman} process, sets some shell
+variables, and then invokes {\tt sman}. 
+
+The {\tt sman} process starts the following tree of processes:
+\begin{verbatim}
+     --xterm---bash---sman-|-AXIOMsys
+                           |-clef---spadclient
+                           |-hypertex
+                           |-session
+                           |-sman
+                           |-viewman
+\end{verbatim}
 
 \chapter{The axiom Command}
+The {\tt axiom} command starts everything for Axiom. The options
+for the {\tt axiom} command are:
+\begin{verbatim}
+axiom
+  [-ht    |-noht]      whether to use HyperDoc
+  [-gr    |-nogr]      whether to use Graphics
+  [-clef  |-noclef]    whether to use Clef
+  [-nonag |-nag]       whether to use NAG
+  [-noiw  |-iw]        start in interpreter in a separate window
+  [-ihere |-noihere]   start an interpreter in this window
+  [-nox]               don't use X Windows
+  [-go  |-nogo]        whether to start system
+  [-ws wsname]         use named workspace
+  [-list]              list workspaces only
+  [-grprog fname]      use named program for Graphics
+  [-nagprog fname]     use named program for Nag
+  [-htprog fname]      use named program for HyperDoc
+  [-clefprog fname]    use named program for Clef
+  [-sessionprog fname] use named program for session
+  [-clientprog fname]  use named program for spadclient
+  [-h]                 show usage
+\end{verbatim}
+
+In detail, the command options are:
+\subsection{[-ht $\vert$ -noht]}
+\begin{verbatim}
+  [-ht    |-noht]      whether to use HyperDoc
+\end{verbatim}
+{\tt Hyperdoc}\cite{7} is the documentation tool for Axiom. The
+{\tt -ht} option, enabled by default, will start this tool.
+See Jenks\cite{1} Chapter 3 for further information on the 
+{\tt hyperdoc} subsystem.
+
+\subsection{[-gr $\vert$ -nogr]}
+\begin{verbatim}
+  [-gr    |-nogr]      whether to use Graphics
+\end{verbatim}
+The {\tt graphics}\cite{8} subsystem is enabled using the 
+{\tt -gr} option, enabled by default. Graphics will appear as a
+result of a draw command, such as
+\begin{verbatim}
+ draw(sin(x),x=0..1)
+\end{verbatim}
+Note that attempting to use draw commands when the graphics is
+disabled will simply hang the interpreter waiting for a response.
+See Jenks\cite{1} Chapter 7 for further information on the 
+{\tt graphics} subsystem.
+
+\subsection{[-clef $\vert$ -noclef]}
+\begin{verbatim}
+  [-clef  |-noclef]    whether to use Clef
+\end{verbatim}
+The {\tt clef} (Command Line Edit Facility) allows for command completion.
+The list of command completion strings is in the last chapter of this
+document. If {\tt clef}, enabled by default, is running then you can type:
+\begin{verbatim}
+ x:Dena<tab>
+\end{verbatim}
+and this will automatically be expanded to:
+\begin{verbatim}
+ x:DenavitHartenbergMatrix
+\end{verbatim}
+
+The {\tt clef} program also allows command line editing. The commands are
+special keyboard keys.
+\begin{itemize}
+\item HOME move to beginning of the line
+\item END move to the end of the line
+\item CTRL-END delete to end of the line
+\item TAB command completion (multiple tabs give new choices)
+\item UPARROW move back thru commands
+\item DOWNARROW move forward thru commands
+\item LEFTARROW move left on the line
+\item RIGHTARROW move right on the line
+\item INSERT toggle insert/overstrike
+\end{itemize}
+See Jenks\cite{1} page 21 for further information on the {\tt clef} command.
+
+\subsection{[-nonag $\vert$ -nag]}
+\begin{verbatim}
+  [-nonag |-nag]       whether to use NAG
+\end{verbatim}
+The {\tt nag} option, disabled by default, will attempt to start
+the {\tt nagman} program in the \$AXIOM/lib subdirectory. Since
+the open source version does not include the NAG numeric libraries
+this option does not work.
+
+\subsection{[-noiw $\vert$ -iw]}
+\begin{verbatim}
+  [-noiw  |-iw]        start in interpreter in a separate window
+\end{verbatim}
+The {\tt iw} option, disabled by default, will start a second
+interpreter in its own window with its own frame. The fact that
+the second interpreter is in its own frame can be seen using the
+{\tt )frame} command. For instance, if you type
+\begin{verbatim}
+ axiom -iw
+\end{verbatim}
+there will be two interpreter windows available, one in the current
+window and one in a new window. In the current window if you type:
+\begin{verbatim}
+ )frame names
+\end{verbatim}
+you will see:
+\begin{verbatim}
+   The names of the existing frames are:
+            frame0 
+            frame1 
+            initial 
+      The current frame is the first one listed.
+\end{verbatim}
+
+In the second window, if you type
+\begin{verbatim}
+ )frame names
+\end{verbatim}
+you will see:
+\begin{verbatim}
+   The names of the existing frames are:
+            frame1 
+            frame0 
+            initial 
+      The current frame is the first one listed.
+\end{verbatim}
+Setting
+\begin{verbatim}
+ x:=3
+\end{verbatim}
+in the second window will set the variable $x$ in the frame {\tt frame1}.
+Switching to the first window and typing:
+\begin{verbatim}
+ x
+\end{verbatim}
+gives:
+\begin{verbatim}
+
+   (1)  x
+                             Type: Variable x
+\end{verbatim}
+since the first window is in {\tt frame0} and the variable $x$ is
+defined in {\tt frame1}.
+But we can switch frames in the first window using
+\begin{verbatim}
+ )frame next
+\end{verbatim}
+and then
+\begin{verbatim}
+ x
+\end{verbatim}
+gives:
+\begin{verbatim}
+
+   (2)  3
+                             Type: PositiveInteger
+\end{verbatim}
+and now the two windows share the same frame space. 
+See Jenks\cite{1} page 579 for further information on the {\tt frame} command.
+
+\subsection{[-ihere $\vert$ -noihere]}
+\begin{verbatim}
+  [-ihere |-noihere]   start an interpreter in this window
+\end{verbatim}
+This option determines whether Axiom will start in the current window.
+Using this option alone is not particularly useful and it is generally
+used in combination with the {\tt -iw} option:
+\begin{verbatim}
+ axiom -noihere -iw &
+\end{verbatim}
+
+However, used alone, as in:
+\begin{verbatim}
+ axiom -noihere &
+\end{verbatim}
+it will start Axiom and show the Hyperdoc window. Graphics will also
+work from the Hyperdoc pages.
+
+\subsection{[-nox]}
+\begin{verbatim}
+  [-nox]               don't use X Windows
+\end{verbatim}
+allows Axiom to start the interpreter without Hyperdoc or the graphics
+subsystem. This is useful for starting Axiom in an emacs buffer.
+
+\subsection{[-go $\vert$ -nogo]}
+\begin{verbatim}
+  [-go  |-nogo]        whether to start system
+\end{verbatim}
+uses the {\tt -go} option, enabled by default, controls whether
+the system starts from the command line. If the {\tt -nogo}
+option is chosen the system prints the command line that would
+have been issued. This is useful for finding out what the command
+line options to {\tt sman} will be. For instance:
+\begin{verbatim}
+ axiom -nogo -iw
+\end{verbatim}
+does not start Axiom but types out:
+\begin{verbatim}
+Would now start the processes.
+exec ~/mnt/linux/bin/sman -iw -ws ~/mnt/linux/bin/AXIOMsys
+\end{verbatim}
+
+\subsection{[-ws wsname]}
+\begin{verbatim}
+  [-ws wsname]         use named workspace
+\end{verbatim}
+In the {\tt -nogo} command above you can see that the default
+workspace name is 
+\begin{verbatim}
+-ws ~/mnt/linux/bin/AXIOMsys
+\end{verbatim}
+This option allows you to change that. This is useful for
+debugging new system builds. During build a debugging version
+of Axiom is created in the {\tt obj/linux/bin} directory. The
+{\tt debugsys} image uses interpreted lisp code rather than
+compiled code. This makes it possible to do deep debugging. To
+use this workspace you would incant:
+\begin{verbatim}
+ cd youraxiombuild
+ export AXIOM=`pwd`/mnt/linux
+ export PATH=$AXIOM/bin:$PATH
+ axiom -ws obj/linux/bin/debugsys
+\end{verbatim}
+
+
+\subsection{[-list]}
+\begin{verbatim}
+  [-list]              list workspaces only
+\end{verbatim}
+shows you the executable workspaces. Generally in a built system
+there is only one, called\\
+{\tt \$AXIOM/bin/AXIOMsys}.
+
+\subsection{[-grprog fname]}
+\begin{verbatim}
+  [-grprog fname]      use named program for Graphics
+\end{verbatim}
+allows you to specify which program to use for the graphics.
+By default this is\\
+{\tt \$AXIOM/lib/viewman}.
+
+\subsection{[-nagprog fname]}
+\begin{verbatim}
+  [-nagprog fname]     use named program for Nag
+\end{verbatim}
+allows you to specify which program to use for the NAG library
+connection. By default this is\\
+{\tt \$AXIOM/lib/nagman} but it is disabled by default.
+
+\subsection{[-htprog fname]}
+\begin{verbatim}
+  [-htprog fname]      use named program for Hyperdoc
+\end{verbatim}
+allows you tp specify which program to use for Hyperdoc. By
+default it is\\
+{\tt \$AXIOM/bin/hypertex -s}.
+
+\subsection{[-clefprog fname]}
+\begin{verbatim}
+  [-clefprog fname]    use named program for Clef
+\end{verbatim}
+allows you to specify which program to use for clef. By default
+it is\\ 
+{\tt \$AXIOM/bin/clef -f \$AXIOM/lib/command.list -e}.
+
+\subsection{[-sessionprog fname]}
+\begin{verbatim}
+  [-sessionprog fname] use named program for session
+\end{verbatim}
+allows you to specify the session manager program. By default it is\\
+{\tt \$AXIOM/lib/session}.
+
+\subsection{[-clientprog fname]}
+\begin{verbatim}
+  [-clientprog fname]  use named program for spadclient
+\end{verbatim}
+allows you to specify the spadclient program. By default it is\\
+{\tt \$AXIOM/lib/spadclient}.
+
+\subsection{[-h]}
+\begin{verbatim}
+  [-h]                 show usage
+\end{verbatim}
+
 <<axiomcmd>>=
 #!/bin/sh
 
-# Start everything for Axiom.
-#
-# axiom
-#      [-ht   |-noht]	    whether to use HyperDoc
-#      [-gr   |-nogr]	    whether to use Graphics
-#      [-clef |-noclef]	    whether to use Clef
-#      [-nag |-nonag]	    whether to use NAG
-#      [-iw   |-noiw]	    start in interpreter window
-#      [-ihere|-noihere]    start an interpreter buffer in the original window
-#      [-nox]		    don't use X Windows
-#      [-go  |-nogo]	    whether to start system
-#      [-ws wsname]	    use named workspace
-#      [-list]		    list workspaces only
-#      [-grprog fname]	    use named program for Graphics
-#      [-nagprog fname]	    use named program for Nag
-#      [-htprog fname]	    use named program for HyperDoc
-#      [-clefprog fname]    use named program for Clef
-#      [-sessionprog fname] use named program for session
-#      [-clientprog fname]  use named program for spadclient
-#      [-h]		    show usage
-#
-#
+@
+The {\tt MALLOCTYPE} shell variable is an {\tt IBM} {\tt AIX}
+shell variable that controls buckets based extensions in the default
+memory allocator which may enhance performance. AIX uses a new
+memory management routine that does not zero {\tt malloc} memory
+and does not round up to the nearest power of 2, unlike most non-AIX
+systems. This can cause failures so we protect against that here.
+See the AIX Performance Tuning Guide\cite{9} for details.
+<<axiomcmd>>=
 
 MALLOCTYPE=3.1
 export MALLOCTYPE
 
-# NAGMAN needs to know the hostname
+@
+The {\tt nagman} process needs to know the hostname
+<<axiomcmd>>=
 HOST=`hostname`
 export HOST
 
-# 0. Basic utilities
-
+@
+There are 4 basic utilities used by this script.
+The {\tt ciao} script for immediate exit:
+<<axiomcmd>>=
 ciao() {
 	echo "Goodbye."
 	exit 1
 }
 
+@
+The {\tt needsubopt} script which is used to issue an error message
+when one of the command line options requires an option:
+<<axiomcmd>>=
 needsubopt () {
 	echo "The $1 option requires an argument."
 	ciao
 }
-
-
+@
+The {\tt showuse} script which gives basic command line help:
+<<axiomcmd>>=
 showuse() {
 echo "axiom"
-echo "     [-ht   |-noht]       whether to use HyperDoc"
-echo "     [-gr   |-nogr]       whether to use Graphics"
-echo "     [-clef |-noclef]     whether to use Clef"
-echo "     [-nag |-nonag]       whether to use NAG"
-echo "     [-iw   |-noiw]       start in interpreter window"
-echo "     [-ihere|-noihere]    start an interpreter buffer in the original window."
-echo "     [-nox]               don't use X Windows"
-echo "     [-go  |-nogo]        whether to start system"
-echo "     [-ws wsname]         use named workspace"
-echo "     [-list]              list workspaces only"
-#echo "     [-grprog fname]      use named program for Graphics"
-#echo "     [-nagprog fname]      use named program for Nag"
-#echo "     [-htprog fname]      use named program for HyperDoc"
-#echo "     [-clefprog fname]    use named program for Clef"
-#echo "     [-sessionprog fname] use named program for session"
-#echo "     [-clientprog fname]  use named program for spadclient"
-echo "     [-h]                 show usage"
+echo "  [-ht    |-noht]      whether to use HyperDoc"
+echo "  [-gr    |-nogr]      whether to use Graphics"
+echo "  [-clef  |-noclef]    whether to use Clef"
+echo "  [-nonag |-nag]       whether to use NAG"
+echo "  [-noiw  |-iw]        start in interpreter in a separate window"
+echo "  [-ihere |-noihere]   start an interpreter in this window"
+echo "  [-nox]               don't use X Windows"
+echo "  [-go  |-nogo]        whether to start system"
+echo "  [-ws wsname]         use named workspace"
+echo "  [-list]              list workspaces only"
+echo "  [-grprog fname]      use named program for Graphics"
+echo "  [-nagprog fname]     use named program for Nag"
+echo "  [-htprog fname]      use named program for HyperDoc"
+echo "  [-clefprog fname]    use named program for Clef"
+echo "  [-sessionprog fname] use named program for session"
+echo "  [-clientprog fname]  use named program for spadclient"
+echo "  [-h]                 show usage"
 }
 
-# 1. Ensure the environment is set.
+@
+List the various workspaces if asked.
+<<axiomcmd>>=
+listwspaces()
+{
+        echo "$1"
+        ls -l $2 | grep "sys$"
+        echo ""
+}
 
-# Just process '-h'
+@
+Step 1. Ensure the environment is set.
+
+Just process ``-h''. If it exists in the command line then we
+print out the simple command line help menu.
+<<axiomcmd>>=
 
 if [ "$*" = "-h" ] ; then
      showuse
 fi
-SPADDEFAULT=/axiom/mnt/linux
+@
 
+We assume that Axiom is installed in the standard place on
+a linux system. We will modify this assumption as we process
+the environment and command line. The term {\tt spad} is an
+historical shortened version of the name {\tt scratchpad},
+the original name of the {\tt Axiom} system.
+<<axiomcmd>>=
+SPADDEFAULT=/usr/local/axiom/mnt/linux
+
+@
+If the {\tt \$AXIOM} shell variable is set then we use it.\\
+If not, then if the {\tt \$SPAD} shell variable is set then we use it.\\
+If not, then we try to use the default value above.\\
+If not, we simply fail.
+<<axiomcmd>>=
 if [ "$SPAD" = "" ] ; then
   if [ "$AXIOM" = "" ] ; then
     SPAD=$SPADDEFAULT
@@ -300,6 +625,25 @@ else
   fi
 fi
 
+@
+If we get here then all attempts to find axiom have failed
+so we complain and exit.
+<<axiomcmd>>=
+if [ ! -d "$SPAD" ] ; then
+  echo "The directory for Axiom, $SPAD, does not exist."
+  ciao
+fi
+
+@
+If we get here we now
+know where axiom lives. We need to see if we can find the
+Aldor compiler. Aldor is optional and is not part of the open source
+version of Axiom due to license issues. However you can install it
+under the location specified by the {\tt \$AXIOMXLROOT} shell variable.
+If the compiler is found we add it to the {\tt PATH}.
+This shell variable defaults to the location:\\
+{\tt \$AXIOM/compiler}
+<<axiomcmd>>=
 if [ "$AXIOMXLROOT" = "" ] ; then 
 AXIOMXLROOT=${AXIOM}/compiler
 fi
@@ -307,97 +651,1182 @@ export AXIOMXLROOT
 PATH=$AXIOM/bin:$AXIOMXLROOT/bin:${PATH}
 export PATH
 
-
-
-if [ ! -d "$SPAD" ] ; then
-  echo "The directory for Axiom, $SPAD, does not exist."
-  ciao
-fi
-
-# Name the workspace directories.
+@
+Name the workspace directories.
+<<axiomcmd>>=
 rootwsdir=$SPAD/bin
 
-# 2. Process command line arguments.
+@
+Step 2. Process command line arguments.
 
-# Defaults for command-line arguments.
+First we set up the defaults for command-line arguments.
+We don't want just a list by default
+<<axiomcmd>>=
 list=no
+
+@
+We default to actually executing the workspace.
+<<axiomcmd>>=
 go=yes
+
+@
+We default to the {\tt AXIOMsys} workspace.
+<<axiomcmd>>=
 wsname=AXIOMsys
 
+@
+And all other options are unset.
+<<axiomcmd>>=
 otheropts=""
 
+@
+For each option on the command line do
+<<axiomcmd>>=
 while [ "$*" != "" ] ; do
+@
+<<axiomcmd>>=
 
 	case $1 in
+@
+If the user specified list anywhere then we give the workspace list
+and exit.
+<<axiomcmd>>=
+
         -list)  list=yes
                 go=no;;
+@
+If the user specified {\tt go} or {\tt nogo} we handle that case
+<<axiomcmd>>=
 	-go)	go=yes ;;
 	-nogo)	go=no ;;
 
+@
+The workspace option requires an argument which follows immediately.
+If the argument is missing we complain and exit.
+<<axiomcmd>>=
 	-ws)
 		if [ "$2" = "" ] ; then needsubopt "$1" ; fi
 		shift
 		wsname="$1"
 		;;
 
-	-nagprog|-grprog|-htprog|-clefprog|-sessionprog|-clientprog|-paste|-rm|-rv)
+@
+We can specify the various subprograms to use.
+<<axiomcmd>>=
+	-nagprog|-grprog|-htprog|-clefprog|-sessionprog|-clientprog)
 		if [ "$2" = "" ] ; then needsubopt "$1" ; fi
 		otheropts="$otheropts  $1 $2"
 		shift
 		;;
-	-clef|-noclef|-gr|-nogr|-ht|-noht|-iw|-noiw|-ihere|-noihere|-nox|-nag|-nonag)
+@
+These options were not explained earlier and are only for developer use.
+<<axiomcmd>>=
+        -paste|-rm|-rv)
+		if [ "$2" = "" ] ; then needsubopt "$1" ; fi
+		otheropts="$otheropts  $1 $2"
+		shift
+		;;
+@
+We handle the various [{\tt -option} $\vert$ {\tt -nooption}] cases
+<<axiomcmd>>=
+	-clef|-noclef|-gr|-nogr|-ht|-noht|-iw|-noiw)
+		otheropts="$otheropts $1"
+		;;
+        -ihere|-noihere|-nox|-nag|-nonag)
 		otheropts="$otheropts $1"
 		;;
-
+@
+The user wanted help so we will not execute.
+<<axiomcmd>>=
 	-h)
 		go=no
 		;;
-
-
+@
+The user is confused. Complain and exit.
+<<axiomcmd>>=
 	*)	echo "Unknown option: $1"
 		echo "To use a specific workspace use, e.g.: spad -ws $1"
 		ciao
 		;;
 	esac
+@
+Move to the next option and loop.
+<<axiomcmd>>=
 
 	shift
 done
 
-# 3. List the available workspaces, if asked
-
-listwspaces()
-{
-        echo "$1"
-        ls -l $2 | grep "sys$"
-        echo ""
-}
+@
+Step 3. Handle options that require special case handling.
 
+The user just wanted to know what workspaces are available.
+<<axiomcmd>>=
 if [ $list = yes ] ; then
-          listwspaces "AXIOM workspaces in \$AXIOM/bin = $rootwsdir: " $rootwsdir
+ listwspaces "AXIOM workspaces in \$AXIOM/bin = $rootwsdir: " $rootwsdir
 fi
 
-# 5. Try to ensure a suitable workspace on this host.
-
+@
+Try to ensure a suitable workspace on this host.
+<<axiomcmd>>=
 if [ `expr $wsname : '.*/.*'` = 0 ] ; then
 	serverws=$rootwsdir/$wsname
 else
 	serverws=$wsname
 fi
+@
+If we can't find the executable then we complain and exit.
+<<axiomcmd>>=
 
-if [ ! -f $serverws ] ; then
+if [ ! -x $serverws ] ; then
+        echo "Cannot find the executable $serverws"
 	showuse
 	ciao
 fi
-
-# 6. Start processes
-
+@
+The user just wanted to see what would happen so we output the
+command line and exit.
+<<axiomcmd>>=
 if [ $go = no ] ; then
 	echo "Would now start the processes."
 	echo exec $SPAD/bin/sman $otheropts -ws $serverws
 	exit 0
 fi
-
+@
+All of the options have been processed so we start {\tt sman}
+<<axiomcmd>>=
 exec $SPAD/bin/sman $otheropts -ws $serverws
+
+@
+\chapter{The {\tt sman} program}
+\section{sman.h}
+The spad\_proc structure holds information about the process id
+of a child process, what to do when it dies, and the shell command
+line necessary to restart the process. There is a linked list of
+these structures which maintains the process list for axiom.
+<<sman.h>>=
+/* Process control definitions.  Used by fork_you and spawn_of_hell */
+
+/* When a process dies it kills off everything else */
+#define Die 1
+/* When a process dies, do nothing */
+#define NadaDelShitsky  2
+/* When a process dies start it up again */
+#define DoItAgain       3
+
+typedef struct spad_proc {
+  int	proc_id;	/* process id of child */
+  int	death_action;	/* one of the above constants */
+  char	*command;	/* sh command line to restart the process */
+  struct spad_proc *next;
+} SpadProcess;
+
+@
+\section{sman}
+\subsection{includes}
+<<sman.includes>>=
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#if defined(SUN4OS5platform) || defined(HP10platform)
+#include <sys/stropts.h>
+#endif
+
+#include "com.h"
+#include "bsdsignal.h"
+#include "sman.h"
+
+#include "bsdsignal.h1"
+#include "sockio-c.h1"
+#include "openpty.h1"
+#include "sman.h1"
+
+@
+\subsection{variables}
+<<sman.variables>>=
+char *ws_path;                  /* location of the AXIOM executable */
+int start_clef;			/* start clef under spad */
+int start_graphics;		/* start the viewman */
+int start_nagman;               /* start the nagman */
+int start_ht;			/* start hypertex */
+int start_spadclient;		/* Start the client spad buffer */
+int start_local_spadclient;	/* Start the client spad buffer */
+int use_X;			/* Use the X windows environment */
+int server_num;			/* AXIOM server number */
+@
+We add a debug flag so we can print information about what [[sman]]
+is trying to do. This change is pervasive as it touches nearly every
+routine.
+<<sman.variables>>=
+int tpd=0;                      /* to-print-debug information */
+
+/************************************************/
+/* definitions of programs which sman can start */
+/************************************************/
+
+<<the viewman command line>>
+<<the nagman command line>>
+<<the hypertex command line>>
+<<the clef command line>>
+<<the session manager command line>>
+<<the spadclient command line>>
+char *PasteFile = NULL;
+char *MakeRecordFile = NULL;
+char *VerifyRecordFile = NULL;
+
+SpadProcess *spad_process_list = NULL;
+/***************************/
+/* sman defaults file name */
+/***************************/
+
+#define SpadDefaultFile "spadprof.input"
+
+char ClefCommandLine[256];
+
+#define BufSize      4096 	/* size of communication buffer */
+char big_bad_buf[BufSize];      /* big I/O buffer */
+
+Sock *session_io = NULL;        /* socket connecting to session manager */
+
+/***********************************************************/
+/* Some characters used and externally defined in edible.h */
+/***********************************************************/
+
+unsigned char  _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2;
+
+/*************************************/
+/* Stuff for opening pseudo-terminal */
+/*************************************/
+
+int ptsNum, ptcNum;
+char ptsPath[20], ptcPath[20];
+
+char **new_envp;                /* new environment for AXIOM */
+int child_pid;                  /* child's process id */
+struct termios oldbuf;           /* the original settings */
+struct termios childbuf;         /* terminal structure for user i/o */
+
+int nagman_signal=0;
+int death_signal = 0;
+
+@
+\subsection{process\_arguments}
+<<sman.processarguments>>=
+static void
+process_arguments(int argc,char ** argv)
+{
+  int arg;
+  if (tpd == 1) fprintf(stderr,"sman:process_arguments entered\n");
+  for (arg = 1; arg < argc; arg++) {
+    if      (strcmp(argv[arg], "-debug")      == 0)
+      tpd = 1;
+    else if (strcmp(argv[arg], "-noclef")      == 0)
+      start_clef = 0;
+    else if (strcmp(argv[arg], "-clef")        == 0)
+      start_clef = 1;
+    else if (strcmp(argv[arg], "-gr")          == 0)
+      start_graphics = 1;
+    else if (strcmp(argv[arg], "-nogr")        == 0)
+      start_graphics = 0;
+    else if (strcmp(argv[arg], "-nag")          == 0)
+      start_nagman = 1;
+    else if (strcmp(argv[arg], "-nonag")        == 0)
+      start_nagman = 0;
+    else if (strcmp(argv[arg], "-ht")          == 0)
+      start_ht = 1;
+    else if (strcmp(argv[arg], "-noht")        == 0)
+      start_ht = 0;
+    else if (strcmp(argv[arg], "-iw")          == 0)
+      start_spadclient = 1;
+    else if (strcmp(argv[arg], "-ihere")       == 0)
+      start_local_spadclient = 1;
+    else if (strcmp(argv[arg], "-noihere")     == 0)
+      start_local_spadclient = 0;
+    else if (strcmp(argv[arg], "-noiw")        == 0)
+      start_spadclient = 0;
+    else if (strcmp(argv[arg], "-ws")          == 0)
+      ws_path = argv[++arg];
+    else if (strcmp(argv[arg], "-comp")        == 0)
+      ws_path = "$AXIOM/etc/images/comp";
+    else if (strcmp(argv[arg], "-nox")         == 0)
+      {
+	use_X = 0;
+	start_local_spadclient = 1;
+	start_spadclient = 0;
+	start_ht = 0;
+	start_graphics = 0;
+      }
+    else if (strcmp(argv[arg], "-grprog")      == 0)
+      GraphicsProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-nagprog")      == 0)
+      NagManagerProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-htprog")      == 0)
+      HypertexProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-clefprog")    == 0) {
+      strcpy(ClefCommandLine,argv[++arg]);
+    ClefProgram = 
+        strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e ");
+    }
+    else if (strcmp(argv[arg], "-sessionprog") == 0)
+      SessionManagerProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-clientprog")  == 0)
+      SpadClientProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-rm")  == 0)
+      MakeRecordFile = argv[++arg];
+    else if (strcmp(argv[arg], "-rv")  == 0)
+      VerifyRecordFile = argv[++arg];
+    else if (strcmp(argv[arg], "-paste")  == 0)
+      PasteFile = argv[++arg];
+    else {
+      fprintf(stderr, "Usage: sman <-clef|-noclef> <-gr|-nogr> <-ht|-noht>");
+      fprintf(stderr, " <-iw|-noiw> <-nag|-nonag> <-nox> <-comp>");
+      fprintf(stderr, " <-ws spad_workspace> <-grprog path> <-htprog path>");
+      fprintf(stderr, " <-clefprog path> <-sessionprog path> <-nagprog path>");
+      fprintf(stderr, " <-clientprog path>\n");
+      exit(-1);
+    }
+  }
+  if (tpd == 1)
+  { fprintf(stderr,"  sman ");
+    if (start_clef == 0)
+      fprintf(stderr,"-noclef ");
+    else
+      fprintf(stderr,"-clef ");
+    if (start_graphics == 0)
+      fprintf(stderr,"-nogr ");
+    else
+      fprintf(stderr,"-gr ");
+    if (start_nagman == 0)
+      fprintf(stderr,"-nonag ");
+    else
+      fprintf(stderr,"-nag ");
+    if (start_ht == 0)
+      fprintf(stderr,"-noht ");
+    else
+      fprintf(stderr,"-ht ");
+    if (start_spadclient == 0)
+      fprintf(stderr,"-noiw ");
+    else
+      fprintf(stderr,"-iw ");
+    if (start_local_spadclient == 0)
+      fprintf(stderr,"-noihere ");
+    else
+      fprintf(stderr,"-ihere ");
+    if (start_local_spadclient == 0)
+      fprintf(stderr,"-noihere ");
+    else
+      fprintf(stderr,"-ihere ");
+    if (use_X == 0)
+      fprintf(stderr,"-nox ");
+    fprintf(stderr,"-ws ");
+    fprintf(stderr,"'%s' ",ws_path);
+    fprintf(stderr,"-grprog ");
+    fprintf(stderr,"'%s' ",GraphicsProgram);
+    fprintf(stderr,"-nagprog ");
+    fprintf(stderr,"'%s' ",NagManagerProgram);
+    fprintf(stderr,"-htprog ");
+    fprintf(stderr,"'%s' ",HypertexProgram);
+    fprintf(stderr,"-clefprog ");
+    fprintf(stderr,"'%s' ",ClefCommandLine);
+    fprintf(stderr,"-sessionprog ");
+    fprintf(stderr,"'%s' ",SessionManagerProgram);
+    fprintf(stderr,"-clientprog ");
+    fprintf(stderr,"'%s' ",SpadClientProgram);
+    fprintf(stderr,"-rm ");
+    fprintf(stderr,"'%s' ",MakeRecordFile);
+    fprintf(stderr,"-rv ");
+    fprintf(stderr,"'%s' ",VerifyRecordFile);
+    fprintf(stderr,"-paste ");
+    fprintf(stderr,"'%s' ",PasteFile);
+    fprintf(stderr,"\n");
+  }
+  if (tpd == 1) fprintf(stderr,"sman:process_arguments exit\n");
+}
+
+@
+\subsection{should\_I\_clef}
+<<sman.shouldIclef>>=
+static int 
+should_I_clef(void)
+{
+  return(1);
+}
+
+@
+\subsection{in\_X}
+<<sman.inX>>=
+static int 
+in_X(void)
+{
+  if (getenv("DISPLAY")) return 1;
+  return 0;
+}
+
+@
+\subsection{set\_up\_defaults}
+These are the default values for sman. A '1' value means that
+sman will try to start the given process, a '0' value means not
+starting the process.
+
+We do not have replacement code for the [[nagman]] process nor
+do we have a copy of the [[nag fortran library]] to test the process.
+Until this changes we set [[start_nagman = 0]] in order to disable
+starting this process by default.
+<<sman.setupdefaults>>=
+static  void
+set_up_defaults(void)
+{
+  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults entered\n");
+  start_clef = should_I_clef();
+  start_graphics = 1;
+  start_nagman = 0;
+  start_ht = 1;
+  start_spadclient = 0;
+  start_local_spadclient = 1;
+  use_X = isatty(0) && in_X();
+  ws_path = "$AXIOM/bin/AXIOMsys";
+  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults exit\n");
+}
+
+@
+\subsection{process\_options}
+<<sman.processoptions>>=
+static void
+process_options(int argc, char **argv)
+{
+  if (tpd == 1) fprintf(stderr,"sman:process_options entered\n");
+  set_up_defaults();
+  process_arguments(argc, argv);
+  if (tpd == 1) fprintf(stderr,"sman:process_options exit\n");
+}
+
+@
+\subsection{death\_handler}
+<<sman.deathhandler>>=
+static void
+death_handler(int sig)
+{
+  death_signal = 1;
+}
+
+@
+\subsection{nagman\_handler}
+<<sman.nagmanhandler>>=
+static void 
+nagman_handler(int sig)
+{
+  nagman_signal=1;
+}
+
+@
+\subsection{sman\_catch\_signals}
+<<sman.smancatchsignals>>=
+static void
+sman_catch_signals(void)
+{
+  
+  /* Set up the signal handlers for sman */
+  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
+  bsdSignal(SIGTERM, death_handler,RestartSystemCalls);
+  bsdSignal(SIGQUIT, death_handler,RestartSystemCalls);
+  bsdSignal(SIGHUP,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGILL,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGTRAP, death_handler,RestartSystemCalls);
+  bsdSignal(SIGIOT,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGBUS,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGSEGV, death_handler,RestartSystemCalls);
+  /* don't restart wait call on SIGUSR1  */
+  bsdSignal(SIGUSR1, nagman_handler,DontRestartSystemCalls); 
+  /* ONLY nagman should send this.
+     If an error (such as C-c) interrupts a NAGLINK call, nagman
+     gets a signal to clean up. We need to start another nagman 
+     almost immediately to process the next NAGLINK request.
+     Since nagman takes a while to clean up, we treat it specially.
+     nagman should send a signal (USR1) to sman.
+     sman should respond by spawning a new nagman.
+     
+     so nagman is NOT a DoItAgain but a NadaDelShitsky.
+     
+     The USR1 mechanism does not work for HPUX 9 - use DoItAgain 
+     */
+
+}
+
+@
+\subsection{fix\_env}
+insert SPADSERVER and SPADNUM variables into the environemnt
+<<sman.fixenv>>=
+static void
+fix_env(char **envp, int spadnum)
+{
+  int len, i;
+  char *sn;
+  for(len = 0; envp[len] != NULL; len++);
+  new_envp = (char **) malloc((len + 3) * sizeof(char *));
+  new_envp[0] = "SPADSERVER=TRUE";
+  sn = (char *) malloc(20 * sizeof(char));
+  sprintf(sn, "SPADNUM=%d", spadnum);
+  new_envp[1] = sn;
+  for(i=0; i<=len; i++)
+    new_envp[i+2] = envp[i];
+}
+
+@
+\subsection{init\_term\_io}
+<<sman.inittermio>>=
+static void
+init_term_io(void)
+{
+  if(!isatty(0)) return;
+  if( tcgetattr(0, &oldbuf) == -1) {
+    perror("getting termios");
+    return ; 			/*  exit(-1); */
+  }
+  if( tcgetattr(0, &childbuf) == -1) {
+    perror("getting termios");
+    return ; 			/*   exit(-1); */
+  }
+  _INTR = oldbuf.c_cc[VINTR];
+  _QUIT = oldbuf.c_cc[VQUIT];
+  _ERASE = oldbuf.c_cc[VERASE];
+  _KILL = oldbuf.c_cc[VKILL];
+  _EOF = oldbuf.c_cc[VEOF];
+  _EOL = oldbuf.c_cc[VEOL];
+}
+
+@
+\subsection{strPrefix}
+<<sman.strPrefix>>=
+static char *
+strPrefix(char *prefix,char * s)
+{
+  while (*prefix != '\0' && *prefix == *s) {
+    prefix++;
+    s++;
+  }
+  if (*prefix == '\0') return s;
+  return NULL;
+}
+
+@
+\subsection{check\_spad\_proc}
+<<sman.checkspadproc>>=
+static void
+check_spad_proc(char *file, char *prefix)
+{
+  char *num;
+  int pid;
+  if ((num = strPrefix(prefix, file))) {
+    pid = atoi(num);
+    if (pid > 2) {
+      kill(pid, 0);
+      if (kill(pid, 0) == -1 && errno == ESRCH) {
+	unlink(file);
+      }
+    }
+  }
+}
+
+@
+\subsection{clean\_up\_old\_sockets}
+<<sman.cleanupoldsockets>>=
+static void
+clean_up_old_sockets(void)
+{
+  char com[512], tmp_file[128];
+  FILE *file;
+  int len;
+  sprintf(tmp_file, "/tmp/socks.%d", server_num);
+  sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s",
+	  tmp_file, tmp_file);
+  system(com);
+  file = fopen(tmp_file, "r");
+  if (file == NULL) {
+    fprintf(stderr, "Can't open socket listing file\n");
+    return;
+  }
+  while(fgets(com, 512, file) != NULL) {
+    len = strlen(com);
+    if (len) com[len-1] = '\0';
+    else break;
+    check_spad_proc(com, "/tmp/.d");
+    check_spad_proc(com, "/tmp/.s");
+    check_spad_proc(com, "/tmp/.i");
+    check_spad_proc(com, "/tmp/.h");
+  }
+  fclose(file);
+  unlink(tmp_file);
+}
+
+@
+\subsection{fork\_you}
+<<sman.forkyou>>=
+static SpadProcess *
+fork_you(int death_action)
+{
+  /* fork a new process, giving it a default death action */
+  /* return NULL in child, SpadProcess in parent          */
+  int child_pid = fork();
+  SpadProcess *proc;
+  if (!child_pid) return NULL;
+  proc = (SpadProcess *) malloc(sizeof(SpadProcess));
+  proc->proc_id = child_pid;
+  proc->death_action = death_action;
+  proc->command = NULL;
+  proc->next = spad_process_list;
+  spad_process_list = proc;
+  return proc;
+}
+
+@
+\subsection{exec\_command\_env}
+Note that the next-to-last argument of {\tt execle} must be an
+explicit NULL pointer. The previous naked 0 value was not correct.
+<<sman.execcommandenv>>=
+static void
+exec_command_env(char *command,char ** env)
+{
+  char new_command[512];
+  sprintf(new_command, "exec %s", command);
+  execle("/bin/sh","/bin/sh", "-c", new_command, (char *)0, env);
+}
+
+@
+\subsection{spawn\_of\_hell}
+<<sman.spawnofhell>>=
+static SpadProcess *
+spawn_of_hell(char *command, int death_action)
+{
+  SpadProcess *proc = fork_you(death_action);
+  if (proc != NULL) {
+    proc->command = command;
+    return proc;
+  }
+  exec_command_env(command, new_envp);
+  return NULL;
+}
+
+@
+\subsection{start\_the\_spadclient}
+run a AXIOM client in the main process
+<<sman.startthespadclient>>=
+static void
+start_the_spadclient(void)
+{
+  char command[256];
+  if (start_clef)
+#ifdef RIOSplatform
+    sprintf(command, 
+	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
+	    ClefProgram, SpadClientProgram);
+#else
+  sprintf(command, 
+	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
+	  ClefProgram, SpadClientProgram);
+#endif
+  else
+#ifdef RIOSplatform
+    sprintf(command, 
+	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
+	    SpadClientProgram);
+#else
+  sprintf(command, 
+	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
+	  SpadClientProgram);
+#endif
+  if (tpd == 1) 
+    fprintf(stderr,"sman:start_the_spadclient: %s\n",command);
+  spawn_of_hell(command, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_local\_spadclient}
+<<sman.startthelocalspadclient>>=
+static void
+start_the_local_spadclient(void)
+{
+  char command[256];
+  if (start_clef)
+    sprintf(command, "%s  %s", ClefProgram, SpadClientProgram);
+  else
+    sprintf(command, "%s", SpadClientProgram);
+  if (tpd == 1) 
+    fprintf(stderr,"sman:start_the_local_spadclient: %s\n",command);
+  spawn_of_hell(command, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_nagman}
+<<sman.startthenagman>>=
+static void
+start_the_nagman(void)
+{
+#if defined(HP9platform)
+  spawn_of_hell(NagManagerProgram,DoItAgain);
+#else
+  spawn_of_hell(NagManagerProgram,NadaDelShitsky );
+#endif
+}
+
+@
+\subsection{start\_the\_session\_manager}
+<<sman.startthesessionmanager>>=
+static void
+start_the_session_manager(void)
+{
+  spawn_of_hell(SessionManagerProgram, Die);
+}
+
+@
+\subsection{start\_the\_hypertex}
+<<sman.startthehypertex>>=
+static void
+start_the_hypertex(void)
+{
+  char prog[512];
+
+  if (PasteFile){
+    sprintf(prog, "%s -k -ip %s", HypertexProgram, PasteFile);
+    spawn_of_hell(prog, NadaDelShitsky);
+  }
+  else if (MakeRecordFile){
+    sprintf(prog, "%s -k -rm %s", HypertexProgram,MakeRecordFile );
+    spawn_of_hell(prog, NadaDelShitsky);
+  }
+  else if (VerifyRecordFile){
+    sprintf(prog, "%s -k -rv %s", HypertexProgram, VerifyRecordFile);
+    spawn_of_hell(prog, NadaDelShitsky);
+  }
+  else	spawn_of_hell(HypertexProgram, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_graphics}
+<<sman.startthegraphics>>=
+static void
+start_the_graphics(void)
+{
+  spawn_of_hell(GraphicsProgram, DoItAgain);
+}
+
+@
+\subsection{fork\_Axiom}
+<<sman.forkAxiom>>=
+/* Start the AXIOM session in a separate process, */
+/* using a pseudo-terminal to catch all input and output */
+static void 
+fork_Axiom(void)
+{
+  char augmented_ws_path[256];  /* will append directory path */
+  char *tmp_pointer;
+  SpadProcess *proc;
+
+  proc =  fork_you(Die);
+  child_pid = (proc == NULL ? 0 : proc->proc_id);
+  switch(child_pid) {
+  case -1 :
+    fprintf(stderr, "Can't create a new process \n");
+    exit(0);
+  case 0:
+    /* Dissasociate from my parents group so all my child processes */
+    /* look at my terminal as the controlling terminal for the      */
+    /* group                                                        */
+
+    if(setsid() < 0) {
+      perror("Dissassociating from parents group");
+      exit(-1);
+    }
+
+    close(ptsNum);
+    /* Now reopen the server side, so that pg, su, etc. work properly */
+
+    if ((ptsNum =  open(ptsPath, O_RDWR)) < 0 ) {
+      perror("fork_Axiom: Failed to reopen server");
+      exit(-1);
+    }
+#if defined(SUN4OS5platform) || defined(HP10platform)
+    ioctl(ptsNum,I_PUSH,"ptem");
+    ioctl(ptsNum,I_PUSH,"ldterm");
+#endif
+
+    /* since I am the child, I can close ptc, and dup pts for all its */
+    /* standard descriptors                                           */
+
+    if( (dup2(ptsNum, 0) == -1) ||
+        (dup2(ptsNum, 1) == -1) ||
+        (dup2(ptsNum, 2) == -1)  ) {
+      perror("trying to dupe the child");
+      exit(-1);
+    }
+    close(ptcNum);
+    close(ptsNum);
+
+
+    /* I also have to turn off echoing, since I am echoing all the */
+    /* input myself                  */
+
+    childbuf.c_lflag &= ~ECHO;
+    if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) {
+      perror("setting the term buffer");
+      exit(-1); 
+    }
+    strcpy(augmented_ws_path,ws_path);          /* write the name    */
+    strcat(augmented_ws_path," ");              /* space             */
+    strcat(augmented_ws_path,ws_path);          /* name again        */
+    tmp_pointer = (char *)
+      strrchr(augmented_ws_path,'/');      /*pointer to last /  */
+    *(++tmp_pointer) = '\0';
+    exec_command_env(augmented_ws_path, new_envp);
+
+    /*    fprintf(stderr, "Cannot execute the %s system.\n", ws_path); */
+
+    exit(0);
+  }
+}
+
+@
+\subsection{start\_the\_Axiom}
+<<sman.starttheAxiom>>=
+static void
+start_the_Axiom(char **envp)
+{
+  server_num = make_server_number();
+  clean_up_old_sockets();
+  if (server_num == -1) {
+    fprintf(stderr, "could not get an AXIOM server number\n");
+    exit(-1);
+  }
+  if (ptyopen(&ptcNum, &ptsNum, ptcPath, ptsPath) == -1) {
+    perror("start_the_Axiom: ptyopen failed");
+    exit(-1);
+  }
+  fix_env(envp, server_num);
+  fork_Axiom();
+  close(ptsNum);
+}
+
+@
+\subsection{clean\_up\_sockets}
+<<sman.cleanupsockets>>=
+static void
+clean_up_sockets(void)
+{
+  char name[256];
+  sprintf(name, "%s%d", SpadServer, server_num);
+  unlink(name);
+  sprintf(name, "%s%d", SessionServer, server_num);
+  unlink(name);
+  sprintf(name, "%s%d", SessionIOName, server_num);
+  unlink(name);
+  sprintf(name, "%s%d", MenuServerName, server_num);
+  unlink(name);
+}
+
+@
+\subsection{read\_from\_spad\_io}
+<<sman.readfromspadio>>=
+static void
+read_from_spad_io(int ptcNum)
+{
+  int ret_code = 0, i=0;
+  static int mes_len =0; 
+  ret_code = read(ptcNum, big_bad_buf, BufSize);
+  if (ret_code == -1) {
+    clean_up_sockets();
+    exit(-1);
+  }
+  if (session_io == NULL) {
+    if (ret_code < mes_len)
+      mes_len -= ret_code;
+    else {
+      if (mes_len > 0) {
+	i = mes_len;
+	mes_len = 0;
+      }
+      else
+	i = 0;
+      ret_code = write(1, big_bad_buf+i, ret_code-i);
+    }
+  }
+  else
+    ret_code = swrite(session_io, big_bad_buf, ret_code,
+		      "writing to session man");
+  if (ret_code == -1) {
+    perror("writing output to session manager");
+    clean_up_sockets();
+    exit(-1);
+  }
+}
+
+@
+\subsection{read\_from\_manager}
+<<sman.readfrommanager>>=
+static void
+read_from_manager(int ptcNum)
+{
+  int ret_code;
+  ret_code = sread(session_io, big_bad_buf, BufSize, "reading session io");
+  if (ret_code == -1) {
+    return;
+  }
+  ret_code = write(ptcNum, big_bad_buf, ret_code);
+  if (ret_code == -1) {
+    return;
+  }
+}
+
+@
+\subsection{manage\_spad\_io}
+<<sman.managespadio>>=
+static void
+manage_spad_io(int ptcNum)
+{
+  int ret_code, i, p;
+  fd_set rd;
+  while (1) {
+    rd = socket_mask;
+    FD_SET(ptcNum, &rd);
+    if (session_io != NULL)
+      FD_SET(session_io->socket, &rd);
+    ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
+    if (ret_code == -1) {
+      perror("Session manager select");
+      clean_up_sockets();
+      exit(-1);
+    }
+    if (FD_ISSET(ptcNum, &rd)) {
+      read_from_spad_io(ptcNum);
+    }
+    for(i=0; i<2; i++) {
+      if (server[i].socket > 0 && FD_ISSET(server[i].socket, &rd)) {
+	p = accept_connection(server+i);
+	switch(p) {
+	case SessionIO:
+	  session_io = purpose_table[SessionIO];
+	  /*  printf("connected session manager\n\r");*/
+	  printf("\n");
+	  break;
+	default:
+	  printf("sman: Unkown connection request type: %d\n", p);
+	  break;
+	}
+      }
+    }
+    if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) {
+      read_from_manager(ptcNum);
+    }
+  }
+}
+
+@
+\subsection{init\_spad\_process\_list}
+<<sman.initspadprocesslist>>=
+static void
+init_spad_process_list(void)
+{
+  spad_process_list = NULL;
+}
+
+@
+\subsection{print\_spad\_process\_list}
+<<sman.printspadprocesslist>>=
+#if 0
+static void
+print_spad_process_list()
+{
+  SpadProcess *proc;
+  for(proc = spad_process_list; proc != NULL; proc = proc->next)
+    fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id,
+	    proc->death_action);
+}
+#endif
+
+@
+\subsection{find\_child}
+<<sman.findchild>>=
+static SpadProcess *
+find_child(int proc_id)
+{
+  SpadProcess *proc;
+  for(proc = spad_process_list; proc != NULL; proc = proc->next)
+    if (proc->proc_id == proc_id) return proc;
+  return NULL;
+}
+
+@
+\subsection{kill\_all\_children}
+<<sman.killallchildren>>=
+static void
+kill_all_children(void)
+{
+  char name[256];
+  SpadProcess *proc;
+  
+  
+  for(proc = spad_process_list; proc != NULL; proc = proc->next) {
+    kill(proc->proc_id, SIGTERM);
+  }
+  sprintf(name, "/tmp/hyper%d.input",server_num);
+  unlink(name);
+
+}
+
+@
+\subsection{clean\_up\_terminal}
+<<sman.cleanupterminal>>=
+static void
+clean_up_terminal(void)
+{
+  tcsetattr(0, TCSAFLUSH, &oldbuf);
+}
+
+@
+\subsection{monitor\_children}
+<<sman.monitorchildren>>=
+static void
+monitor_children(void)
+{
+  int dead_baby, stat;
+  SpadProcess *proc;
+  while (1) {
+    stat = 0;
+    dead_baby = wait(&stat);
+    /* Check the value of dead_baby, since wait may have returned
+       a pid but subsequently we have received a signal.  Yeuch! */
+    if (dead_baby == -1 && death_signal) {
+      kill_all_children();
+      clean_up_sockets();
+      clean_up_terminal();
+      sleep(2);
+      exit(0);
+    }
+    /* Check the value of dead_baby, since wait may have returned
+       a pid but subsequently we have received a signal.  Yeuch! */
+    if(dead_baby == -1 && nagman_signal) {
+      nagman_signal=0;
+      spawn_of_hell(NagManagerProgram,NadaDelShitsky);
+      continue;
+    }
+
+    if (dead_baby == -1) {
+      fprintf(stderr, "sman: wait returned -1\n");
+      continue;
+    }
+    proc = find_child(dead_baby);
+    if (proc == NULL) {
+      /*      fprintf(stderr, "sman: %d is not known to be a child process\n",
+	      dead_baby);
+	      */
+      continue;
+    }
+    switch(proc->death_action) {
+    case Die:
+      kill_all_children();
+      clean_up_sockets();
+      clean_up_terminal();
+      sleep(2);
+      exit(0);
+    case NadaDelShitsky:
+      break;
+    case DoItAgain:
+      spawn_of_hell(proc->command, DoItAgain);
+      break;
+    }
+  }
+}
+
+@
+\subsection{main sman}
+The main procedure should return an [[int]]. We change the return value
+here and in [[src/include/sman.h1]].
+<<sman.result>>=
+  return(0);
+@
+<<sman.main>>=
+int
+main(int argc, char *argv[],char *envp[])
+{
+  if (tpd == 1) fprintf(stderr,"sman:main entered\n");
+  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
+  process_options(argc, argv);
+
+  init_term_io();
+  init_spad_process_list();
+  start_the_Axiom(envp);
+  if (open_server(SessionIOName) == -2) {
+    fprintf(stderr, "Fatal error opening I/O socket\n");
+    clean_up_sockets();
+    exit(-1);
+  }
+  start_the_session_manager();
+  if (start_spadclient)       start_the_spadclient();
+  if (start_local_spadclient) start_the_local_spadclient();
+  if (start_nagman)           start_the_nagman();
+  if (start_ht)               start_the_hypertex();
+  if (start_graphics)         start_the_graphics();
+  sleep(1);
+
+  if (fork_you(Die) != NULL) {
+    sman_catch_signals();
+    monitor_children();
+    exit(0);
+  }
+  manage_spad_io(ptcNum);
+  if (tpd == 1) fprintf(stderr,"sman:main exit\n");
+<<sman.result>>
+}
+
+@
+\subsection{sman}
+<<sman>>=
+#define _SMAN_C
+
+<<sman.includes>>
+<<sman.variables>>
+<<sman.processarguments>>
+<<sman.shouldIclef>>
+<<sman.inX>>
+<<sman.setupdefaults>>
+<<sman.processoptions>>
+<<sman.deathhandler>>
+<<sman.nagmanhandler>>
+<<sman.smancatchsignals>>
+<<sman.fixenv>>
+<<sman.inittermio>>
+<<sman.strPrefix>>
+<<sman.checkspadproc>>
+<<sman.cleanupoldsockets>>
+<<sman.forkyou>>
+<<sman.execcommandenv>>
+<<sman.spawnofhell>>
+<<sman.startthespadclient>>
+<<sman.startthelocalspadclient>>
+<<sman.startthenagman>>
+<<sman.startthesessionmanager>>
+<<sman.startthehypertex>>
+<<sman.startthegraphics>>
+<<sman.forkAxiom>>
+<<sman.starttheAxiom>>
+<<sman.cleanupsockets>>
+<<sman.readfromspadio>>
+<<sman.readfrommanager>>
+<<sman.managespadio>>
+<<sman.initspadprocesslist>>
+<<sman.printspadprocesslist>>
+<<sman.findchild>>
+<<sman.killallchildren>>
+<<sman.cleanupterminal>>
+<<sman.monitorchildren>>
+<<sman.main>>
+
 @
 \chapter{Support Routines}
 \section{Command Completion}
@@ -1565,1037 +2994,6 @@ main(void)
 }
 
 @
-\chapter{The {\tt sman} program}
-\section{sman.h}
-The spad\_proc structure holds information about the process id
-of a child process, what to do when it dies, and the shell command
-line necessary to restart the process. There is a linked list of
-these structures which maintains the process list for axiom.
-<<sman.h>>=
-/* Process control definitions.  Used by fork_you and spawn_of_hell */
-
-/* When a process dies it kills off everything else */
-#define Die 1
-/* When a process dies, do nothing */
-#define NadaDelShitsky  2
-/* When a process dies start it up again */
-#define DoItAgain       3
-
-typedef struct spad_proc {
-  int	proc_id;	/* process id of child */
-  int	death_action;	/* one of the above constants */
-  char	*command;	/* sh command line to restart the process */
-  struct spad_proc *next;
-} SpadProcess;
-
-@
-\section{sman}
-\subsection{includes}
-<<sman.includes>>=
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <pwd.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#if defined(SUN4OS5platform) || defined(HP10platform)
-#include <sys/stropts.h>
-#endif
-
-#include "com.h"
-#include "bsdsignal.h"
-#include "sman.h"
-
-#include "bsdsignal.h1"
-#include "sockio-c.h1"
-#include "openpty.h1"
-#include "sman.h1"
-
-@
-\subsection{variables}
-<<sman.variables>>=
-char *ws_path;                  /* location of the AXIOM executable */
-int start_clef;			/* start clef under spad */
-int start_graphics;		/* start the viewman */
-int start_nagman;               /* start the nagman */
-int start_ht;			/* start hypertex */
-int start_spadclient;		/* Start the client spad buffer */
-int start_local_spadclient;	/* Start the client spad buffer */
-int use_X;			/* Use the X windows environment */
-int server_num;			/* AXIOM server number */
-@
-We add a debug flag so we can print information about what [[sman]]
-is trying to do. This change is pervasive as it touches nearly every
-routine.
-<<sman.variables>>=
-int tpd=0;                      /* to-print-debug information */
-
-/************************************************/
-/* definitions of programs which sman can start */
-/************************************************/
-
-<<the viewman command line>>
-<<the nagman command line>>
-<<the hypertex command line>>
-<<the clef command line>>
-<<the session manager command line>>
-<<the spadclient command line>>
-char *PasteFile = NULL;
-char *MakeRecordFile = NULL;
-char *VerifyRecordFile = NULL;
-
-SpadProcess *spad_process_list = NULL;
-/***************************/
-/* sman defaults file name */
-/***************************/
-
-#define SpadDefaultFile "spadprof.input"
-
-char ClefCommandLine[256];
-
-#define BufSize      4096 	/* size of communication buffer */
-char big_bad_buf[BufSize];      /* big I/O buffer */
-
-Sock *session_io = NULL;        /* socket connecting to session manager */
-
-/***********************************************************/
-/* Some characters used and externally defined in edible.h */
-/***********************************************************/
-
-unsigned char  _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2;
-
-/*************************************/
-/* Stuff for opening pseudo-terminal */
-/*************************************/
-
-int ptsNum, ptcNum;
-char ptsPath[20], ptcPath[20];
-
-char **new_envp;                /* new environment for AXIOM */
-int child_pid;                  /* child's process id */
-struct termios oldbuf;           /* the original settings */
-struct termios childbuf;         /* terminal structure for user i/o */
-
-int nagman_signal=0;
-int death_signal = 0;
-
-@
-\subsection{process\_arguments}
-<<sman.processarguments>>=
-static void
-process_arguments(int argc,char ** argv)
-{
-  int arg;
-  if (tpd == 1) fprintf(stderr,"sman:process_arguments entered\n");
-  for (arg = 1; arg < argc; arg++) {
-    if      (strcmp(argv[arg], "-debug")      == 0)
-      tpd = 1;
-    else if (strcmp(argv[arg], "-noclef")      == 0)
-      start_clef = 0;
-    else if (strcmp(argv[arg], "-clef")        == 0)
-      start_clef = 1;
-    else if (strcmp(argv[arg], "-gr")          == 0)
-      start_graphics = 1;
-    else if (strcmp(argv[arg], "-nogr")        == 0)
-      start_graphics = 0;
-    else if (strcmp(argv[arg], "-nag")          == 0)
-      start_nagman = 1;
-    else if (strcmp(argv[arg], "-nonag")        == 0)
-      start_nagman = 0;
-    else if (strcmp(argv[arg], "-ht")          == 0)
-      start_ht = 1;
-    else if (strcmp(argv[arg], "-noht")        == 0)
-      start_ht = 0;
-    else if (strcmp(argv[arg], "-iw")          == 0)
-      start_spadclient = 1;
-    else if (strcmp(argv[arg], "-ihere")       == 0)
-      start_local_spadclient = 1;
-    else if (strcmp(argv[arg], "-noihere")     == 0)
-      start_local_spadclient = 0;
-    else if (strcmp(argv[arg], "-noiw")        == 0)
-      start_spadclient = 0;
-    else if (strcmp(argv[arg], "-ws")          == 0)
-      ws_path = argv[++arg];
-    else if (strcmp(argv[arg], "-comp")        == 0)
-      ws_path = "$AXIOM/etc/images/comp";
-    else if (strcmp(argv[arg], "-nox")         == 0)
-      {
-	use_X = 0;
-	start_local_spadclient = 1;
-	start_spadclient = 0;
-	start_ht = 0;
-	start_graphics = 0;
-      }
-    else if (strcmp(argv[arg], "-grprog")      == 0)
-      GraphicsProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-nagprog")      == 0)
-      NagManagerProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-htprog")      == 0)
-      HypertexProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-clefprog")    == 0) {
-      strcpy(ClefCommandLine,argv[++arg]);
-    ClefProgram = 
-        strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e ");
-    }
-    else if (strcmp(argv[arg], "-sessionprog") == 0)
-      SessionManagerProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-clientprog")  == 0)
-      SpadClientProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-rm")  == 0)
-      MakeRecordFile = argv[++arg];
-    else if (strcmp(argv[arg], "-rv")  == 0)
-      VerifyRecordFile = argv[++arg];
-    else if (strcmp(argv[arg], "-paste")  == 0)
-      PasteFile = argv[++arg];
-    else {
-      fprintf(stderr, "Usage: sman <-clef|-noclef> <-gr|-nogr> <-ht|-noht>");
-      fprintf(stderr, " <-iw|-noiw> <-nag|-nonag> <-nox> <-comp>");
-      fprintf(stderr, " <-ws spad_workspace> <-grprog path> <-htprog path>");
-      fprintf(stderr, " <-clefprog path> <-sessionprog path> <-nagprog path>");
-      fprintf(stderr, " <-clientprog path>\n");
-      exit(-1);
-    }
-  }
-  if (tpd == 1)
-  { fprintf(stderr,"  sman ");
-    if (start_clef == 0)
-      fprintf(stderr,"-noclef ");
-    else
-      fprintf(stderr,"-clef ");
-    if (start_graphics == 0)
-      fprintf(stderr,"-nogr ");
-    else
-      fprintf(stderr,"-gr ");
-    if (start_nagman == 0)
-      fprintf(stderr,"-nonag ");
-    else
-      fprintf(stderr,"-nag ");
-    if (start_ht == 0)
-      fprintf(stderr,"-noht ");
-    else
-      fprintf(stderr,"-ht ");
-    if (start_spadclient == 0)
-      fprintf(stderr,"-noiw ");
-    else
-      fprintf(stderr,"-iw ");
-    if (start_local_spadclient == 0)
-      fprintf(stderr,"-noihere ");
-    else
-      fprintf(stderr,"-ihere ");
-    if (start_local_spadclient == 0)
-      fprintf(stderr,"-noihere ");
-    else
-      fprintf(stderr,"-ihere ");
-    if (use_X == 0)
-      fprintf(stderr,"-nox ");
-    fprintf(stderr,"-ws ");
-    fprintf(stderr,"'%s' ",ws_path);
-    fprintf(stderr,"-grprog ");
-    fprintf(stderr,"'%s' ",GraphicsProgram);
-    fprintf(stderr,"-nagprog ");
-    fprintf(stderr,"'%s' ",NagManagerProgram);
-    fprintf(stderr,"-htprog ");
-    fprintf(stderr,"'%s' ",HypertexProgram);
-    fprintf(stderr,"-clefprog ");
-    fprintf(stderr,"'%s' ",ClefCommandLine);
-    fprintf(stderr,"-sessionprog ");
-    fprintf(stderr,"'%s' ",SessionManagerProgram);
-    fprintf(stderr,"-clientprog ");
-    fprintf(stderr,"'%s' ",SpadClientProgram);
-    fprintf(stderr,"-rm ");
-    fprintf(stderr,"'%s' ",MakeRecordFile);
-    fprintf(stderr,"-rv ");
-    fprintf(stderr,"'%s' ",VerifyRecordFile);
-    fprintf(stderr,"-paste ");
-    fprintf(stderr,"'%s' ",PasteFile);
-    fprintf(stderr,"\n");
-  }
-  if (tpd == 1) fprintf(stderr,"sman:process_arguments exit\n");
-}
-
-@
-\subsection{should\_I\_clef}
-<<sman.shouldIclef>>=
-static int 
-should_I_clef(void)
-{
-  return(1);
-}
-
-@
-\subsection{in\_X}
-<<sman.inX>>=
-static int 
-in_X(void)
-{
-  if (getenv("DISPLAY")) return 1;
-  return 0;
-}
-
-@
-\subsection{set\_up\_defaults}
-These are the default values for sman. A '1' value means that
-sman will try to start the given process, a '0' value means not
-starting the process.
-
-We do not have replacement code for the [[nagman]] process nor
-do we have a copy of the [[nag fortran library]] to test the process.
-Until this changes we set [[start_nagman = 0]] in order to disable
-starting this process by default.
-<<sman.setupdefaults>>=
-static  void
-set_up_defaults(void)
-{
-  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults entered\n");
-  start_clef = should_I_clef();
-  start_graphics = 1;
-  start_nagman = 0;
-  start_ht = 1;
-  start_spadclient = 0;
-  start_local_spadclient = 1;
-  use_X = isatty(0) && in_X();
-  ws_path = "$AXIOM/bin/AXIOMsys";
-  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults exit\n");
-}
-
-@
-\subsection{process\_options}
-<<sman.processoptions>>=
-static void
-process_options(int argc, char **argv)
-{
-  if (tpd == 1) fprintf(stderr,"sman:process_options entered\n");
-  set_up_defaults();
-  process_arguments(argc, argv);
-  if (tpd == 1) fprintf(stderr,"sman:process_options exit\n");
-}
-
-@
-\subsection{death\_handler}
-<<sman.deathhandler>>=
-static void
-death_handler(int sig)
-{
-  death_signal = 1;
-}
-
-@
-\subsection{nagman\_handler}
-<<sman.nagmanhandler>>=
-static void 
-nagman_handler(int sig)
-{
-  nagman_signal=1;
-}
-
-@
-\subsection{sman\_catch\_signals}
-<<sman.smancatchsignals>>=
-static void
-sman_catch_signals(void)
-{
-  
-  /* Set up the signal handlers for sman */
-  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
-  bsdSignal(SIGTERM, death_handler,RestartSystemCalls);
-  bsdSignal(SIGQUIT, death_handler,RestartSystemCalls);
-  bsdSignal(SIGHUP,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGILL,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGTRAP, death_handler,RestartSystemCalls);
-  bsdSignal(SIGIOT,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGBUS,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGSEGV, death_handler,RestartSystemCalls);
-  /* don't restart wait call on SIGUSR1  */
-  bsdSignal(SIGUSR1, nagman_handler,DontRestartSystemCalls); 
-  /* ONLY nagman should send this.
-     If an error (such as C-c) interrupts a NAGLINK call, nagman
-     gets a signal to clean up. We need to start another nagman 
-     almost immediately to process the next NAGLINK request.
-     Since nagman takes a while to clean up, we treat it specially.
-     nagman should send a signal (USR1) to sman.
-     sman should respond by spawning a new nagman.
-     
-     so nagman is NOT a DoItAgain but a NadaDelShitsky.
-     
-     The USR1 mechanism does not work for HPUX 9 - use DoItAgain 
-     */
-
-}
-
-@
-\subsection{fix\_env}
-insert SPADSERVER and SPADNUM variables into the environemnt
-<<sman.fixenv>>=
-static void
-fix_env(char **envp, int spadnum)
-{
-  int len, i;
-  char *sn;
-  for(len = 0; envp[len] != NULL; len++);
-  new_envp = (char **) malloc((len + 3) * sizeof(char *));
-  new_envp[0] = "SPADSERVER=TRUE";
-  sn = (char *) malloc(20 * sizeof(char));
-  sprintf(sn, "SPADNUM=%d", spadnum);
-  new_envp[1] = sn;
-  for(i=0; i<=len; i++)
-    new_envp[i+2] = envp[i];
-}
-
-@
-\subsection{init\_term\_io}
-<<sman.inittermio>>=
-static void
-init_term_io(void)
-{
-  if(!isatty(0)) return;
-  if( tcgetattr(0, &oldbuf) == -1) {
-    perror("getting termios");
-    return ; 			/*  exit(-1); */
-  }
-  if( tcgetattr(0, &childbuf) == -1) {
-    perror("getting termios");
-    return ; 			/*   exit(-1); */
-  }
-  _INTR = oldbuf.c_cc[VINTR];
-  _QUIT = oldbuf.c_cc[VQUIT];
-  _ERASE = oldbuf.c_cc[VERASE];
-  _KILL = oldbuf.c_cc[VKILL];
-  _EOF = oldbuf.c_cc[VEOF];
-  _EOL = oldbuf.c_cc[VEOL];
-}
-
-@
-\subsection{strPrefix}
-<<sman.strPrefix>>=
-static char *
-strPrefix(char *prefix,char * s)
-{
-  while (*prefix != '\0' && *prefix == *s) {
-    prefix++;
-    s++;
-  }
-  if (*prefix == '\0') return s;
-  return NULL;
-}
-
-@
-\subsection{check\_spad\_proc}
-<<sman.checkspadproc>>=
-static void
-check_spad_proc(char *file, char *prefix)
-{
-  char *num;
-  int pid;
-  if ((num = strPrefix(prefix, file))) {
-    pid = atoi(num);
-    if (pid > 2) {
-      kill(pid, 0);
-      if (kill(pid, 0) == -1 && errno == ESRCH) {
-	unlink(file);
-      }
-    }
-  }
-}
-
-@
-\subsection{clean\_up\_old\_sockets}
-<<sman.cleanupoldsockets>>=
-static void
-clean_up_old_sockets(void)
-{
-  char com[512], tmp_file[128];
-  FILE *file;
-  int len;
-  sprintf(tmp_file, "/tmp/socks.%d", server_num);
-  sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s",
-	  tmp_file, tmp_file);
-  system(com);
-  file = fopen(tmp_file, "r");
-  if (file == NULL) {
-    fprintf(stderr, "Can't open socket listing file\n");
-    return;
-  }
-  while(fgets(com, 512, file) != NULL) {
-    len = strlen(com);
-    if (len) com[len-1] = '\0';
-    else break;
-    check_spad_proc(com, "/tmp/.d");
-    check_spad_proc(com, "/tmp/.s");
-    check_spad_proc(com, "/tmp/.i");
-    check_spad_proc(com, "/tmp/.h");
-  }
-  fclose(file);
-  unlink(tmp_file);
-}
-
-@
-\subsection{fork\_you}
-<<sman.forkyou>>=
-static SpadProcess *
-fork_you(int death_action)
-{
-  /* fork a new process, giving it a default death action */
-  /* return NULL in child, SpadProcess in parent          */
-  int child_pid = fork();
-  SpadProcess *proc;
-  if (!child_pid) return NULL;
-  proc = (SpadProcess *) malloc(sizeof(SpadProcess));
-  proc->proc_id = child_pid;
-  proc->death_action = death_action;
-  proc->command = NULL;
-  proc->next = spad_process_list;
-  spad_process_list = proc;
-  return proc;
-}
-
-@
-\subsection{exec\_command\_env}
-Note that the next-to-last argument of {\tt execle} must be an
-explicit NULL pointer. The previous naked 0 value was not correct.
-<<sman.execcommandenv>>=
-static void
-exec_command_env(char *command,char ** env)
-{
-  char new_command[512];
-  sprintf(new_command, "exec %s", command);
-  execle("/bin/sh","/bin/sh", "-c", new_command, (char *)0, env);
-}
-
-@
-\subsection{spawn\_of\_hell}
-<<sman.spawnofhell>>=
-static SpadProcess *
-spawn_of_hell(char *command, int death_action)
-{
-  SpadProcess *proc = fork_you(death_action);
-  if (proc != NULL) {
-    proc->command = command;
-    return proc;
-  }
-  exec_command_env(command, new_envp);
-  return NULL;
-}
-
-@
-\subsection{start\_the\_spadclient}
-run a AXIOM client in the main process
-<<sman.startthespadclient>>=
-static void
-start_the_spadclient(void)
-{
-  char command[256];
-  if (start_clef)
-#ifdef RIOSplatform
-    sprintf(command, 
-	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
-	    ClefProgram, SpadClientProgram);
-#else
-  sprintf(command, 
-	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
-	  ClefProgram, SpadClientProgram);
-#endif
-  else
-#ifdef RIOSplatform
-    sprintf(command, 
-	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
-	    SpadClientProgram);
-#else
-  sprintf(command, 
-	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
-	  SpadClientProgram);
-#endif
-  if (tpd == 1) 
-    fprintf(stderr,"sman:start_the_spadclient: %s\n",command);
-  spawn_of_hell(command, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_local\_spadclient}
-<<sman.startthelocalspadclient>>=
-static void
-start_the_local_spadclient(void)
-{
-  char command[256];
-  if (start_clef)
-    sprintf(command, "%s  %s", ClefProgram, SpadClientProgram);
-  else
-    sprintf(command, "%s", SpadClientProgram);
-  if (tpd == 1) 
-    fprintf(stderr,"sman:start_the_local_spadclient: %s\n",command);
-  spawn_of_hell(command, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_nagman}
-<<sman.startthenagman>>=
-static void
-start_the_nagman(void)
-{
-#if defined(HP9platform)
-  spawn_of_hell(NagManagerProgram,DoItAgain);
-#else
-  spawn_of_hell(NagManagerProgram,NadaDelShitsky );
-#endif
-}
-
-@
-\subsection{start\_the\_session\_manager}
-<<sman.startthesessionmanager>>=
-static void
-start_the_session_manager(void)
-{
-  spawn_of_hell(SessionManagerProgram, Die);
-}
-
-@
-\subsection{start\_the\_hypertex}
-<<sman.startthehypertex>>=
-static void
-start_the_hypertex(void)
-{
-  char prog[512];
-
-  if (PasteFile){
-    sprintf(prog, "%s -k -ip %s", HypertexProgram, PasteFile);
-    spawn_of_hell(prog, NadaDelShitsky);
-  }
-  else if (MakeRecordFile){
-    sprintf(prog, "%s -k -rm %s", HypertexProgram,MakeRecordFile );
-    spawn_of_hell(prog, NadaDelShitsky);
-  }
-  else if (VerifyRecordFile){
-    sprintf(prog, "%s -k -rv %s", HypertexProgram, VerifyRecordFile);
-    spawn_of_hell(prog, NadaDelShitsky);
-  }
-  else	spawn_of_hell(HypertexProgram, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_graphics}
-<<sman.startthegraphics>>=
-static void
-start_the_graphics(void)
-{
-  spawn_of_hell(GraphicsProgram, DoItAgain);
-}
-
-@
-\subsection{fork\_Axiom}
-<<sman.forkAxiom>>=
-/* Start the AXIOM session in a separate process, */
-/* using a pseudo-terminal to catch all input and output */
-static void 
-fork_Axiom(void)
-{
-  char augmented_ws_path[256];  /* will append directory path */
-  char *tmp_pointer;
-  SpadProcess *proc;
-
-  proc =  fork_you(Die);
-  child_pid = (proc == NULL ? 0 : proc->proc_id);
-  switch(child_pid) {
-  case -1 :
-    fprintf(stderr, "Can't create a new process \n");
-    exit(0);
-  case 0:
-    /* Dissasociate from my parents group so all my child processes */
-    /* look at my terminal as the controlling terminal for the      */
-    /* group                                                        */
-
-    if(setsid() < 0) {
-      perror("Dissassociating from parents group");
-      exit(-1);
-    }
-
-    close(ptsNum);
-    /* Now reopen the server side, so that pg, su, etc. work properly */
-
-    if ((ptsNum =  open(ptsPath, O_RDWR)) < 0 ) {
-      perror("fork_Axiom: Failed to reopen server");
-      exit(-1);
-    }
-#if defined(SUN4OS5platform) || defined(HP10platform)
-    ioctl(ptsNum,I_PUSH,"ptem");
-    ioctl(ptsNum,I_PUSH,"ldterm");
-#endif
-
-    /* since I am the child, I can close ptc, and dup pts for all its */
-    /* standard descriptors                                           */
-
-    if( (dup2(ptsNum, 0) == -1) ||
-        (dup2(ptsNum, 1) == -1) ||
-        (dup2(ptsNum, 2) == -1)  ) {
-      perror("trying to dupe the child");
-      exit(-1);
-    }
-    close(ptcNum);
-    close(ptsNum);
-
-
-    /* I also have to turn off echoing, since I am echoing all the */
-    /* input myself                  */
-
-    childbuf.c_lflag &= ~ECHO;
-    if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) {
-      perror("setting the term buffer");
-      exit(-1); 
-    }
-    strcpy(augmented_ws_path,ws_path);          /* write the name    */
-    strcat(augmented_ws_path," ");              /* space             */
-    strcat(augmented_ws_path,ws_path);          /* name again        */
-    tmp_pointer = (char *)
-      strrchr(augmented_ws_path,'/');      /*pointer to last /  */
-    *(++tmp_pointer) = '\0';
-    exec_command_env(augmented_ws_path, new_envp);
-
-    /*    fprintf(stderr, "Cannot execute the %s system.\n", ws_path); */
-
-    exit(0);
-  }
-}
-
-@
-\subsection{start\_the\_Axiom}
-<<sman.starttheAxiom>>=
-static void
-start_the_Axiom(char **envp)
-{
-  server_num = make_server_number();
-  clean_up_old_sockets();
-  if (server_num == -1) {
-    fprintf(stderr, "could not get an AXIOM server number\n");
-    exit(-1);
-  }
-  if (ptyopen(&ptcNum, &ptsNum, ptcPath, ptsPath) == -1) {
-    perror("start_the_Axiom: ptyopen failed");
-    exit(-1);
-  }
-  fix_env(envp, server_num);
-  fork_Axiom();
-  close(ptsNum);
-}
-
-@
-\subsection{clean\_up\_sockets}
-<<sman.cleanupsockets>>=
-static void
-clean_up_sockets(void)
-{
-  char name[256];
-  sprintf(name, "%s%d", SpadServer, server_num);
-  unlink(name);
-  sprintf(name, "%s%d", SessionServer, server_num);
-  unlink(name);
-  sprintf(name, "%s%d", SessionIOName, server_num);
-  unlink(name);
-  sprintf(name, "%s%d", MenuServerName, server_num);
-  unlink(name);
-}
-
-@
-\subsection{read\_from\_spad\_io}
-<<sman.readfromspadio>>=
-static void
-read_from_spad_io(int ptcNum)
-{
-  int ret_code = 0, i=0;
-  static int mes_len =0; 
-  ret_code = read(ptcNum, big_bad_buf, BufSize);
-  if (ret_code == -1) {
-    clean_up_sockets();
-    exit(-1);
-  }
-  if (session_io == NULL) {
-    if (ret_code < mes_len)
-      mes_len -= ret_code;
-    else {
-      if (mes_len > 0) {
-	i = mes_len;
-	mes_len = 0;
-      }
-      else
-	i = 0;
-      ret_code = write(1, big_bad_buf+i, ret_code-i);
-    }
-  }
-  else
-    ret_code = swrite(session_io, big_bad_buf, ret_code,
-		      "writing to session man");
-  if (ret_code == -1) {
-    perror("writing output to session manager");
-    clean_up_sockets();
-    exit(-1);
-  }
-}
-
-@
-\subsection{read\_from\_manager}
-<<sman.readfrommanager>>=
-static void
-read_from_manager(int ptcNum)
-{
-  int ret_code;
-  ret_code = sread(session_io, big_bad_buf, BufSize, "reading session io");
-  if (ret_code == -1) {
-    return;
-  }
-  ret_code = write(ptcNum, big_bad_buf, ret_code);
-  if (ret_code == -1) {
-    return;
-  }
-}
-
-@
-\subsection{manage\_spad\_io}
-<<sman.managespadio>>=
-static void
-manage_spad_io(int ptcNum)
-{
-  int ret_code, i, p;
-  fd_set rd;
-  while (1) {
-    rd = socket_mask;
-    FD_SET(ptcNum, &rd);
-    if (session_io != NULL)
-      FD_SET(session_io->socket, &rd);
-    ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
-    if (ret_code == -1) {
-      perror("Session manager select");
-      clean_up_sockets();
-      exit(-1);
-    }
-    if (FD_ISSET(ptcNum, &rd)) {
-      read_from_spad_io(ptcNum);
-    }
-    for(i=0; i<2; i++) {
-      if (server[i].socket > 0 && FD_ISSET(server[i].socket, &rd)) {
-	p = accept_connection(server+i);
-	switch(p) {
-	case SessionIO:
-	  session_io = purpose_table[SessionIO];
-	  /*  printf("connected session manager\n\r");*/
-	  printf("\n");
-	  break;
-	default:
-	  printf("sman: Unkown connection request type: %d\n", p);
-	  break;
-	}
-      }
-    }
-    if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) {
-      read_from_manager(ptcNum);
-    }
-  }
-}
-
-@
-\subsection{init\_spad\_process\_list}
-<<sman.initspadprocesslist>>=
-static void
-init_spad_process_list(void)
-{
-  spad_process_list = NULL;
-}
-
-@
-\subsection{print\_spad\_process\_list}
-<<sman.printspadprocesslist>>=
-#if 0
-static void
-print_spad_process_list()
-{
-  SpadProcess *proc;
-  for(proc = spad_process_list; proc != NULL; proc = proc->next)
-    fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id,
-	    proc->death_action);
-}
-#endif
-
-@
-\subsection{find\_child}
-<<sman.findchild>>=
-static SpadProcess *
-find_child(int proc_id)
-{
-  SpadProcess *proc;
-  for(proc = spad_process_list; proc != NULL; proc = proc->next)
-    if (proc->proc_id == proc_id) return proc;
-  return NULL;
-}
-
-@
-\subsection{kill\_all\_children}
-<<sman.killallchildren>>=
-static void
-kill_all_children(void)
-{
-  char name[256];
-  SpadProcess *proc;
-  
-  
-  for(proc = spad_process_list; proc != NULL; proc = proc->next) {
-    kill(proc->proc_id, SIGTERM);
-  }
-  sprintf(name, "/tmp/hyper%d.input",server_num);
-  unlink(name);
-
-}
-
-@
-\subsection{clean\_up\_terminal}
-<<sman.cleanupterminal>>=
-static void
-clean_up_terminal(void)
-{
-  tcsetattr(0, TCSAFLUSH, &oldbuf);
-}
-
-@
-\subsection{monitor\_children}
-<<sman.monitorchildren>>=
-static void
-monitor_children(void)
-{
-  int dead_baby, stat;
-  SpadProcess *proc;
-  while (1) {
-    stat = 0;
-    dead_baby = wait(&stat);
-    /* Check the value of dead_baby, since wait may have returned
-       a pid but subsequently we have received a signal.  Yeuch! */
-    if (dead_baby == -1 && death_signal) {
-      kill_all_children();
-      clean_up_sockets();
-      clean_up_terminal();
-      sleep(2);
-      exit(0);
-    }
-    /* Check the value of dead_baby, since wait may have returned
-       a pid but subsequently we have received a signal.  Yeuch! */
-    if(dead_baby == -1 && nagman_signal) {
-      nagman_signal=0;
-      spawn_of_hell(NagManagerProgram,NadaDelShitsky);
-      continue;
-    }
-
-    if (dead_baby == -1) {
-      fprintf(stderr, "sman: wait returned -1\n");
-      continue;
-    }
-    proc = find_child(dead_baby);
-    if (proc == NULL) {
-      /*      fprintf(stderr, "sman: %d is not known to be a child process\n",
-	      dead_baby);
-	      */
-      continue;
-    }
-    switch(proc->death_action) {
-    case Die:
-      kill_all_children();
-      clean_up_sockets();
-      clean_up_terminal();
-      sleep(2);
-      exit(0);
-    case NadaDelShitsky:
-      break;
-    case DoItAgain:
-      spawn_of_hell(proc->command, DoItAgain);
-      break;
-    }
-  }
-}
-
-@
-\subsection{main sman}
-The main procedure should return an [[int]]. We change the return value
-here and in [[src/include/sman.h1]].
-<<sman.result>>=
-  return(0);
-@
-<<sman.main>>=
-int
-main(int argc, char *argv[],char *envp[])
-{
-  if (tpd == 1) fprintf(stderr,"sman:main entered\n");
-  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
-  process_options(argc, argv);
-
-  init_term_io();
-  init_spad_process_list();
-  start_the_Axiom(envp);
-  if (open_server(SessionIOName) == -2) {
-    fprintf(stderr, "Fatal error opening I/O socket\n");
-    clean_up_sockets();
-    exit(-1);
-  }
-  start_the_session_manager();
-  if (start_spadclient)       start_the_spadclient();
-  if (start_local_spadclient) start_the_local_spadclient();
-  if (start_nagman)           start_the_nagman();
-  if (start_ht)               start_the_hypertex();
-  if (start_graphics)         start_the_graphics();
-  sleep(1);
-
-  if (fork_you(Die) != NULL) {
-    sman_catch_signals();
-    monitor_children();
-    exit(0);
-  }
-  manage_spad_io(ptcNum);
-  if (tpd == 1) fprintf(stderr,"sman:main exit\n");
-<<sman.result>>
-}
-
-@
-\subsection{sman}
-<<sman>>=
-#define _SMAN_C
-
-<<sman.includes>>
-<<sman.variables>>
-<<sman.processarguments>>
-<<sman.shouldIclef>>
-<<sman.inX>>
-<<sman.setupdefaults>>
-<<sman.processoptions>>
-<<sman.deathhandler>>
-<<sman.nagmanhandler>>
-<<sman.smancatchsignals>>
-<<sman.fixenv>>
-<<sman.inittermio>>
-<<sman.strPrefix>>
-<<sman.checkspadproc>>
-<<sman.cleanupoldsockets>>
-<<sman.forkyou>>
-<<sman.execcommandenv>>
-<<sman.spawnofhell>>
-<<sman.startthespadclient>>
-<<sman.startthelocalspadclient>>
-<<sman.startthenagman>>
-<<sman.startthesessionmanager>>
-<<sman.startthehypertex>>
-<<sman.startthegraphics>>
-<<sman.forkAxiom>>
-<<sman.starttheAxiom>>
-<<sman.cleanupsockets>>
-<<sman.readfromspadio>>
-<<sman.readfrommanager>>
-<<sman.managespadio>>
-<<sman.initspadprocesslist>>
-<<sman.printspadprocesslist>>
-<<sman.findchild>>
-<<sman.killallchildren>>
-<<sman.cleanupterminal>>
-<<sman.monitorchildren>>
-<<sman.main>>
-
-@
 \chapter{The Command Completion List}
 <<command.list>>=
 -
@@ -6723,11 +7121,11 @@ XExponentialPackage
 ZeroDimensionalSolvePackage
 @
 \begin{thebibliography}{99}
-\bibitem{1} Jenks, R.J. and Sutor, R.S. 
-``Axiom -- The Scientific Computation System''
+\bibitem{1} Jenks, R.J. and Sutor, R.S. \\
+``Axiom -- The Scientific Computation System''\\
 Springer-Verlag New York (1992)
 ISBN 0-387-97855-0
-\bibitem{2} Knuth, Donald E., ``Literate Programming''
+\bibitem{2} Knuth, Donald E., ``Literate Programming''\\
 Center for the Study of Language and Information
 ISBN 0-937073-81-4
 Stanford CA (1992) 
@@ -6735,11 +7133,20 @@ Stanford CA (1992)
 {\bf http://wiki.axiom-developer.org}
 \bibitem{4} Watt, Stephen, ``Aldor'',\\
 {\bf http://www.aldor.org}
-\bibitem{5} Lamport, Leslie, ``Latex -- A Document Preparation System'',
+\bibitem{5} Lamport, Leslie,\\
+``Latex -- A Document Preparation System'',
 Addison-Wesley, New York ISBN 0-201-52983-1
-\bibitem{6} Ramsey, Norman ``Noweb -- A Simple, Extensible Tool for
-Literate Programming''\\
+\bibitem{6} Ramsey, Norman\\
+``Noweb -- A Simple, Extensible Tool for Literate Programming''\\
 {\bf http://www.eecs.harvard.edu/ $\tilde{}$nr/noweb}
+\bibitem{7} Axiom Book Volume 7 -- Hyperdoc\\
+{\bf file://usr/local/axiom/src/hyper/bookvol7.pamphlet}
+\bibitem{8} Axiom Book Volume 8 -- Graphics\\
+{\bf file://usr/local/axiom/src/graph/bookvol8.pamphlet}
+\bibitem{9} AIX Version 3.2 and 4 Performance Tuning Guide\\
+{\bf 
+http://www.rs6000.ibm.com/doc\_link/en\_US/\\
+{\hbox {\hskip 1.0cm}}a\_doc\_lib/aixbman/prftungd/toc.htm}
 \end{thebibliography}
 \printindex
 \end{document}

\start
Date: Mon, 27 Aug 2007 03:48:15 -0500
From: Tim Daly
To: list
Subject: synching of all sources

All 5 axiom locations now have the same sources
  cvs.savannah.nongnu.org (CVS)
  cvs.sourceforge.net (CVS)
  svn.sourceforge.net (SVN)
  arch.axiom-developer (ARCH)
  git.axiom-developer (GIT)

I will be away on business this week.

\start
Date: Tue, 28 Aug 2007 12:12:39 -0700
From: Arthur Ralfs
To: list
Subject: Interpreter commands from Spad?

Hi All,

I'm trying to send axiom output to a browser using spad sockets.
So far I'm hung up on submitting the command to axiom from
within spad and understanding the result.  Below is my code
attempt to date.  I am not at this point trying to actually send
anything back to the browser.

First the lisp stuff, file: http.lisp
-------------------------------------------------------------
;; file: http.lisp

;; some regexp stuff

(defun |StringMatch| (s1 s2)
  (si::string-match s1 s2)
  )


(defun |MatchBeginning| (i)
  (si::match-beginning i)
  )

(defun |MatchEnd| (i)
  (si::match-end i)
  )

;; the socket stuff


(defun |SiSock| (p spadfn)
;;  (format t "SiSocket-1")
  (si::socket p :server
          (function
           (lambda (w) (SPADCALL w spadfn) )
           )
          :daemon nil)
  )

(defun |SiListen| (s)
;;  (format t "SiListen-1")
  (si::listen s)
  )
(defun |SiAccept| (s) (si::accept s))
(defun |SiCopyStream| (q s) (si::copy-stream q s))


-----------------------------------------------------------------------

Now the spad code, file axserver.spad

-----------------------------------------------------------------------

)abbrev package SISOCK SiSocket
SiSocket: with
    socketServer: (Integer, SExpression->Void) -> Void
    axserver: SExpression -> Void

  == add

    socketServer(port:Integer,serverfunc:SExpression->Void):Void ==
      WRITE_-LINE("socketServer")$Lisp
      WRITE_-LINE("")$Lisp
      s := SiSock(port,serverfunc)$Lisp
      -- I listen for just one connection and then close the socket
      -- to make debugging easier
      i:Integer := 1
      while (i > 0) repeat
        if not null?(SiListen(s)$Lisp)$SExpression then
          w := SiAccept(s)$Lisp
          serverfunc(w)
      i := 0
      CLOSE(s)$Lisp



    axserver(s:SExpression):Void ==
      httpheaders:List String := []
      httphead:String
      numheads:Integer := 0
      i:Integer
      itest:Integer
      jtest:Integer := 1
      -- read in the http headers
      while jtest > 0 repeat
          httphead := ""
              itest := 1
          while itest > 0 repeat
              c := STRING(READ_-CHAR(s)$Lisp)$Lisp
          if c = " " then itest := 0
              else httphead := concat [httphead, c]
              numheads := numheads + 1
          -- I want to test when there are no more characters to read in s
          -- but don't know how to do it properly.  The "Connection:" header
          -- is the last one I've noticed so I just test for that for now.
          --  I could also use read-char-no-hang, test for nil, wait a
bit, and
          -- try again.
          if StringMatch("Connection:",httphead)$Lisp > -1 then
              jtest := 0
              httpheaders := concat!(httpheaders, httphead)
      headers:String := ""
      for i in 1..#httpheaders repeat
          headers := concat [headers," ",httpheaders.i]
      sayTeX$Lisp headers
      -- Pick out the axiom command from the GET string. It should be
      -- encoded as, e.g., http://localhost:8085/?axiom=(x+y)**2
      StringMatch( "(/?axiom=)(.*)",httpheaders.2)$Lisp
      axcomm:String
      u:UniversalSegment(Integer)
      u :=
segment(MatchBeginning(2)$Lisp+1,MatchEnd(2)$Lisp)$UniversalSegment(Integer)
      axcomm := (httpheaders.2).u
      -- I found 2 functions in interp/server.boot.pamphlet which seem to
      -- be what I want.  I don't see any difference between them.
--      parseAndEvalStr$Lisp axcomm
      parseAndInterpret$Lisp axcomm
      -- fetchOutput is defined in interp/i-hist.boot.pamphlet
      histvar := fetchOutput(-1)$Lisp
      display(coerce(histvar)$TexFormat)$TexFormat

----------------------------------------------------------------------------

To run this example I first enter:

)lisp (load "http.lisp")

)compile axserver

Now I include my actual axiom output

----------------------------------------------------------------------------

(1) -> )set messages autoload off
(1) -> (x+y)**2

         2           2
   (1)  y  + 2x y + x
                                                     Type: Polynomial
Integer
(2) -> coerce(%)$TexFormat

   (2)  ["$$","{y \sp 2}+{2 \  x \  y}+{x \sp 2} ","$$"]
                                                             Type:
OutputForm
(3) -> socketServer(8085,axserver$SISOCK)
socketServer

 GET /?axiom=(x+y)**2 HTTP/1.1
Host: 127.0.0.1:8085
Gecko/20061023 SUSE/2.0.0.4-1.1 Firefox/2.0.0.4
Accept:
text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection:

         2           2
   (3)  y  + 2x y + x
                                                     Type: Polynomial
Integer
$$
{Polynomial
\left(
{{Integer()}}
\right)}
\left(
{WRAPPED, \: 1, \: y, \: {2
\left(
{0}
\right)},
\: {1
\left(
{1, \: x, \: {1
\left(
{0}
\right)}}
\right)},
\: {0
\left(
{1, \: x, \: {2
\left(
{0}
\right)}}
\right)}}
\right)
$$

--------------------------------------------------------------------------

My problem is that I don't know how to interpret the output
and get the correctly formatted TeX.  At this point I've tried
everything I can think of.

\start
Date: 29 Aug 2007 10:52:11 +0200
From: Martin Rubey
To: Arthur Ralfs
Subject: Re: Interpreter commands from Spad?

Dear Arthur,

I'm not sure whether I understand what you are after, so please correct me:

* you are able to make Axiom interpret a string entered into the browsers
  adressbar

* you would like to display the result in the browser?

Did you look at my code in HyperDocReplacement on MathAction?  I use file-io,
because I want to use tex4ht to transform the result into html (or mathml or
whatever).  I guess that this is not what you want, so please give me some
further hints!

\start
Date: Wed, 29 Aug 2007 08:27:24 -0400
From: Bill Page
To: Arthur Ralfs
Subject: Re: Interpreter commands from Spad?

On 8/28/07, Arthur Ralfs wrote:
> ...
> My problem is that I don't know how to interpret the output
> and get the correctly formatted TeX.  At this point I've tried
> everything I can think of.
>

Perhaps this approach suggested by Tim Daly a few years ago will help:

http://lists.nongnu.org/archive/html/axiom-developer/2005-05/msg00228.html

)lisp (progn
        (setq tmpout (make-string-output-stream))
        (setq save |$algebraOutputStream|)
        (setq |$algebraOutputStream| tmpout)
        (|parseAndInterpret| "(x+1)^9")
        (setq result (get-output-stream-string |$algebraOutputStream|))
        (setq |$algebraOutputStream| save)
        result)

)lisp result

\start
Date: Wed, 29 Aug 2007 09:34:38 -0700
From: Arthur Ralfs
To: list
Subject: Re: Interpreter commands from Spad?

Thanks for the suggestions from Bill and Martin.
I hope to have some time to look at this problem
later today.

\start
Date: Wed, 29 Aug 2007 13:01:59 -0400
From: Bill Page
To: Arthur Ralfs
Subject: Re: Interpreter commands from Spad?

If you are interested in the LaTeX output from the Axiom interpreter
you will need to re-direct a different stream. I.e. $texOutputStream
instead of $algebraOutputStream. For example:

(1) -> )set message autoload off
(1) -> )set output tex on
(1) -> )lisp (progn (setq tmpout (make-string-output-stream)) (setq save |$texOu
tputStream|) (setq |$texOutputStream| tmpout) (|parseAndInterpret| "(x+1)^9") (s
etq |result| (get-output-stream-string |$texOutputStream|)) (setq |$texOutputStr
eam| save))

         9     8      7      6       5       4      3      2
   (1)  x  + 9x  + 36x  + 84x  + 126x  + 126x  + 84x  + 36x  + 9x + 1
                                                     Type: Polynomial Integer
Value = #<synonym stream to *TERMINAL-IO*>
(2) -> )set output tex off
(2) -> string(result$Lisp)

   (2)
  "$$
{x \sp 9}+{9 \  {x \sp 8}}+{{36} \  {x \sp 7}}+{{84} \  {x \sp 6}}+{{126}
   \
{x \sp 5}}+{{126} \  {x \sp 4}}+{{84} \  {x \sp 3}}+{{36} \  {x \sp 2}}+
  {9 \
x}+1
\leqno(1)
$$

"
                                                                 Type: String
(3) ->

---------

You should be able to use (2) above in a Spad program.

Regards,
Bill Page.

On 8/29/07, Arthur Ralfs wrote:
> Thanks for the suggestions from Bill and Martin.
> I hope to have some time to look at this problem
> later today.

\start
Date: Mon, 27 Aug 2007 02:23:25 -0500
From: Tim Daly
To: list
Subject: 20070811.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 7cbe49b..e3d84c9 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,13 @@
+20070811 tpd src/input/Makefile add mathml.input
+20070811 tpd src/input/mathml.input write test cases
+20070810 tpd readme add Arthur C. Ralfs
+20070810 tpd src/interp/setq.lisp add Arthur C. Ralfs
+20070810 tpd src/algebra/Makefile add mathml.spad
+20070810 acr src/algebra/exposed.lsp add (|MathMLFormat| . MMLFORM)
+20070810 acr src/interp/i-output.boot added mathml patch
+20070810 acr scr/interp/setvars.boot add mathml patch
+20070810 acr scr/interp/setvart.boot add mathml patch
+20070810 acr Arthur Ralfs
 20070810 tpd src/interp/metameta.lisp removed (unused)
 20070810 tpd src/interp/ccl-depsys.lsp remove metameta
 20070810 tpd src/interp/parsing.lisp remove metameta
diff --git a/readme b/readme
index 112fa70..578fc37 100644
--- a/readme
+++ b/readme
@@ -221,9 +221,10 @@ at the axiom command prompt will prettyprint the list.
 "Michel Petitot         Didier Pinchon         Ayal Pinkus"
 "Jose Alfredo Portes"
 "Claude Quitte"
-"Norman Ramsey          Michael Richardson     Renaud Rioboo"
-"Jean Rivlin            Nicolas Robidoux       Simon Robinson"
-"Raymond Rogers         Michael Rothstein      Martin Rubey"
+"Arthur C. Ralfs        Norman Ramsey          Michael Richardson"
+"Renaud Rioboo          Jean Rivlin            Nicolas Robidoux"
+"Simon Robinson         Raymond Rogers         Michael Rothstein"
+"Martin Rubey"
 "Philip Santas          Alfred Scheerhorn      William Schelter"
 "Gerhard Schneider      Martin Schoenert       Marshall Schor"
 "Frithjof Schulze       Fritz Schwarz          Nick Simicich"
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index 987ea71..9172e69 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -743,7 +743,8 @@ view3d.spad.pamphlet (VIEW3D)
 
 LAYER17=\
   ${OUT}/CCLASS.o  ${OUT}/FSAGG2.o  ${OUT}/GALFACT.o ${OUT}/IALGFACT.o \
-  ${OUT}/IBACHIN.o ${OUT}/NORMMA.o  ${OUT}/ODERED.o  ${OUT}/OMSAGG.o   \
+  ${OUT}/IBACHIN.o ${OUT}/MMLFORM.o \
+  ${OUT}/NORMMA.o  ${OUT}/ODERED.o  ${OUT}/OMSAGG.o   \
   ${OUT}/PERM.o    ${OUT}/PERMGRP.o ${OUT}/PRIMES.o  ${OUT}/PWFFINTB.o \
   ${OUT}/RDIST.o   ${OUT}/SAE.o     ${OUT}/SAEFACT.o ${OUT}/SAERFFC.o  \
   ${OUT}/SGCF.o    ${OUT}/TBAGG.o   ${OUT}/TBAGG-.o  ${OUT}/VIEW3D.o  \
@@ -1249,7 +1250,8 @@ SPADFILES= \
  ${OUTSRC}/list.spad ${OUTSRC}/lmdict.spad ${OUTSRC}/lodof.spad \
  ${OUTSRC}/lodop.spad ${OUTSRC}/lodo.spad \
  ${OUTSRC}/manip.spad ${OUTSRC}/mappkg.spad ${OUTSRC}/matcat.spad \
- ${OUTSRC}/matfuns.spad ${OUTSRC}/matrix.spad ${OUTSRC}/matstor.spad \
+ ${OUTSRC}/matfuns.spad ${OUTSRC}/mathml.spad \
+ ${OUTSRC}/matrix.spad ${OUTSRC}/matstor.spad \
  ${OUTSRC}/mesh.spad ${OUTSRC}/mfinfact.spad ${OUTSRC}/misc.spad \
  ${OUTSRC}/mkfunc.spad ${OUTSRC}/mkrecord.spad \
  ${OUTSRC}/mlift.spad ${OUTSRC}/moddfact.spad ${OUTSRC}/modgcd.spad \
@@ -1409,7 +1411,8 @@ DOCFILES= \
  ${DOC}/list.spad.dvi ${DOC}/lmdict.spad.dvi ${DOC}/lodof.spad.dvi \
  ${DOC}/lodop.spad.dvi ${DOC}/lodo.spad.dvi \
  ${DOC}/manip.spad.dvi ${DOC}/mappkg.spad.dvi ${DOC}/matcat.spad.dvi \
- ${DOC}/matfuns.spad.dvi ${DOC}/matrix.spad.dvi ${DOC}/matstor.spad.dvi \
+ ${DOC}/matfuns.spad.dvi ${DOC}/mathml.spad.dvi \
+ ${DOC}/matrix.spad.dvi ${DOC}/matstor.spad.dvi \
  ${DOC}/mesh.spad.dvi ${DOC}/mfinfact.spad.dvi ${DOC}/misc.spad.dvi \
  ${DOC}/mkfunc.spad.dvi ${DOC}/mkrecord.spad.dvi ${DOC}/mlift.spad.jhd.dvi \
  ${DOC}/mlift.spad.dvi ${DOC}/moddfact.spad.dvi ${DOC}/modgcd.spad.dvi \
diff --git a/src/algebra/exposed.lsp.pamphlet b/src/algebra/exposed.lsp.pamphlet
index 498b79a..c893d91 100644
--- a/src/algebra/exposed.lsp.pamphlet
+++ b/src/algebra/exposed.lsp.pamphlet
@@ -207,6 +207,7 @@
   (|MappingPackage1| . MAPPKG1)
   (|MappingPackage2| . MAPPKG2)
   (|MappingPackage3| . MAPPKG3)
+  (|MathMLFormat| . MMLFORM)
   (|Matrix| . MATRIX)
   (|MatrixCategoryFunctions2| . MATCAT2)
   (|MatrixCommonDenominator| . MCDEN)
diff --git a/src/algebra/mathml.spad.pamphlet b/src/algebra/mathml.spad.pamphlet
new file mode 100644
index 0000000..c589e78
--- /dev/null
+++ b/src/algebra/mathml.spad.pamphlet
@@ -0,0 +1,1376 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/algebra mathml.spad}
+\author{Arthur C. Ralfs}
+\maketitle
+\begin{abstract}
+MathMLFormat is a package to produce presentation mathematical
+markup language from OutputForm.
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{Preface}
+
+Both this code and documentation are still under development and
+I don't pretend they are anywhere close to perfect or even finished.
+However the code does work and I hope it might be useful to somebody
+both for it's ability to output MathML from Axiom and as an example
+of how to write a new output form.
+
+\section{Introduction to Mathematical Markup Language}
+
+MathML exists in two forms: presentation and content.
+At this time (2007-02-11) the package only has a presentation
+package.  A content package is in the
+works however it is more difficult.  Unfortunately Axiom does
+not make its semantics easliy available.  The \spadtype{OutputForm}
+domain mediates between the individual Axiom domains and the
+user visible output but \spadtype{OutputForm} does not provide full
+semantic information.  From my currently incomplete understanding
+of Axiom it appears that remedying this would entail going back
+to the individual domains and rewriting a lot of code.
+However some semantics are conveyed directly by \spadtype{OutputForm} and other
+things can be deduced from \spadtype{OutputForm} or form the original
+user command.
+
+\section{Displaying MathML}
+
+The MathML string produced by ")set output mathml on" can be pasted
+directly into an appropriate xhtml page and then viewed in Firefox
+or some other MathML aware browser. The boiler plate code needed for
+a test page, testmathml.xml, is:
+
+\begin{verbatim}
+<?xml version="1.0" ?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
+                      "http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd" [
+<!ENTITY mathml "http://www.w3.org/1998/Math/MathML">
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xlink="http://www.w3.org/1999/xlink" >
+
+
+  <head>
+    <title>MathML Test </title>
+  </head>
+
+  <body>
+
+  </body>
+</html>
+\end{verbatim}
+
+
+Paste the MathML string into the body element and it should display
+nicely in Firefox.
+
+\section{Test Cases}
+
+Here's a list of test cases that currently format correctly:
+
+1. (x+y)**2
+
+2. integrate(x**x,x)
+
+3. integral(x**x,x)
+
+4. (5 + sqrt 63 + sqrt 847)**(1/3)
+
+5. set $[$1,2,3$]$
+
+6. multiset $[$x rem 5 for x in primes(2,1000)$]$
+
+7. series(sin(a*x),x=0)
+
+8. matrix $[$ $[$x**i + y**j for i in 1..10$]$ for j in 1..10$]$
+
+9. y := operator 'y
+   a. D(y(x,z),$[$x,x,z,x$]$)
+   b. D(y x,x,2)
+
+10. x := series 'x
+    a. sin(1+x)
+
+11. series(1/log(y),y=1)
+
+12. y:UTS(FLOAT,'z,0) := exp(z)
+
+13. a. c := continuedFraction(314159/100000)
+    b. c := continuedFraction(314159/100000)
+
+The \spadtype{TexFormat} domain has the capability to format an object with
+subscripts, superscripts, presubscripts and presuperscripts however
+I don't know of any Axiom command that produces such an object. In
+fact at present I see the case of "SUPERSUB" being used for putting
+primes in the superscript position to denote ordinary differentiation.
+I also only see the "SUB" case being only used to denote partial
+derivatives.
+
+\section{)set output mathml on}
+
+
+Making mathml appear as output during a normal Axiom session
+by invoking ")set output mathml on" proved to be a bit tedious
+and seems to be undocumented.  I document my experience here
+in case in proves useful to somebody else trying to get a new
+output format from Axiom.
+
+In \spadtype{MathMLFormat} the functions 
+\spadfun{coerce(expr : OutputForm) : String} and
+\spadfun{display(s : String) : Void} provide the desired mathml output.
+Note that this package was constructed by close examination of
+Robert Sutor's \spadtype{TexFormat} domain and much remains from that source.
+To have mathml displayed as output we need to get Axiom to 
+call display(coerce(expr)) at the appropriate place.  Here's what
+I did to get that to happen. Note that my starting point here was
+an attempt by Andrey Grozin to do the same.  To figure things out
+I searched through files for "tex" to see what was done for the
+\spadtype{TexFormat} domain, and used grep to find which files had mention of
+\spadtype{TexFormat}.
+
+\subsection{File src/interp/setvars.boot.pamphlet}
+
+
+  Create an output mathml section by analogy to the tex section.
+Remember to add the code chunk "outputmathmlCode" at the end.
+
+setvars.boot is a bootstrap file which means that it has to be
+precompiled into lisp code and then that code has to be inserted
+back into setvars.boot. To do this extract the boot code by running
+"notangle" on it.  I did this from the "tmp" directory.
+From inside axiom run ")lisp (boottran::boottocl "tmp/setvars.boot")
+which put "setvars.clisp" into "int/interp/setvars.clisp".  Then
+replace the lisp in "setvars.boot.pamphlet" with that in the newly
+generated "setvars.clisp".
+
+The relevant code chunks appearing in "setvars.boot.pamphlet" are:
+\begin{verbatim}
+    outputmathmlCode
+    setOutputMathml
+    describeSetOutputMathml
+\end{verbatim}
+and the relevant variables are:
+\begin{verbatim}
+    setOutputMathml
+    $mathmlOutputStream
+    $mathmlOutputFile
+    $mathmlFormat
+    describeSetOutputMathml
+\end{verbatim}
+
+\subsection{File setvart.boot.pamphlet}
+
+
+Create an output mathml section in "setvart.boot.pamphlet" again
+patterned after the tex section.  I changed the default file 
+extension from ".stex" to ".smml".
+
+To the "section{output}" table I added the line
+\begin{verbatim}
+   mathml		   created output in MathML style	Off:CONSOLE
+\end{verbatim}
+Added the code chunk "outputmathml" to the code chunk "output"
+in "section{output}".
+
+Relevant code chunks:
+\begin{verbatim}
+	 outputmathml
+\end{verbatim}
+Relevant variables:
+\begin{verbatim}
+	 setOutputMathml
+	 $mathmlFormat
+	 $mathmlOutputFile
+\end{verbatim}
+
+Note when copying the tex stuff I changed occurrences of "tex"
+to "mathml", "Tex" to "Mathml" and "TeX" to "MathML".
+
+\subsection{File src/algebra/Makefile.pamphlet}
+
+
+The file "src/algebra/tex.spad.pamphlet" contains
+the domain \spadtype{TexFormat} (TEX) and the package 
+\spadtype{TexFormat1} (TEX1).
+However the sole function of \spadtype{TexFormat1} is to \spadfun{coerce}
+objects from a domain into \spadtype{OutputForm} and then apply 
+\spadtype{TexFormat}
+to them.  It is to save programmers the trouble of doing
+the coercion themselves from inside spad code.  It does
+not appear to be used for the main purpose of delivering
+Axiom output in TeX format.  In order to keep the mathml
+package as simple as possible, and because I didn't see much
+use for this, I didn't copy the \spadtype{TexFormat1} package.  So
+no analog of the TEX1 entries in "Makefile.pamphlet" were
+needed.  One curiosity I don't understand is why TEX1
+appears in layer 4 when it seems to depend on TEX which
+appears in layer 14.
+
+Initially I added "\${OUT}/MMLFORM.o" to layer 14 and
+"mathml.spad.pamphlet" to completed spad files in layer 14.
+When trying to compile the build failed at MMLFORM.  It left
+"MMLFORM.erlib" in "int/algebra" instead of "MMLFORM.NRLIB"
+which confused me at first because mathml.spad compiled
+under a running axiom.  By examining the file "obj/tmp/trace"
+I saw that a new dependency had been introduced, compared
+to TexFormat, with the function eltName depending on the
+domain FSAGG in layer 16.  So the lines had to be moved 
+from layer 14 to layer 17.
+
+Added appropriate lines to "SPADFILES" and "DOCFILES".
+
+\subsection{File src/algebra/exposed.lsp.pamphlet}
+
+Add the line "($\vert{}$MathMLFormat$\vert$ . MMLFORM)"
+
+\subsection{File src/algebra/Lattice.pamphlet}
+
+I don't see that this file is used anywhere but I made
+the appropriate changes anyway by searching for "TEX" and
+mimicing everthing for MMLFORM.
+
+\subsection{File src/doc/axiom.bib.pamphlet}
+
+Added mathml.spad subsection to "src/doc/axiom.bib.pamphlet".
+
+\subsection{File interp/i-output.boot.pamphlet}
+
+
+This is where the \spadfun{coerce} and \spadfun{display} functions 
+from MathMLFormat
+actually get called.  The following was added:
+
+\begin{verbatim}
+mathmlFormat expr ==
+  mml := '(MathMLFormat)
+  mmlrep := '(String)
+  formatFn := getFunctionFromDomain("coerce",mml,[$OutputForm])
+  displayFn := getFunctionFromDomain("display",mml,[mmlrep])
+  SPADCALL(SPADCALL(expr,formatFn),displayFn)
+  TERPRI $mathmlOutputStream
+  FORCE_-OUTPUT $mathmlOutputStream
+  NIL
+\end{verbatim}
+
+Note that compared to the texFormat function there are a couple
+of differences.  Since \spadtype{MathMLFormat} is currently a package rather
+than a domain there is the "mmlrep" variable whereas in texFormat
+the argument of the "display" function is an instance of the 
+domain.  Also the \spadfun{coerce} function here only has one argument,
+namely "\$OutputForm".
+
+Also for the function "output(expr,domain)" add lines for mathml,
+e.g. "if \$mathmlFormat then mathmlFormat expr".
+
+After these changes Axiom compiled with mathml enabled under
+)set output.
+
+\section{package MMLFORM MathMLFormat}
+
+\subsection{Public Declarations}
+
+The declarations
+\begin{verbatim}
+  E      ==> OutputForm
+  I      ==> Integer
+  L      ==> List
+  S      ==> String
+  US     ==> UniversalSegment(Integer)
+\end{verbatim}
+provide abbreviations for domains used heavily in the code.
+The publicly exposed functions are:
+
+    \spadfun{coerce: E -$>$ S}  This function is the main one for converting
+and expression in domain OutputForm into a MathML string.
+
+    \spadfun{coerceS: E -$>$ S}  This function is for use from the command line.
+It converts an OutputForm expression into a MathML string and does
+some formatting so that the output is not one long line.  If you take
+the output from this function, stick it in an emacs buffer in
+nxml-mode and then indent according to mode, you'll get something that's
+nicer to look at than comes from coerce. Note that coerceS returns
+the same value as coerce but invokes a display function as well so that
+the result will be printed twice in different formats.  The need for this
+is that the output from coerce is automatically formatted with line breaks
+by Axiom's output routine that are not in the right place.
+
+    \spadfun{coerceL: E -$>$ S}  Similar to coerceS except that the displayed result
+is the MathML string in one long line.  These functions can be used,
+for instance, to get the MathML for the previous result by typing
+coerceL(%)\$MMLFORM.
+
+    \spadfun{exprex: E -$>$ S}  Converts \spadtype{OutputForm} to 
+\spadtype{String} with
+the structure preserved with braces.  This is useful in developing this
+package. Actually this is not quite accurate.  The function
+\spadfun{precondition} is first applied to the \spadtype{OutputForm}
+expression before \spadfun{exprex}.   Raw \spadtype{OutputForm} and the nature
+of the \spadfun{precondition} function is still obscure to me at the time of
+this writing (2007-02-14), however I probably need to understand it to make
+sure I'm not missing any semantics.  The spad function \spadfun{precondition}
+is just a wrapper for the lisp function outputTran\$Lisp, which I guess is
+compiled from boot.
+
+    \spadfun{display: S -$>$ Void}  This one prints the string returned by coerce as one
+long line, adding "math" tags: $<$math ...$>$ ... $<$/math$>$.  Thus the output
+from this can be stuck directly into an appropriate html/xhtml page and will
+be displayed nicely by a MathML aware browser.
+
+    \spadfun{displayF: S -$>$ Void}  This function doesn't exist 
+yet but it would be nice
+to have a humanly readable formatted output as well.  The basics do exist in
+the coerceS function however the formatting still needs some work to be 
+really good.
+
+<<public declarations>>=
+)abbrev domain MMLFORM MathMLFormat
+++ Author: Arthur C. Ralfs
+++ Date: January 2007
+++ This package is based on the TeXFormat domain by Robert S. Sutor
+++ without which I wouldn't have known where to start.
+++ Basic Operations: coerce, coerceS, coerceL, exprex, display
+++ Description:
+++    \spadtype{MathMLFormat} provides a coercion from \spadtype{OutputForm}
+++    to MathML format.
+
+MathMLFormat(): public == private where
+  E      ==> OutputForm
+  I      ==> Integer
+  L      ==> List
+  S      ==> String
+  US     ==> UniversalSegment(Integer)
+
+  public == SetCategory with
+    coerce:    E -> S
+      ++ coerceS(o) changes o in the standard output format to MathML
+      ++ format.
+    coerceS:   E -> S
+      ++ coerceS(o) changes o in the standard output format to MathML
+      ++ format and displays formatted result.
+    coerceL:   E -> S
+      ++ coerceS(o) changes o in the standard output format to MathML
+      ++ format and displays result as one long string.
+    exprex:    E -> S
+      ++ coverts \spadtype{OutputForm} to \spadtype{String} with the
+      ++ structure preserved with braces.  Actually this is not quite
+      ++ accurate.  The function \spadfun{precondition} is first 
+      ++ applied to the
+      ++ \spadtype{OutputForm} expression before \spadfun{exprex}.  
+      ++ The raw \spadtype{OutputForm} and
+      ++ the nature of the \spadfun{precondition} function is 
+      ++ still obscure to me
+      ++ at the time of this writing (2007-02-14).
+    display:   S -> Void
+      ++ prints the string returned by coerce, adding <math ...> tags.
+
+@
+\subsection{Private Constant Declarations}
+<<private constant declarations>>=
+  private == add
+    import OutputForm
+    import Character
+    import Integer
+    import List OutputForm
+    import List String
+
+    -- local variables declarations and definitions
+
+    expr: E
+    prec,opPrec: I
+    str:  S
+    blank         : S := " \  "
+
+    maxPrec       : I   := 1000000
+    minPrec       : I   := 0
+
+    unaryOps      : L S := ["-","^"]$(L S)
+    unaryPrecs    : L I := [700,260]$(L I)
+
+    -- the precedence of / in the following is relatively low because
+    -- the bar obviates the need for parentheses.
+    binaryOps     : L S := ["+->","|","**","/","<",">","=","OVER"]$(L S)
+    binaryPrecs   : L I := [0,0,900, 700,400,400,400,   700]$(L I)
+
+    naryOps       : L S := ["-","+","*",blank,",",";"," ","ROW","",
+       " \cr ","&","</mtd></mtr><mtr><mtd>"]$(L S)
+    naryPrecs     : L I := [700,700,800,  800,110,110,  0,    0, 0,
+             0,  0,   0]$(L I)
+    naryNGOps     : L S := ["ROW","&"]$(L S)
+
+    plexOps       : L S := ["SIGMA","SIGMA2","PI","PI2","INTSIGN","INDEFINTEGRAL"]$(L S)
+    plexPrecs     : L I := [    700, 800,     700, 800 , 700,      700]$(L I)
+
+    specialOps    : L S := ["MATRIX","BRACKET","BRACE","CONCATB","VCONCAT",  _
+                            "AGGLST","CONCAT","OVERBAR","ROOT","SUB","TAG", _
+                            "SUPERSUB","ZAG","AGGSET","SC","PAREN", _
+                            "SEGMENT","QUOTE","theMap" ]
+
+    -- the next two lists provide translations for some strings for
+    -- which MML provides special macros.
+
+    specialStrings : L S :=
+      ["cos", "cot", "csc", "log", "sec", "sin", "tan",
+        "cosh", "coth", "csch", "sech", "sinh", "tanh",
+          "acos","asin","atan","erf","...","$","infinity"]
+    specialStringsInMML : L S :=
+      ["<mo>cos</mo>","<mo>cot</mo>","<mo>csc</mo>","<mo>log</mo>","<mo>sec</mo>","<mo>sin</mo>","<mo>tan</mo>",
+        "<mo>cosh</mo>","<mo>coth</mo>","<mo>csch</mo>","<mo>sech</mo>","<mo>sinh</mo>","<mo>tanh</mo>",
+          "<mo>arccos</mo>","<mo>arcsin</mo>","<mo>arctan</mo>","<mo>erf</mo>","<mo>&#x2026;</mo>","<mo>$</mo>","<mo>&#x221E;</mo>"]
+
+@
+\subsection{Private Function Declarations}
+
+These are the local functions:
+
+    addBraces:S -$>$ S
+
+    addBrackets:S -$>$ S
+
+    atomize:E -$>$ L E
+
+    displayElt:S -$>$ Void
+      function for recursively displaying mathml nicely formatted
+
+    eltLimit:(S,I,S) -$>$ I
+      demarcates end postion of mathml element with name:S starting at
+      position i:I in mathml string s:S and returns end of end tag as
+      i:I position in mathml string, i.e. find start and end of
+      substring:  $<$name ...$>$...$<$/name$>$
+
+    eltName:(I,S) -$>$ S
+      find name of mathml element starting at position i:I in string s:S
+
+    group:S -$>$ S
+
+    formatBinary:(S,L E, I) -$>$ S
+
+    formatFunction:(S,L E, I) -$>$ S
+
+    formatMatrix:L E -$>$ S
+
+    formatNary:(S,L E, I) -$>$ S
+
+    formatNaryNoGroup:(S,L E, I) -$>$ S
+
+    formatNullary:S -$>$ S
+
+    formatPlex:(S,L E, I) -$>$ S
+
+    formatSpecial:(S,L E, I) -$>$ S
+
+    formatUnary:(S,  E, I) -$>$ S
+
+    formatMml:(E,I) -$>$ S
+
+    newWithNum:I -$>$ \$
+      this is a relic from tex.spad and is not used here so far.  I'll
+      probably remove it.
+
+    parenthesize:S -$>$ S
+
+    precondition:E -$>$ E
+      this function is applied to the OutputForm expression before
+      doing anything else.
+
+    postcondition:S -$>$ S
+      this function is applied after all other OutputForm -$>$ MathML
+      transformations.  In the TexFormat domain the ungroup function
+      first peels off the outermost set of braces however I have 
+      replaced braces with $<$mrow$>$s here and sometimes the outermost set
+      of $<$mrow$>$s is necessary to get proper display in Firefox.  
+      For instance with getting the correct size of brackets on a matrix 
+      the whole expression needs to be enclosed in a mrow element.  
+      It also checks for $+-$ and removes the $+$.
+
+    stringify:E -$>$ S
+
+    tagEnd:(S,I,S) -$>$ I
+      finds closing "$>$" of start or end tag for mathML element for formatting
+      MathML string for human readability.  No analog in TexFormat.
+
+    ungroup:S -$>$ S
+
+<<private function declarations>>=
+    -- local function signatures
+
+    addBraces:      S -> S
+    addBrackets:    S -> S
+    atomize:        E -> L E
+    displayElt:     S -> Void
+      ++ function for recursively displaying mathml nicely formatted
+    eltLimit:       (S,I,S) -> I
+      ++ demarcates end postion of mathml element with name:S starting at
+      ++ position i:I in mathml string s:S and returns end of end tag as
+      ++  i:I position in mathml string, i.e. find start and end of
+      ++  substring:  <name ...>...</name>
+    eltName:        (I,S) -> S
+      ++ find name of mathml element starting at position i:I in string s:S
+    group:          S -> S
+    formatBinary:   (S,L E, I) -> S
+    formatFunction: (S,L E, I) -> S
+    formatIntSign:  (L E, I) -> S
+    formatMatrix:   L E -> S
+    formatNary:     (S,L E, I) -> S
+    formatNaryNoGroup: (S,L E, I) -> S
+    formatNullary:  S -> S
+    formatPlex:     (S,L E, I) -> S
+    formatSpecial:  (S,L E, I) -> S
+    formatSub:      (E, L E, I) -> S
+    formatSuperSub: (E, L E, I) -> S
+    formatSuperSub1: (E, L E, I) -> S
+    formatUnary:    (S,  E, I) -> S
+    formatMml:      (E,I) -> S
+    formatZag:      L E -> S
+    formatZag1:     L E -> S
+    newWithNum:     I -> $
+    parenthesize:   S -> S
+    precondition:   E -> E
+    postcondition:  S -> S
+    stringify:      E -> S
+    tagEnd:         (S,I,S) -> I
+      ++  finds closing ">" of start or end tag for mathML element
+    ungroup:        S -> S
+
+@
+\subsection{Public Function Definitions}
+
+Note that I use the function sayTeX\$Lisp much as I would printf in a
+C program.  I've noticed in grepping the code that there are other "say"
+functions, sayBrightly and sayMessage for instance, but I have no idea
+what the difference is between them at this point.  sayTeX\$Lisp does the
+job so for the time being I'll use that until I learn more.
+
+The functions coerceS and coerceL should probably be changed to display
+functions, {\it i.e.}\/ \spadfun{displayS} and \spadfun{display L}, 
+returning Void.  I really only need the one coerce function.
+
+<<public function definitions>>=
+    -- public function definitions
+
+    coerce(expr : E): S ==
+      s : S := postcondition formatMml(precondition expr, minPrec)
+      s
+
+    coerceS(expr : E): S ==
+      s : S := postcondition formatMml(precondition expr, minPrec)
+      sayTeX$Lisp "<math xmlns=_"http://www.w3.org/1998/Math/MathML_" mathsize=_"big_" display=_"block_">"
+      displayElt(s)
+      sayTeX$Lisp "</math>"
+      s
+
+    coerceL(expr : E): S ==
+      s : S := postcondition formatMml(precondition expr, minPrec)
+      sayTeX$Lisp "<math xmlns=_"http://www.w3.org/1998/Math/MathML_" mathsize=_"big_" display=_"block_">"
+      sayTeX$Lisp s
+      sayTeX$Lisp "</math>"
+      s
+
+    display(mathml : S): Void ==
+      sayTeX$Lisp "<math xmlns=_"http://www.w3.org/1998/Math/MathML_" mathsize=_"big_" display=_"block_">"
+      sayTeX$Lisp mathml
+      sayTeX$Lisp "</math>"
+      void()$Void
+
+      
+
+    exprex(expr : E): S ==
+      -- This breaks down an expression into atoms and returns it as
+      -- a string.  It's for developmental purposes to help understand
+      -- the expressions.
+      a : E
+      expr := precondition expr
+--      sayTeX$Lisp "0: "stringify expr
+      (ATOM(expr)$Lisp@Boolean) or (stringify expr = "NOTHING") => 
+        concat ["{",stringify expr,"}"]      
+      le : L E := (expr pretend L E)
+      op := first le
+      sop : S := exprex op
+      args : L E := rest le
+      nargs : I := #args
+--      sayTeX$Lisp concat ["1: ",stringify first le," : ",string(nargs)$S]
+      s : S := concat ["{",sop]
+      if nargs > 0  then
+        for a in args repeat
+--	  sayTeX$Lisp concat ["2: ",stringify a]
+	  s1 : S := exprex a
+	  s := concat [s,s1]
+      s := concat [s,"}"]
+
+@
+\subsection{Private Function Definitions}
+
+\subsubsection{Display Functions}
+
+    displayElt(mathml:S):Void
+
+    eltName(pos:I,mathml:S):S
+
+    eltLimit(name:S,pos:I,mathml:S):I
+
+    tagEnd(name:S,pos:I,mathml:S):I
+
+<<display functions>>=
+
+    displayElt(mathML:S): Void ==
+      -- Takes a string of syntactically complete mathML
+      -- and formats it for display.
+--      sayTeX$Lisp "****displayElt1****"
+--      sayTeX$Lisp mathML
+      enT:I -- marks end of tag, e.g. "<name>"
+      enE:I -- marks end of element, e.g. "<name> ... </name>"
+      end:I -- marks end of mathML string
+      u:US
+      end := #mathML
+      length:I := 60
+--      sayTeX$Lisp "****displayElt1.1****"
+      name:S := eltName(1,mathML)
+--      sayTeX$Lisp name
+--      sayTeX$Lisp concat("****displayElt1.2****",name)
+      enE := eltLimit(name,2+#name,mathML)
+--      sayTeX$Lisp "****displayElt2****"
+      if enE < length then
+--        sayTeX$Lisp "****displayElt3****"
+        u := segment(1,enE)$US
+	sayTeX$Lisp mathML.u
+      else
+--        sayTeX$Lisp "****displayElt4****"
+        enT := tagEnd(name,1,mathML)
+	u := segment(1,enT)$US
+	sayTeX$Lisp mathML.u
+	u := segment(enT+1,enE-#name-3)$US
+	displayElt(mathML.u)
+	u := segment(enE-#name-2,enE)$US
+	sayTeX$Lisp mathML.u
+      if end > enE then
+--        sayTeX$Lisp "****displayElt5****"
+        u := segment(enE+1,end)$US
+        displayElt(mathML.u)
+
+      void()$Void
+
+    eltName(pos:I,mathML:S): S ==
+      -- Assuming pos is the position of "<" for a start tag of a mathML
+      -- element finds and returns the element's name.
+      i:I := pos+1
+      --sayTeX$Lisp "eltName:mathmML string: "mathML
+      while member?(mathML.i,lowerCase()$CharacterClass)$CharacterClass repeat
+         i := i+1
+      u:US := segment(pos+1,i-1)
+      name:S := mathML.u
+
+    eltLimit(name:S,pos:I,mathML:S): I ==
+      -- Finds the end of a mathML element like "<name ...> ... </name>"
+      -- where pos is the position of the space after name in the start tag
+      -- although it could point to the closing ">".  Returns the position
+      -- of the ">" in the end tag.
+      pI:I := pos
+      startI:I
+      endI:I
+      startS:S := concat ["<",name]
+      endS:S := concat ["</",name,">"]
+      level:I := 1
+      --sayTeX$Lisp "eltLimit: element name: "name
+      while (level > 0) repeat
+        startI := position(startS,mathML,pI)$String
+
+	endI := position(endS,mathML,pI)$String
+
+	if (startI = 0) then
+	  level := level-1
+          --sayTeX$Lisp "****eltLimit 1******"
+	  pI := tagEnd(name,endI,mathML)
+	else
+	  if (startI < endI) then
+	    level := level+1
+	    pI := tagEnd(name,startI,mathML)
+	  else
+	    level := level-1
+	    pI := tagEnd(name,endI,mathML)
+      pI
+
+
+    tagEnd(name:S,pos:I,mathML:S):I ==
+      -- Finds the closing ">" for either a start or end tag of a mathML
+      -- element, so the return value is the position of ">" in mathML.
+      pI:I := pos
+      while  (mathML.pI ^= char ">") repeat
+        pI := pI+1
+      u:US := segment(pos,pI)$US
+      --sayTeX$Lisp "tagEnd: "mathML.u
+      pI
+
+@
+\subsubsection{Formatting Functions}
+
+Still need to format \verb+\zag+ in formatSpecial!
+
+In formatPlex the case op = "INTSIGN" is now passed off to
+formatIntSign which is a change from the TexFormat domain.
+This is done here for presentation mark up to replace the
+ugly bound variable that Axiom delivers.  For content mark up
+this has to be done anyway.  
+
+The formatPlex function also allows for op = "INDEFINTEGRAL".
+However I don't know what Axiom command gives rise to this case.
+The INTSIGN case already allows for both definite and indefinite
+integrals.
+
+In the function formatSpecial various cases are handled including
+SUB and SUPERSUB.  These cases are now caught in formatMml and so
+the code in formatSpecial doesn't get executed.  The only cases
+I know of using these are partial derivatives for SUB and ordinary
+derivatives or SUPERSUB however in TexFormat the capability is there
+to handle multiscripts, i.e. an object with subscripts, superscripts,
+pre-subscripts and pre-superscripts but I am so far unaware of any
+Axiom command that produces such a multiscripted object.
+
+Another question is how to represent derivatives.  At present I have
+differential notation for partials and prime notation for ordinary 
+derivatives, 
+but it would be nice to allow for different derivative notations in 
+different circumstances, maybe some options to )set output mathml on.
+
+Ordinary derivatives are formatted in formatSuperSub and there are
+2 versions, formatSuperSub and formatSuperSub1, which at this point
+have to be switched by swapping names.
+
+<<formatting functions>>=
+
+    atomize(expr : E): L E ==
+      -- This breaks down an expression into a flat list of atomic expressions.
+      -- expr should be preconditioned.
+      le : L E := nil()
+      a : E
+      letmp : L E
+      (ATOM(expr)$Lisp@Boolean) or (stringify expr = "NOTHING") => 
+        le := append(le,list(expr))
+      letmp := expr pretend L E
+      for a in letmp repeat
+        le := append(le,atomize a)
+      le
+      	
+
+    ungroup(str: S): S ==
+      len : I := #str
+      len < 14 => str
+      lrow : S :=  "<mrow>"
+      rrow : S :=  "</mrow>"
+      -- drop leading and trailing mrows
+      u1 : US := segment(1,6)$US
+      u2 : US := segment(len-6,len)$US
+      if (str.u1 =$S lrow) and (str.u2 =$S rrow) then
+        u : US := segment(7,len-7)$US
+        str := str.u
+      str
+
+    postcondition(str: S): S ==
+--      str := ungroup str
+      len : I := #str
+      plusminus : S := "<mo>+</mo><mo>-</mo>"
+      pos : I := position(plusminus,str,1)
+      if pos > 0 then
+        ustart:US := segment(1,pos-1)$US
+	uend:US := segment(pos+20,len)$US
+        str := concat [str.ustart,"<mo>-</mo>",str.uend]
+	if pos < len-18 then
+	  str := postcondition(str)
+      str
+
+
+
+    stringify expr == (object2String$Lisp expr)@S
+
+
+
+    group str ==
+      concat ["<mrow>",str,"</mrow>"]
+
+    addBraces str ==
+      concat ["<mo>{</mo>",str,"<mo>}</mo>"]
+
+    addBrackets str ==
+      concat ["<mo>[</mo>",str,"<mo>]</mo>"]
+
+    parenthesize str ==
+      concat ["<mo>(</mo>",str,"<mo>)</mo>"]
+
+    precondition expr ==
+      outputTran$Lisp expr
+
+    formatSpecial(op : S, args : L E, prec : I) : S ==
+      arg : E
+      prescript : Boolean := false
+      op = "theMap" => "<mtext>theMap(...)</mtext>"
+      op = "AGGLST" =>
+        formatNary(",",args,prec)
+      op = "AGGSET" =>
+        formatNary(";",args,prec)
+      op = "TAG" =>
+        group concat [formatMml(first args,prec),
+                      "<mo>&#x02192;</mo>",
+                        formatMml(second args,prec)]
+			 --RightArrow
+      op = "VCONCAT" =>
+        group concat("<mtable><mtr>",
+                     concat(concat([concat("<mtd>",concat(formatMml(u, minPrec),"</mtd>"))
+                                    for u in args]::L S),
+                            "</mtr></mtable>"))
+      op = "CONCATB" =>
+        formatNary(" ",args,prec)
+      op = "CONCAT" =>
+        formatNary("",args,minPrec)
+      op = "QUOTE" =>
+        group concat("<mo>'</mo>",formatMml(first args, minPrec))
+      op = "BRACKET" =>
+        group addBrackets ungroup formatMml(first args, minPrec)
+      op = "BRACE" =>
+        group addBraces ungroup formatMml(first args, minPrec)
+      op = "PAREN" =>
+        group parenthesize ungroup formatMml(first args, minPrec)
+      op = "OVERBAR" =>
+        null args => ""
+        group concat ["<mover accent='true'><mrow>",formatMml(first args,minPrec),"</mrow><mo stretchy='true'>&#x000AF;</mo></mover>"]
+	 --OverBar
+      op = "ROOT" =>
+        null args => ""
+        tmp : S := group formatMml(first args, minPrec)
+        null rest args => concat ["<msqrt>",tmp,"</msqrt>"]
+        group concat
+	  ["<mroot><mrow>",tmp,"</mrow>",formatMml(first rest args, minPrec),"</mroot>"]
+      op = "SEGMENT" =>
+        tmp : S := concat [formatMml(first args, minPrec),"<mo>..</mo>"]
+        group
+          null rest args =>  tmp
+          concat [tmp,formatMml(first rest args, minPrec)]
+      -- SUB should now be diverted in formatMml although I'll leave
+      -- the code here for now.
+      op = "SUB" =>
+        group concat ["<msub>",formatMml(first args, minPrec),
+          formatSpecial("AGGLST",rest args,minPrec),"</msub>"]
+      -- SUPERSUB should now be diverted in formatMml although I'll leave
+      -- the code here for now.
+      op = "SUPERSUB" =>
+        base:S := formatMml(first args, minPrec)
+	args := rest args
+	if #args = 1 then
+	  "<msub><mrow>"base"</mrow><mrow>"formatMml(first args, minPrec)"</mrow></msub>"
+	else if #args = 2 then
+	-- it would be nice to substitue &#x2032; for , in the case of
+	-- an ordinary derivative, it looks a lot better.
+	  "<msubsup><mrow>"base"</mrow><mrow>"formatMml(first args,minPrec)"</mrow><mrow>"formatMml(first rest args, minPrec)"</mrow></msubsup>"
+	else if #args = 3 then
+	  "<mmultiscripts><mrow>"base"</mrow><mrow>"formatMml(first args,minPrec)"</mrow><mrow>"formatMml(first rest args,minPrec)"</mrow><mprescripts/><mrow>"formatMml(first rest rest args,minPrec)"</mrow><none/></mmultiscripts>"
+	else if #args = 4 then
+	  "<mmultiscripts><mrow>"base"</mrow><mrow>"formatMml(first args,minPrec)"</mrow><mrow>"formatMml(first rest args,minPrec)"</mrow><mprescripts/><mrow>"formatMml(first rest rest args,minPrec)"</mrow><mrow>"formatMml(first rest rest rest args,minPrec)"</mrow></mmultiscripts>"
+	else
+	  "<mtext>Problem with multiscript object</mtext>"
+      op = "SC" =>
+        -- need to handle indentation someday
+        null args => ""
+        tmp := formatNaryNoGroup("</mtd></mtr><mtr><mtd>", args, minPrec)
+        group concat ["<mtable><mtr><mtd>",tmp,"</mtd></mtr></mtable>"]
+      op = "MATRIX" => formatMatrix rest args
+      op = "ZAG" =>
+-- {{+}{3}{{ZAG}{1}{7}}{{ZAG}{1}{15}}{{ZAG}{1}{1}}{{ZAG}{1}{25}}{{ZAG}{1}{1}}{{ZAG}{1}{7}}{{ZAG}{1}{4}}}
+-- to format continued fraction traditionally need to intercept it at the
+-- formatNary of the "+"
+        concat [" \zag{",formatMml(first args, minPrec),"}{",
+          formatMml(first rest args,minPrec),"}"]
+      concat ["<mtext>not done yet for: ",op,"</mtext>"]
+
+    formatSub(expr : E, args : L E, opPrec : I) : S ==
+      -- This one produces differential notation partial derivatives.
+      -- At this time this is only to handle partial derivatives.
+      -- If the SUB case handles anything else I'm not aware of it.
+      -- This an example of the 4th partial of y(x,z) w.r.t. x,x,z,x
+      -- {{{SUB}{y}{{CONCAT}{{CONCAT}{{CONCAT}{{CONCAT}{,}{1}}{{CONCAT}{,}{1}}}{{CONCAT}{,}{2}}}{{CONCAT}{,}{1}}}}{x}{z}}
+      atomE : L E := atomize(expr)      
+      op : S := stringify first atomE
+      op ^= "SUB" => "<mtext>Mistake in formatSub: no SUB</mtext>"
+      stringify first rest rest atomE ^= "CONCAT" => "<mtext>Mistake in formatSub: no CONCAT</mtext>"
+      -- expecting form for atomE like
+      --[{SUB}{func}{CONCAT}...{CONCAT}{,}{n}{CONCAT}{,}{n}...{CONCAT}{,}{n}],
+      --counting the first CONCATs before the comma gives the number of
+      --derivatives
+      ndiffs : I := 0
+      tmpLE : L E := rest rest atomE
+      while stringify first tmpLE = "CONCAT" repeat
+        ndiffs := ndiffs+1
+	tmpLE := rest tmpLE
+      numLS : L S := nil
+      i : I := 1
+      while i < ndiffs repeat
+        numLS := append(numLS,list(stringify first rest tmpLE))
+	tmpLE := rest rest rest tmpLE
+	i := i+1
+      numLS := append(numLS,list(stringify first rest tmpLE))
+      -- numLS contains the numbers of the bound variables as strings
+      -- for the differentiations, thus for the differentiation [x,x,z,x]
+      -- for y(x,z) numLS = ["1","1","2","1"]
+      posLS : L S := nil
+      i := 0
+ --     sayTeX$Lisp "formatSub: nargs = "string(#args)
+      while i < #args repeat
+        posLS := append(posLS,list(string(i+1)))
+	i := i+1
+      -- posLS contains the positions of the bound variables in args
+      -- as a list of strings, e.g. for the above example ["1","2"]
+      tmpS: S := stringify atomE.2
+      if ndiffs = 1 then
+        s : S := "<mfrac><mo>&#x02202;</mo><mi>"tmpS"</mi><mrow>"
+      else        
+        s : S := "<mfrac><mrow><msup><mo>&#x02202;</mo><mn>"string(ndiffs)"</mn></msup><mi>"tmpS"</mi></mrow><mrow>"
+      -- need to find the order of the differentiation w.r.t. the i-th
+      -- variable
+      i := 1
+      j : I
+      k : I
+      tmpS: S
+      while i < #posLS+1 repeat
+	j := 0
+	k := 1
+	while k < #numLS + 1 repeat
+	  if numLS.k = string i then j := j + 1
+	  k := k+1
+        if j > 0 then
+	  tmpS := stringify args.i
+	  if j = 1 then
+	    s := s"<mo>&#x02202;</mo><mi>"tmpS"</mi>"
+	  else
+	    s := s"<mo>&#x02202;</mo><msup><mi>"tmpS"</mi><mn>"string(j)"</mn></msup>"
+        i := i + 1
+      s := s"</mrow></mfrac><mo>(</mo>"
+      i := 1
+      while i < #posLS+1 repeat
+        tmpS := stringify args.i
+	s := s"<mi>"tmpS"</mi>"
+	if i < #posLS then s := s"<mo>,</mo>"
+	i := i+1
+      s := s"<mo>)</mo>"
+
+    formatSub1(expr : E, args : L E, opPrec : I) : S ==
+      -- This one produces partial derivatives notated by ",n" as
+      -- subscripts.
+      -- At this time this is only to handle partial derivatives.
+      -- If the SUB case handles anything else I'm not aware of it.
+      -- This an example of the 4th partial of y(x,z) w.r.t. x,x,z,x
+      -- {{{SUB}{y}{{CONCAT}{{CONCAT}{{CONCAT}{{CONCAT}{,}{1}}
+      -- {{CONCAT}{,}{1}}}{{CONCAT}{,}{2}}}{{CONCAT}{,}{1}}}}{x}{z}},
+      -- here expr is everything in the first set of braces and 
+      -- args is {{x}{z}}
+      atomE : L E := atomize(expr)      
+      op : S := stringify first atomE
+      op ^= "SUB" => "<mtext>Mistake in formatSub: no SUB</mtext>"
+      stringify first rest rest atomE ^= "CONCAT" => "<mtext>Mistake in formatSub: no CONCAT</mtext>"
+      -- expecting form for atomE like
+      --[{SUB}{func}{CONCAT}...{CONCAT}{,}{n}{CONCAT}{,}{n}...{CONCAT}{,}{n}],
+      --counting the first CONCATs before the comma gives the number of
+      --derivatives
+      ndiffs : I := 0
+      tmpLE : L E := rest rest atomE
+      while stringify first tmpLE = "CONCAT" repeat
+        ndiffs := ndiffs+1
+	tmpLE := rest tmpLE
+      numLS : L S := nil
+      i : I := 1
+      while i < ndiffs repeat
+        numLS := append(numLS,list(stringify first rest tmpLE))
+	tmpLE := rest rest rest tmpLE
+	i := i+1
+      numLS := append(numLS,list(stringify first rest tmpLE))
+      -- numLS contains the numbers of the bound variables as strings
+      -- for the differentiations, thus for the differentiation [x,x,z,x]
+      -- for y(x,z) numLS = ["1","1","2","1"]
+      posLS : L S := nil
+      i := 0
+ --     sayTeX$Lisp "formatSub: nargs = "string(#args)
+      while i < #args repeat
+        posLS := append(posLS,list(string(i+1)))
+	i := i+1
+      -- posLS contains the positions of the bound variables in args
+      -- as a list of strings, e.g. for the above example ["1","2"]
+      funcS: S := stringify atomE.2
+      s : S := "<msub><mi>"funcS"</mi><mrow>"
+      i := 1
+      while i < #numLS+1 repeat
+        s := s"<mo>,</mo><mn>"numLS.i"</mn>"
+	i := i + 1
+      s := s"</mrow></msub><mo>(</mo>"
+      i := 1
+      while i < #posLS+1 repeat
+        tmpS := stringify args.i
+	s := s"<mi>"tmpS"</mi>"
+	if i < #posLS then s := s"<mo>,</mo>"
+	i := i+1
+      s := s"<mo>)</mo>"
+
+    formatSuperSub1(expr : E, args : L E, opPrec : I) : S ==
+      -- this produces differential notation ordinary derivatives.
+      -- first have to divine the semantics, add cases as needed
+      atomE : L E := atomize(expr)      
+      op : S := stringify first atomE
+      op ^= "SUPERSUB" => "<mtext>Mistake in formatSuperSub: no SUPERSUB</mtext>"
+      #args ^= 1 => "<mtext>Mistake in SuperSub: #args <> 1</mtext>"
+      var : E := first args
+      -- should be looking at something like {{SUPERSUB}{var}{ }{,,...,}} for
+      -- example here's the second derivative of y w.r.t. x
+      -- {{{SUPERSUB}{y}{ }{,,}}{x}}, expr is the first {} and args is the
+      -- {x}
+      funcS : S := stringify first rest atomE
+      bvarS : S := stringify first args
+      -- count the number of commas
+      commaS : S := stringify first rest rest rest atomE
+      commaTest : S := ","
+      i : I := 0
+      while position(commaTest,commaS,1) > 0 repeat
+        i := i+1
+	commaTest := commaTest","
+      s : S := "<msup><mi>"funcS"</mi><mrow>"
+      j : I := 0
+      while j < i repeat
+        s := s"<mo>&#x02032;</mo>"
+	j := j + 1
+      s := s"</mrow></msup><mo>&#x02061;</mo><mo>(</mo><mi>"bvarS"</mi><mo>)</mo>"
+
+    formatSuperSub(expr : E, args : L E, opPrec : I) : S ==
+      -- This one produces ordinary derivatives with prime notation.
+      -- first have to divine the semantics, add cases as needed
+      atomE : L E := atomize(expr)      
+      op : S := stringify first atomE
+      op ^= "SUPERSUB" => "<mtext>Mistake in formatSuperSub: no SUPERSUB</mtext>"
+      #args ^= 1 => "<mtext>Mistake in SuperSub: #args <> 1</mtext>"
+      var : E := first args
+      -- should be looking at something like {{SUPERSUB}{var}{ }{,,...,}} for
+      -- example here's the second derivative of y w.r.t. x
+      -- {{{SUPERSUB}{y}{ }{,,}}{x}}, expr is the first {} and args is the
+      -- {x}
+      funcS : S := stringify first rest atomE
+      bvarS : S := stringify first args
+      -- count the number of commas
+      commaS : S := stringify first rest rest rest atomE
+      commaTest : S := ","
+      ndiffs : I := 0
+      while position(commaTest,commaS,1) > 0 repeat
+        ndiffs := ndiffs+1
+	commaTest := commaTest","
+      s : S := "<mfrac><mrow><msup><mo>&#x02146;</mo><mn>"string(ndiffs)"</mn></msup><mi>"funcS"</mi></mrow><mrow><mo>&#x02146;</mo><msup><mi>"bvarS"</mi><mn>"string(ndiffs)"</mn></msup></mrow></mfrac><mo>&#x02061;</mo><mo>(</mo><mi>"bvarS"</mi><mo>)</mo>"
+
+    formatPlex(op : S, args : L E, prec : I) : S ==
+      hold : S
+      p : I := position(op,plexOps)
+      p < 1 => error "unknown plex op"
+      op = "INTSIGN" => formatIntSign(args,minPrec)
+      opPrec := plexPrecs.p
+      n : I := #args
+      (n ^= 2) and (n ^= 3) => error "wrong number of arguments for plex"
+      s : S :=
+        op = "SIGMA"   => "<mo>&#x02211;</mo>"
+	-- Sum
+        op = "SIGMA2"   => "<mo>&#x02211;</mo>"
+	-- Sum
+        op = "PI"      => "<mo>&#x0220F;</mo>"
+	-- Product
+        op = "PI2"     => "<mo>&#x0220F;</mo>"
+	-- Product
+--        op = "INTSIGN" => "<mo>&#x0222B;</mo>"
+	-- Integral, int
+        op = "INDEFINTEGRAL" => "<mo>&#x0222B;</mo>"
+	-- Integral, int
+        "????"
+      hold := formatMml(first args,minPrec)
+      args := rest args
+      if op ^= "INDEFINTEGRAL" then
+        if hold ^= "" then
+          s := concat ["<munderover>",s,group hold]
+	else
+	  s := concat ["<munderover>",s,group " "]
+        if not null rest args then
+          hold := formatMml(first args,minPrec)
+	  if hold ^= "" then
+            s := concat [s,group hold,"</munderover>"]
+	  else
+	    s := concat [s,group " ","</munderover>"]
+          args := rest args
+        s := concat [s,formatMml(first args,minPrec)]
+      else
+        hold := group concat [hold,formatMml(first args,minPrec)]
+        s := concat [s,hold]
+--      if opPrec < prec then s := parenthesize s
+-- getting ugly parentheses on fractions
+      group s
+
+    formatIntSign(args : L E, opPrec : I) : S ==
+      -- the original OutputForm expression looks something like this:
+      -- {{INTSIGN}{NOTHING or lower limit?}
+      -- {bvar or upper limit?}{{*}{integrand}{{CONCAT}{d}{axiom var}}}}
+      -- the args list passed here consists of the rest of this list, i.e.
+      -- starting at the NOTHING or ...
+      (stringify first args) = "NOTHING" =>
+        -- the bound variable is the second one in the argument list
+	bvar : E := first rest args
+	bvarS : S := stringify bvar
+	tmpS : S
+	i : I := 0
+	u1 : US
+	u2 : US
+	-- this next one atomizes the integrand plus differential
+	atomE : L E := atomize(first rest rest args)
+	-- pick out the bound variable used by axiom
+	varRS : S := stringify last(atomE)
+	tmpLE : L E := ((first rest rest args) pretend L E)
+        integrand : S := formatMml(first rest tmpLE,minPrec)
+	-- replace the bound variable, i.e. axiom uses someting of the form
+	-- %A for the bound variable and puts the original variable used
+	-- in the input command as a superscript on the integral sign.
+	-- I'm assuming that the axiom variable is 2 characters.
+	while (i := position(varRS,integrand,i+1)) > 0 repeat
+	  u1 := segment(1,i-1)$US
+	  u2 := segment(i+2,#integrand)$US
+	  integrand := concat [integrand.u1,bvarS,integrand.u2]
+	concat ["<mrow><mo>&#x0222B;</mo>" integrand "<mo>&#x02146;</mo><mi>" bvarS "</mi></mrow>"]
+
+      lowlim : S := stringify first args
+      highlim : S := stringify first rest args
+      bvar : E := last atomize(first rest rest args)
+      bvarS : S := stringify bvar
+      tmpLE : L E := ((first rest rest args) pretend L E)
+      integrand : S := formatMml(first rest tmpLE,minPrec)
+      concat ["<mrow><munderover><mo>&#x0222B;</mo><mi>" lowlim "</mi><mi>" highlim "</mi></munderover>" integrand "<mo>&#x02146;</mo><mi>" bvarS "</mi></mrow>"] 
+
+
+    formatMatrix(args : L E) : S ==
+      -- format for args is [[ROW ...],[ROW ...],[ROW ...]]
+      -- generate string for formatting columns (centered)
+      group addBrackets concat
+        ["<mtable><mtr><mtd>",formatNaryNoGroup("</mtd></mtr><mtr><mtd>",args,minPrec),
+          "</mtd></mtr></mtable>"]
+
+    formatFunction(op : S, args : L E, prec : I) : S ==
+      group concat ["<mo>",op,"</mo>",parenthesize formatNary(",",args,minPrec)]
+
+    formatNullary(op : S) ==
+      op = "NOTHING" => ""
+      group concat ["<mo>",op,"</mo><mo>(</mo><mo>)</mo>"]
+
+    formatUnary(op : S, arg : E, prec : I) ==
+      p : I := position(op,unaryOps)
+      p < 1 => error "unknown unary op"
+      opPrec := unaryPrecs.p
+      s : S := concat ["<mo>",op,"</mo>",formatMml(arg,opPrec)]
+      opPrec < prec => group parenthesize s
+      op = "-" => s
+      group s
+
+    formatBinary(op : S, args : L E, prec : I) : S ==
+      p : I := position(op,binaryOps)
+      p < 1 => error "unknown binary op"
+      opPrec := binaryPrecs.p
+      s1 : S := formatMml(first args, opPrec)
+      s2 : S := formatMml(first rest args, opPrec)
+      op :=
+        op = "|"     =>  s := concat ["<mrow>",s1,"</mrow><mo>",op,"</mo><mrow>",s2,"</mrow>"]
+        op = "**"    =>  s := concat ["<msup><mrow>",s1,"</mrow><mrow>",s2,"</mrow></msup>"]
+        op = "/"     =>  s := concat ["<mfrac><mrow>",s1,"</mrow><mrow>",s2,"</mrow></mfrac>"]
+        op = "OVER"  =>  s := concat ["<mfrac><mrow>",s1,"</mrow><mrow>",s2,"</mrow></mfrac>"]
+        op = "+->"   =>  s := concat ["<mrow>",s1,"</mrow><mo>",op,"</mo><mrow>",s2,"</mrow>"]
+        s := concat ["<mrow>",s1,"</mrow><mo>",op,"</mo><mrow>",s2,"</mrow>"]
+      group
+        op = "OVER" => s
+--        opPrec < prec => parenthesize s
+-- ugly parentheses?
+        s
+
+    formatNary(op : S, args : L E, prec : I) : S ==
+      group formatNaryNoGroup(op, args, prec)
+
+    formatNaryNoGroup(op : S, args : L E, prec : I) : S ==
+      null args => ""
+      p : I := position(op,naryOps)
+      p < 1 => error "unknown nary op"
+      -- need to test for "ZAG" case and divert it here, here's an
+      -- example including "op", the args list would be the rest of this
+      -- {{+}{3}{{ZAG}{1}{7}}{{ZAG}{1}{15}}{{ZAG}{1}{1}}{{ZAG}{1}{25}}
+      -- {{ZAG}{1}{1}}{{ZAG}{1}{7}}{{ZAG}{1}{4}}}
+      -- The first arg, the "3" in this case, could be a "ZAG" or something
+      -- else, but the second arg looks like it has to be "ZAG", so maybe
+      -- test for #args > 1 and args.2 is "ZAG".
+      -- This test should work so long as axiom doesn't try to evaluate
+      -- the second half of the "and" when the first half is false.
+      (#args > 1) and (position("ZAG",stringify first rest args,1) > 0) =>
+	   tmpS : S := stringify first args
+	   position("ZAG",tmpS,1) > 0 => formatZag(args)
+--	   position("ZAG",tmpS,1) > 0 => formatZag1(args)
+	   concat [formatMml(first args,minPrec) "<mo>+</mo>" formatZag(rest args)]
+      op :=
+        op = ","     => "<mo>,</mo>" --originally , \:
+        op = ";"     => "<mo>;</mo>" --originally ; \: should figure these out
+        op = "*"     => "<mo>&#x02062;</mo>"
+	-- InvisibleTimes
+        op = " "     => "<mspace width='0.5em'/>"
+        op = "ROW"   => "</mtd><mtd>"
+	op = "+"     => "<mo>+</mo>"
+	op = "-"     => "<mo>-</mo>"
+        op
+      l : L S := nil
+      opPrec := naryPrecs.p
+      for a in args repeat
+        l := concat(op,concat(formatMml(a,opPrec),l)$L(S))$L(S)
+      s : S := concat reverse rest l
+      opPrec < prec => parenthesize s
+      s
+
+    formatZag(args : L E) : S ==
+    -- {{ZAG}{1}{7}}
+      tmpZag : L E := first args pretend L E
+      #args > 1 => "<mfrac>"formatMml(first rest tmpZag,minPrec)"<mrow><mn>"formatMml(first rest rest tmpZag,minPrec)"</mn><mo>+</mo>"formatZag(rest args)"</mrow></mfrac>"
+      "<mfrac>"formatMml(first rest tmpZag,minPrec)formatMml(first rest rest tmpZag,minPrec)"</mfrac>"
+      
+    formatZag1(args : L E) : S ==
+    -- make alternative ZAG format without diminishing fonts, maybe
+    -- use a table
+    -- {{ZAG}{1}{7}}
+      tmpZag : L E := first args pretend L E
+      #args > 1 => "<mfrac>"formatMml(first rest tmpZag,minPrec)"<mrow><mn>"formatMml(first rest rest tmpZag,minPrec)"</mn><mo>+</mo>"formatZag(rest args)"</mrow></mfrac>"
+      "<mfrac>"formatMml(first rest tmpZag,minPrec)formatMml(first rest rest tmpZag,minPrec)"</mfrac>"
+
+    formatMml(expr : E,prec : I) ==
+      i,len : Integer
+      intSplitLen : Integer := 20
+      ATOM(expr)$Lisp@Boolean =>
+        str := stringify expr
+        len := #str
+	-- this bit seems to deal with integers
+        FIXP$Lisp expr =>
+          i := expr pretend Integer
+          if (i < 0) or (i > 9)
+            then
+              group
+                 nstr : String := ""
+                 -- insert some blanks into the string, if too long
+                 while ((len := #str) > intSplitLen) repeat
+                   nstr := concat [nstr," ",
+                     elt(str,segment(1,intSplitLen)$US)]
+                   str := elt(str,segment(intSplitLen+1)$US)
+                 empty? nstr => concat ["<mn>",str,"</mn>"]
+                 nstr :=
+                   empty? str => nstr
+                   concat [nstr," ",str]
+                 concat ["<mn>",elt(nstr,segment(2)$US),"</mn>"]
+            else str := concat ["<mn>",str,"</mn>"]
+        str = "%pi" => "<mi>&#x003C0;</mi>"
+	-- pi
+        str = "%e"  => "<mi>&#x02147;</mi>"
+	-- ExponentialE
+        str = "%i"  => "<mi>&#x02148;</mi>"
+	-- ImaginaryI
+	-- what sort of atom starts with %%? need an example
+        len > 1 and str.1 = char "%" and str.2 = char "%" =>
+          u : US := segment(3,len)$US
+          concat(concat("<mi>",str.u),"</mi>")
+        len > 0 and str.1 = char "%" => concat(concat("<mi>",str),"</mi>")
+        len > 1 and digit? str.1 => concat ["<mn>",str,"</mn>"] -- should handle floats
+	-- presumably this is a literal string
+        len > 0 and str.1 = char "_"" =>
+          concat(concat("<mtext>",str),"</mtext>")
+        len = 1 and str.1 = char " " => " "
+        (i := position(str,specialStrings)) > 0 =>
+          specialStringsInMML.i
+        (i := position(char " ",str)) > 0 =>
+          -- We want to preserve spacing, so use a roman font.
+	  -- What's this for?  Leave the \rm in for now so I can see
+	  -- where it arises.  Removed 2007-02-14
+          concat(concat("<mtext>",str),"</mtext>")
+	-- if we get to here does that mean it's a variable?
+        concat ["<mi>",str,"</mi>"]
+      l : L E := (expr pretend L E)
+      null l => blank
+      op : S := stringify first l
+      args : L E := rest l
+      nargs : I := #args
+
+      -- special cases
+      member?(op, specialOps) => formatSpecial(op,args,prec)
+      member?(op, plexOps)    => formatPlex(op,args,prec)
+
+      -- nullary case
+      0 = nargs => formatNullary op
+
+      -- unary case
+      (1 = nargs) and member?(op, unaryOps) =>
+        formatUnary(op, first args, prec)
+
+      -- binary case
+      (2 = nargs) and member?(op, binaryOps) =>
+        formatBinary(op, args, prec)
+
+      -- nary case
+      member?(op,naryNGOps) => formatNaryNoGroup(op,args, prec)
+      member?(op,naryOps) => formatNary(op,args, prec)
+      -- need to test here in case first l is SUPERSUB case and then
+      -- pass first l and args to formatSuperSub.
+      position("SUPERSUB",op,1) > 0 =>
+        formatSuperSub(first l,args,minPrec)
+      -- now test for SUB
+      position("SUB",op,1) > 0 =>
+        formatSub(first l,args,minPrec)
+
+      op := formatMml(first l,minPrec)
+      formatFunction(op,args,prec)
+
+@
+\section{Mathematical Markup Language Form}
+<<package MMLFORM MathMLForm>>=
+<<public declarations>>
+<<private constant declarations>>
+<<private function declarations>>
+<<public function definitions>>
+<<display functions>>
+<<formatting functions>>
+
+@
+\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.
+@
+<<*>>=
+<<license>>
+<<package MMLFORM MathMLForm>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}
diff --git a/src/input/Makefile.pamphlet b/src/input/Makefile.pamphlet
index 474b899..621d8ed 100644
--- a/src/input/Makefile.pamphlet
+++ b/src/input/Makefile.pamphlet
@@ -329,7 +329,8 @@ REGRES= algaggr.regress algbrbf.regress  algfacob.regress alist.regress  \
     lodo2.regress     lodo3.regress    lodof.regress    lodo.regress \
     lpoly.regress     lupfact.regress  lword.regress    macbug.regress \
     macros.regress    magma.regress    mapleok.regress  mappkg1.regress \
-    matbug.regress    matrix1.regress  matrix22.regress matrix.regress \
+    matbug.regress    mathml.regress   \
+    matrix1.regress  matrix22.regress matrix.regress \
     mfinfact.regress  mkfunc.regress   mpoly.regress    mset2.regress \
     mset.regress      multfact.regress multiple.regress ndftip.regress \
     negfloats.regress nepip.regress    newlodo.regress  newton.regress \
@@ -551,6 +552,7 @@ FILES= ${OUT}/algaggr.input  ${OUT}/algbrbf.input    ${OUT}/algfacob.input \
        ${OUT}/lupfact.input  ${OUT}/lword.input      ${OUT}/macbug.input \
        ${OUT}/macros.input   ${OUT}/marcbench.input  ${OUT}/magma.input \
        ${OUT}/mapleok.input  ${OUT}/mappkg1.input    ${OUT}/matbug.input \
+       ${OUT}/mathml.input \
        ${OUT}/matrix22.input ${OUT}/matrix.input     ${OUT}/matrix1.input \
        ${OUT}/mfinfact.input ${OUT}/mkfunc.input     ${OUT}/mountain.input \
        ${OUT}/mpoly.input    ${OUT}/mset.input       ${OUT}/mset2.input \
@@ -816,6 +818,7 @@ DOCFILES= \
   ${DOC}/macros.input.dvi      ${DOC}/magma.input.dvi      \
   ${DOC}/mapleok.input.dvi     ${DOC}/mappkg1.input.dvi    \
   ${DOC}/marcbench.input.dvi   ${DOC}/matbug.input.dvi     \
+  ${DOC}/mathml.input.dvi      \
   ${DOC}/matops.as.dvi         ${DOC}/matrix1.input.dvi    \
   ${DOC}/matrix22.input.dvi    ${DOC}/matrix.input.dvi     \
   ${DOC}/matrox.input.dvi      ${DOC}/mfinfact.input.dvi   \
diff --git a/src/input/mathml.input.pamphlet b/src/input/mathml.input.pamphlet
new file mode 100644
index 0000000..461f32c
--- /dev/null
+++ b/src/input/mathml.input.pamphlet
@@ -0,0 +1,349 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/input mathml.input}
+\author{Arthur Ralfs}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+<<*>>=
+)spool mathml.output
+)set message test on
+)set message auto off
+)clear all
+ 
+--S 1 of 21
+(x+y)**2
+--R 
+--R
+--R         2           2
+--R   (1)  y  + 2x y + x
+--R                                                     Type: Polynomial Integer
+--E 1
+
+--S 2 of 21
+coerce(%)$MMLFORM
+--R 
+--R
+--R   (2)
+--R  "<mrow><mrow><msup><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msup></mro
+--R  w><mo>+</mo><mrow><mn>2</mn><mo>&#x02062;</mo><mi>x</mi><mo>&#x02062;</mo><mi
+--R  >y</mi></mrow><mo>+</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>2</mn></
+--R  mrow></msup></mrow></mrow>"
+--R                                                                 Type: String
+--E 2
+
+--S 3 of 21
+(x+y)**2
+--R 
+--R
+--R         2           2
+--R   (3)  y  + 2x y + x
+--R                                                     Type: Polynomial Integer
+--E 3
+
+--S 4 of 21
+display(coerce(%)$MMLFORM)$MMLFORM
+--R 
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mrow><msup><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msup></mrow><mo>+</mo><mrow><mn>2</mn><mo>&#x02062;</mo><mi>x</mi><mo>&#x02062;</mo><mi>y</mi></mrow><mo>+</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msup></mrow></mrow>
+--R</math>
+--R                                                                   Type: Void
+--E 4
+
+)set output mathml on
+
+--S 5 of 21
+(x+y)**2
+--R
+--R         2           2
+--R   (5)  y  + 2x y + x
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mrow><msup><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msup></mrow><mo>+</mo><mrow><mn>2</mn><mo>&#x02062;</mo><mi>x</mi><mo>&#x02062;</mo><mi>y</mi></mrow><mo>+</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msup></mrow></mrow>
+--R</math>
+--R
+--R                                                     Type: Polynomial Integer
+--E 5
+
+--S 6 of 21
+integrate(x**x,x)
+--R
+--R           x
+--R         ++    %I
+--R   (6)   |   %I  d%I
+--R        ++
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mo>&#x0222B;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mi>x</mi></mrow></msup></mrow><mo>&#x02146;</mo><mi>x</mi></mrow>
+--R</math>
+--R
+--R                                          Type: Union(Expression Integer,...)
+--E 6
+
+--S 7 of 21
+integral(x**x,x)
+--R
+--R           x
+--R         ++    %I
+--R   (7)   |   %I  d%I
+--R        ++
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mo>&#x0222B;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mi>x</mi></mrow></msup></mrow><mo>&#x02146;</mo><mi>x</mi></mrow>
+--R</math>
+--R
+--R                                                     Type: Expression Integer
+--E 7
+
+--S 8 of 21
+(5+sqrt 63 + sqrt 847)**(1/3)
+--R
+--R         +----------+
+--R        3|   +-+
+--R   (8)  \|14\|7  + 5
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mroot><mrow><mrow><mrow><mrow><mrow><mn>14</mn></mrow><mo>&#x02062;</mo><msqrt><mrow><mn>7</mn></mrow></msqrt></mrow><mo>+</mo><mn>5</mn></mrow></mrow></mrow><mn>3</mn></mroot></mrow>
+--R</math>
+--R
+--R                                                        Type: AlgebraicNumber
+--E 8
+
+--S 9 of 21
+set [1,2,3]
+--R
+--R   (9)  {1,2,3}
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mo>{</mo><mn>1</mn><mo>,</mo><mn>2</mn><mo>,</mo><mn>3</mn><mo>}</mo></mrow>
+--R</math>
+--R
+--R                                                    Type: Set PositiveInteger
+--E 9
+
+--S 10 of 21
+multiset [x rem 5 for x in primes(2,1000)]
+--R
+--R   (10)  {0,40: 1,47: 2,42: 3,38: 4}
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mo>{</mo><mn>0</mn><mo>,</mo><mrow><mrow><mn>40</mn></mrow><mtext>: </mtext><mn>1</mn></mrow><mo>,</mo><mrow><mrow><mn>47</mn></mrow><mtext>: </mtext><mn>2</mn></mrow><mo>,</mo><mrow><mrow><mn>42</mn></mrow><mtext>: </mtext><mn>3</mn></mrow><mo>,</mo><mrow><mrow><mn>38</mn></mrow><mtext>: </mtext><mn>4</mn></mrow><mo>}</mo></mrow>
+--R</math>
+--R
+--R                                                       Type: Multiset Integer
+--E 10
+
+--S 11 of 21
+series(sin(a*x),x=0)
+--R
+--R                3        5        7          9            11
+--R               a   3    a   5    a    7     a     9      a      11      12
+--R   (11)  a x - -- x  + --- x  - ---- x  + ------ x  - -------- x   + O(x  )
+--R                6      120      5040      362880      39916800
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mrow><mi>a</mi><mo>&#x02062;</mo><mi>x</mi></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><msup><mrow><mi>a</mi></mrow><mrow><mn>3</mn></mrow></msup></mrow></mrow><mrow><mn>6</mn></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>3</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><msup><mrow><mi>a</mi></mrow><mrow><mn>5</mn></mrow></msup></mrow></mrow><mrow><mrow><mn>120</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>5</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><msup><mrow><mi>a</mi></mrow><mrow><mn>7</mn></mrow></msup></mrow></mrow><mrow><mrow><mn>5040</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>7</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><msup><mrow><mi>a</mi></mrow><mrow><mn>9</mn></mrow></msup></mrow></mrow><mrow><mrow><mn>362880</mn></mrow></!
mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>9</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><msup><mrow><mi>a</mi></mrow><mrow><mrow><mn>11</mn></mrow></mrow></msup></mrow></mrow><mrow><mrow><mn>39916800</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mrow><mn>11</mn></mrow></mrow></msup></mrow></mrow><mo>+</mo><mrow><mo><mi>O</mi></mo><mo>(</mo><mrow><mrow><msup><mrow><mi>x</mi></mrow><mrow><mrow><mn>12</mn></mrow></mrow></msup></mrow></mrow><mo>)</mo></mrow></mrow>
+--R</math>
+--R
+--R                        Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
+--E 11
+
+--S 12 of 21
+matrix [[xi+yj for i in 1..10] for j in 1..10]
+--R
+--R   (12)
+--R   [
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ,
+--R
+--R     [yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi, yj + xi,
+--R      yj + xi, yj + xi]
+--R     ]
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mo>[</mo><mtable><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow!
></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mr!
ow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><m!
i>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+<!
/mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mt!
d></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mro!
w></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj<!
/mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr><mtr><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd><mtd><mrow><mi>yj</mi><mo>+</mo><mi>xi</mi></mrow></mtd></mtr></mtable><mo>]</mo></mrow>
+--R</math>
+--R
+--R                                              Type: Matrix Polynomial Integer
+--E 12
+
+--S 13 of 21
+y:=operator 'y
+--R
+--R   (13)  y
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mi>y</mi>
+--R</math>
+--R
+--R                                                          Type: BasicOperator
+--E 13
+
+--S 14 of 21
+D(y(x,z),[x,x,z,x])
+--R
+--R   (14)  y        (x,z)
+--R          ,1,1,2,1
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mfrac><mrow><msup><mo>&#x02202;</mo><mn>4</mn></msup><mi>y</mi></mrow><mrow><mo>&#x02202;</mo><msup><mi>x</mi><mn>3</mn></msup><mo>&#x02202;</mo><mi>z</mi></mrow></mfrac><mo>(</mo><mi>x</mi><mo>,</mo><mi>z</mi><mo>)</mo>
+--R</math>
+--R
+--R                                                     Type: Expression Integer
+--E 14
+)clear all
+
+--S 15 of 21
+y:=operator 'y
+--R 
+--R
+--R   (1)  y
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mi>y</mi>
+--R</math>
+--R
+--R                                                          Type: BasicOperator
+--E 15
+
+--S 16 of 21
+D(y x,x,2)
+--R
+--R         ,,
+--R   (2)  y  (x)
+--R
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mfrac><mrow><msup><mo>&#x02146;</mo><mn>2</mn></msup><mi>y</mi></mrow><mrow><mo>&#x02146;</mo><msup><mi>x</mi><mn>2</mn></msup></mrow></mfrac><mo>&#x02061;</mo><mo>(</mo><mi>x</mi><mo>)</mo>
+--R</math>
+--R
+--R                                                     Type: Expression Integer
+--E 16
+
+--S 17 of 21
+x:=series 'x
+--R 
+--R
+--R   (3)  x
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mi>x</mi>
+--R</math>
+--R
+--R                        Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
+--E 17
+
+--S 18 of 21
+sin(1+x)
+--R
+--R   (4)
+--R                        sin(1)  2   cos(1)  3   sin(1)  4   cos(1)  5
+--R     sin(1) + cos(1)x - ------ x  - ------ x  + ------ x  + ------ x
+--R                           2           6          24          120
+--R   + 
+--R       sin(1)  6   cos(1)  7   sin(1)  8   cos(1)  9    sin(1)  10      11
+--R     - ------ x  - ------ x  + ------ x  + ------ x  - ------- x   + O(x  )
+--R         720        5040        40320      362880      3628800
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mrow><mo><mo>sin</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow><mo>+</mo><mrow><mrow><mo><mo>cos</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow><mo>&#x02062;</mo><mi>x</mi></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>sin</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mn>2</mn></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>cos</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mn>6</mn></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>3</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>sin</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mrow><mn>24</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>4</mn></mrow></msup></mrow></mro!
w><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>cos</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mrow><mn>120</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>5</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>sin</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mrow><mn>720</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>6</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>cos</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mrow><mn>5040</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>7</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>sin</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mrow><mn>40320</mn></mrow></mrow></mfrac></mrow><mo>&!
#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>8</!
mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>cos</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mrow><mn>362880</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mn>9</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mo><mo>sin</mo></mo><mo>(</mo><mrow><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mrow><mrow><mn>3628800</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mi>x</mi></mrow><mrow><mrow><mn>10</mn></mrow></mrow></msup></mrow></mrow><mo>+</mo><mrow><mo><mi>O</mi></mo><mo>(</mo><mrow><mrow><msup><mrow><mi>x</mi></mrow><mrow><mrow><mn>11</mn></mrow></mrow></msup></mrow></mrow><mo>)</mo></mrow></mrow>
+--R</math>
+--R
+--R                        Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
+--E 18
+
+)clear all
+
+--S 19 of 21
+series(1/log(y),y=1)
+--R
+--R   (1)
+--R            - 1   1    1            1        2    19        3    3         4
+--R     (y - 1)    + - - -- (y - 1) + -- (y - 1)  - --- (y - 1)  + --- (y - 1)
+--R                  2   12           24            720            160
+--R   + 
+--R        863         5    275         6    33953         7     8183         8
+--R     - ----- (y - 1)  + ----- (y - 1)  - ------- (y - 1)  + ------- (y - 1)
+--R       60480            24192            3628800            1036800
+--R   + 
+--R        3250433         9            10
+--R     - --------- (y - 1)  + O((y - 1)  )
+--R       479001600
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mrow><mo>(</mo><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow></msup></mrow><mo>+</mo><mrow><mfrac><mrow><mn>1</mn></mrow><mrow><mn>2</mn></mrow></mfrac></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mn>1</mn></mrow><mrow><mrow><mn>12</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mn>1</mn></mrow><mrow><mrow><mn>24</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mn>2</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mn>19</mn></mrow></mrow><mrow><mrow><mn>720</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mn>3</mn></mrow></msup></mrow></mrow><mo>+</mo><m!
row><mrow><mfrac><mrow><mn>3</mn></mrow><mrow><mrow><mn>160</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mn>4</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mn>863</mn></mrow></mrow><mrow><mrow><mn>60480</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mn>5</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><mn>275</mn></mrow></mrow><mrow><mrow><mn>24192</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mn>6</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mn>33953</mn></mrow></mrow><mrow><mrow><mn>3628800</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>!
1</mn><mo>)</mo></mrow></mrow><mrow><mn>7</mn></mrow></msup><!
/mrow></mrow><mo>+</mo><mrow><mrow><mfrac><mrow><mrow><mn>8183</mn></mrow></mrow><mrow><mrow><mn>1036800</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mn>8</mn></mrow></msup></mrow></mrow><mo>-</mo><mrow><mrow><mfrac><mrow><mrow><mn>3250433</mn></mrow></mrow><mrow><mrow><mn>479001600</mn></mrow></mrow></mfrac></mrow><mo>&#x02062;</mo><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mn>9</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mo><mi>O</mi></mo><mo>(</mo><mrow><mrow><msup><mrow><mrow><mo>(</mo><mi>y</mi><mo>-</mo><mn>1</mn><mo>)</mo></mrow></mrow><mrow><mrow><mn>10</mn></mrow></mrow></msup></mrow></mrow><mo>)</mo></mrow></mrow>
+--R</math>
+--R
+--R                        Type: UnivariatePuiseuxSeries(Expression Integer,y,1)
+--E 19
+
+)clear all
+
+--S 20 of 21
+y:UTS(FLOAT,'z,0):=exp(z)
+--R
+--R   (1)
+--R                    2                            3
+--R     1.0 + z + 0.5 z  + 0.1666666666 6666666667 z
+--R   + 
+--R                                4                               5
+--R     0.0416666666 6666666666 7 z  + 0.0083333333 3333333333 34 z
+--R   + 
+--R                                 6                               7
+--R     0.0013888888 8888888888 89 z  + 0.0001984126 9841269841 27 z
+--R   + 
+--R                                   8                                  9
+--R     0.0000248015 8730158730 1587 z  + 0.0000027557 3192239858 90653 z
+--R   + 
+--R                                   10      11
+--R     0.2755731922 3985890653 E -6 z   + O(z  )
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mn>1.0</mn><mo>+</mo><mi>z</mi><mo>+</mo><mrow><mn>0.5</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mn>2</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.1666666666 6666666667</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mn>3</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.0416666666 6666666666 7</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mn>4</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.0083333333 3333333333 34</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mn>5</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.0013888888 8888888888 89</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mn>6</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.0001984126 9841269841 27</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mn>7</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.0000248015 8730158730 1587</mn><mo>&#x02062;</mo><mrow><msup><mr!
ow><mi>z</mi></mrow><mrow><mn>8</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.0000027557 3192239858 90653</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mn>9</mn></mrow></msup></mrow></mrow><mo>+</mo><mrow><mn>0.2755731922 3985890653 E -6</mn><mo>&#x02062;</mo><mrow><msup><mrow><mi>z</mi></mrow><mrow><mrow><mn>10</mn></mrow></mrow></msup></mrow></mrow><mo>+</mo><mrow><mo><mi>O</mi></mo><mo>(</mo><mrow><mrow><msup><mrow><mi>z</mi></mrow><mrow><mrow><mn>11</mn></mrow></mrow></msup></mrow></mrow><mo>)</mo></mrow></mrow>
+--R</math>
+--R
+--R                                    Type: UnivariateTaylorSeries(Float,z,0.0)
+--E 20
+
+--S 21 of 21
+c:=continuedFraction(314159/100000)
+--R
+--R              1 |     1  |     1 |     1  |     1 |     1 |     1 |
+--R   (2)  3 + +---+ + +----+ + +---+ + +----+ + +---+ + +---+ + +---+
+--R            | 7     | 15     | 1     | 25     | 1     | 7     | 4
+--R<math xmlns="http://www.w3.org/1998/Math/MathML" mathsize="big" display="block">
+--R<mrow><mn>3</mn><mo>+</mo><mfrac><mn>1</mn><mrow><mn><mn>7</mn></mn><mo>+</mo><mfrac><mn>1</mn><mrow><mn><mrow><mn>15</mn></mrow></mn><mo>+</mo><mfrac><mn>1</mn><mrow><mn><mn>1</mn></mn><mo>+</mo><mfrac><mn>1</mn><mrow><mn><mrow><mn>25</mn></mrow></mn><mo>+</mo><mfrac><mn>1</mn><mrow><mn><mn>1</mn></mn><mo>+</mo><mfrac><mn>1</mn><mrow><mn><mn>7</mn></mn><mo>+</mo><mfrac><mn>1</mn><mn>4</mn></mfrac></mrow></mfrac></mrow></mfrac></mrow></mfrac></mrow></mfrac></mrow></mfrac></mrow></mfrac></mrow>
+--R</math>
+--R
+--R                                              Type: ContinuedFraction Integer
+--E 21
+)spool
+)lisp (bye)
+ 
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}
diff --git a/src/interp/i-output.boot.pamphlet b/src/interp/i-output.boot.pamphlet
index 10cd956..a1a84ab 100644
--- a/src/interp/i-output.boot.pamphlet
+++ b/src/interp/i-output.boot.pamphlet
@@ -1380,12 +1380,24 @@ texFormat1 expr ==
   FORCE_-OUTPUT $texOutputStream
   NIL
 
+mathmlFormat expr ==
+  mml := '(MathMLFormat)
+  mmlrep := '(String)
+  formatFn := getFunctionFromDomain("coerce",mml,[$OutputForm])
+  displayFn := getFunctionFromDomain("display",mml,[mmlrep])
+  SPADCALL(SPADCALL(expr,formatFn),displayFn)
+  TERPRI $mathmlOutputStream
+  FORCE_-OUTPUT $mathmlOutputStream
+  NIL
+
+
 output(expr,domain) ==
   if isWrapped expr then expr := unwrap expr
   isMapExpr expr =>
     if $formulaFormat then formulaFormat expr
     if $texFormat     then texFormat expr
     if $algebraFormat then mathprintWithNumber expr
+    if $mathmlFormat  then mathmlFormat expr
   categoryForm? domain or domain in '((Mode) (Domain) (SubDomain (Domain))) =>
     if $algebraFormat then
       mathprintWithNumber outputDomainConstructor expr
@@ -1401,6 +1413,7 @@ output(expr,domain) ==
     if $algebraFormat then
       mathprintWithNumber x
     if $texFormat     then texFormat x
+    if $mathmlFormat  then mathmlFormat x
   (FUNCTIONP(opOf domain)) and
     (printfun := compiledLookup("<<",'(TextWriter TextWriter $), evalDomain domain))
        and (textwrit := compiledLookup("print", '($), TextWriter())) =>
diff --git a/src/interp/setq.lisp.pamphlet b/src/interp/setq.lisp.pamphlet
index 6f23778..25155d8 100644
--- a/src/interp/setq.lisp.pamphlet
+++ b/src/interp/setq.lisp.pamphlet
@@ -777,9 +777,10 @@
 "Michel Petitot         Didier Pinchon         Ayal Pinkus"
 "Jose Alfredo Portes"
 "Claude Quitte"
-"Norman Ramsey          Michael Richardson     Renaud Rioboo"
-"Jean Rivlin            Nicolas Robidoux       Simon Robinson"
-"Raymond Rogers         Michael Rothstein      Martin Rubey"
+"Arthur C. Ralfs        Norman Ramsey          Michael Richardson"
+"Renaud Rioboo          Jean Rivlin            Nicolas Robidoux"
+"Simon Robinson         Raymond Rogers         Michael Rothstein"
+"Martin Rubey"
 "Philip Santas          Alfred Scheerhorn      William Schelter"
 "Gerhard Schneider      Martin Schoenert       Marshall Schor"
 "Frithjof Schulze       Fritz Schwarz          Nick Simicich"
diff --git a/src/interp/setvars.boot.pamphlet b/src/interp/setvars.boot.pamphlet
index 864ced0..b052e85 100644
--- a/src/interp/setvars.boot.pamphlet
+++ b/src/interp/setvars.boot.pamphlet
@@ -1382,6 +1382,125 @@ describeSetOutputFortran() ==
   '"The current setting is: ",'%b,setOutputFortran "%display%",'%d)
 
 @
+\section{output mathml}
+See the section mathml in setvart.boot.pamphlet\cite{1}
+\begin{verbatim}
+----------------------- The mathml Option ------------------------
+
+ Description: create output in MathML style
+
+ )set output mathml is used to tell AXIOM to turn MathML-style output
+printing on and off, and where to place the output.  By default,
+the destination for the output is the screen but printing is 
+turned off.
+
+Syntax:   )set output mathml <arg>
+    where arg can be one of
+  on          turn MathML printing on
+  off         turn MathML printing off (default state)
+  console     send MathML output to screen (default state)
+  fp<.fe>     send MathML output to file with file prefix fp
+              and file extension .fe. If not given, 
+              .fe defaults to .stex.
+
+If you wish to send the output to a file, you must issue 
+this command twice: once with on and once with the file name. 
+For example, to send MathML output to the file polymer.stex, 
+issue the two commands
+
+  )set output mathml on
+  )set output mathml polymer
+
+The output is placed in the directory from which you invoked 
+AXIOM or the one you set with the )cd system command.
+The current setting is:  Off:CONSOLE 
+\end{verbatim}
+<<outputmathmlCode>>=
+<<setOutputMathml>>
+<<describeSetOutputMathml>>
+@
+\subsection{setOutputMathml}
+<<setOutputMathml>>=
+setOutputMathml arg ==
+  arg = "%initialize%" =>
+    $mathmlOutputStream :=
+      DEFIOSTREAM('((MODE . OUTPUT) (DEVICE . CONSOLE)),255,0)
+    $mathmlOutputFile := '"CONSOLE"
+    $mathmlFormat := NIL
+
+  arg = "%display%" =>
+    if $mathmlFormat then label := '"On:" else label := '"Off:"
+    STRCONC(label,$mathmlOutputFile)
+
+  (null arg) or (arg = "%describe%") or (first arg = '_?) =>
+    describeSetOutputMathml()
+
+  -- try to figure out what the argument is
+
+  if arg is [fn] and
+    fn in '(Y N YE YES NO O ON OF OFF CONSOLE y n ye yes no o on of off console)
+      then 'ok
+      else arg := [fn,'smml]
+
+  arg is [fn] =>
+    UPCASE(fn) in '(Y N YE O OF) =>
+      sayKeyedMsg("S2IV0002",'(MathML mathml))
+    UPCASE(fn) in '(NO OFF)  => $mathmlFormat := NIL
+    UPCASE(fn) in '(YES ON) => $mathmlFormat := true
+    UPCASE(fn) = 'CONSOLE =>
+      SHUT $mathmlOutputStream
+      $mathmlOutputStream :=
+        DEFIOSTREAM('((MODE . OUTPUT) (DEVICE . CONSOLE)),255,0)
+      $mathmlOutputFile := '"CONSOLE"
+
+  (arg is [fn,ft]) or (arg is [fn,ft,fm]) => -- aha, a file
+    if (ptype := pathnameType fn) then
+      fn := STRCONC(pathnameDirectory fn,pathnameName fn)
+      ft := ptype
+    if null fm then fm := 'A
+    filename := $FILEP(fn,ft,fm)
+    null filename =>
+      sayKeyedMsg("S2IV0003",[fn,ft,fm])
+    (testStream := MAKE_-OUTSTREAM(filename,255,0)) =>
+      SHUT $mathmlOutputStream
+      $mathmlOutputStream := testStream
+      $mathmlOutputFile := object2String filename
+      sayKeyedMsg("S2IV0004",['"MathML",$mathmlOutputFile])
+    sayKeyedMsg("S2IV0003",[fn,ft,fm])
+
+  sayKeyedMsg("S2IV0005",NIL)
+  describeSetOutputMathml()
+
+@
+\subsection{describeSetOutputMathml}
+<<describeSetOutputMathml>>=
+describeSetOutputMathml() ==
+  sayBrightly LIST ('%b,'")set output mathml",'%d,_
+   '"is used to tell AXIOM to turn MathML-style output",'%l,_
+   '"printing on and off, and where to place the output.  By default, the",'%l,_
+   '"destination for the output is the screen but printing is turned off.",'%l,_
+   '%l,_
+   '"Syntax:   )set output mathml <arg>",'%l,_
+  '"    where arg can be one of",'%l,_
+  '"  on          turn MathML printing on",'%l,_
+  '"  off         turn MathML printing off (default state)",'%l,_
+  '"  console     send MathML output to screen (default state)",'%l,_
+  '"  fp<.fe>     send MathML output to file with file prefix fp and file",'%l,_
+  '"              extension .fe. If not given, .fe defaults to .stex.",'%l,
+  '%l,_
+  '"If you wish to send the output to a file, you must issue this command",'%l,_
+  '"twice: once with",'%b,'"on",'%d,'"and once with the file name. For example, to send",'%l,_
+  '"MathML output to the file",'%b,'"polymer.smml,",'%d,'"issue the two commands",'%l,_
+  '%l,_
+  '"  )set output mathml on",'%l,_
+  '"  )set output mathml polymer",'%l,_
+  '%l,_
+  '"The output is placed in the directory from which you invoked AXIOM or",'%l,_
+  '"the one you set with the )cd system command.",'%l,_
+  '"The current setting is: ",'%b,setOutputMathml "%display%",'%d)
+
+
+@
 \section{output openmath}
 See the subsection output openmath in setvart.boot.pamphlet\cite{1}
 \begin{verbatim}
@@ -1821,6 +1940,7 @@ describeSetStreamsCalculate() == sayKeyedMsg("S2IV0001",[$streamCount])
 <<outputalgebraCode>>
 <<outputcharactersCode>>
 <<outputfortranCode>>
+<<outputmathmlCode>>
 <<outputopenmathCode>>
 <<outputscriptCode>>
 <<outputtexCode>>
diff --git a/src/interp/setvart.boot.pamphlet b/src/interp/setvart.boot.pamphlet
index 92e8825..bfa2f14 100644
--- a/src/interp/setvart.boot.pamphlet
+++ b/src/interp/setvart.boot.pamphlet
@@ -1673,6 +1673,7 @@ length      line length of output displays           77
 scripts     show subscripts,... linearly             off 
 showeditor  view output of )show in editor           off 
 tex         create output in TeX style               Off:CONSOLE 
+mathml	    create output in MathML style	     Off:CONSOLE 
 \end{verbatim}
 Since the output option has a bunch of sub-options each suboption 
 is defined within the output structure.
@@ -1694,6 +1695,7 @@ is defined within the output structure.
 <<outputscripts>>
 <<outputshoweditor>>
 <<outputtex>>
+<<outputmathml>>
  ))
 @
 \subsection{abbreviate}
@@ -1901,6 +1903,58 @@ The current setting is:  Off:CONSOLE
       (10 245)
       77)
 @
+\subsection{mathml}
+\begin{verbatim}
+----------------------- The mathml Option ------------------------
+
+ Description: create output in MathML style
+
+ )set output mathml is used to tell AXIOM to turn MathML-style output
+printing on and off, and where to place the output.  By default,
+the destination for the output is the screen but printing is 
+turned off.
+
+Syntax:   )set output mathml <arg>
+    where arg can be one of
+  on          turn MathML printing on
+  off         turn MathML printing off (default state)
+  console     send MathML output to screen (default state)
+  fp<.fe>     send MathML output to file with file prefix fp
+              and file extension .fe. If not given, 
+              .fe defaults to .smml.
+
+If you wish to send the output to a file, you must issue 
+this command twice: once with on and once with the file name. 
+For example, to send MathML output to the file polymer.smml, 
+issue the two commands
+
+  )set output mathml on
+  )set output mathml polymer
+
+The output is placed in the directory from which you invoked 
+AXIOM or the one you set with the )cd system command.
+The current setting is:  Off:CONSOLE 
+\end{verbatim}
+<<outputmathml>>=
+     (mathml
+      "create output in MathML style"
+      interpreter
+      FUNCTION
+      setOutputMathml
+      (("create output in MathML format"
+        LITERALS
+        $mathmlFormat
+        (off on)
+        off)
+       (break $mathmlFormat)
+       ("where MathML output goes (enter {\em console} or a pathname)"
+        FILENAME
+        $mathmlOutputFile
+        chkOutputFileName
+        "console"))
+      NIL)
+
+@
 \subsection{openmath}
 \begin{verbatim}
 ----------------------- The openmath Option ------------------------

\start
Date: Mon, 27 Aug 2007 02:47:45 -0500
From: Tim Daly
To: list
Subject: 20070824.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 87548f8..eaa591a 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,68 @@
+20070824 tpd src/doc/spadhelp          add DecimalExpansion
+20070824 tpd src/algebra/Makefile      add DecimalExpansion.help 
+20070824 tpd src/algebra/radix.spad    add DecimalExpansion.help 
+20070824 tpd src/algebra/radix.spad    add DecimalExpansion.input
+20070824 tpd src/doc/spadhelp          add DeRhamComplex
+20070824 tpd src/algebra/Makefile      add DeRhamComplex.help 
+20070824 tpd src/algebra/derham.spad   add DeRhamComplex.help 
+20070824 tpd src/algebra/derham.spad   add DeRhamComplex.input
+20070824 tpd src/doc/spadhelp          add CycleIndicators
+20070824 tpd src/algebra/Makefile      add CycleIndicators.help 
+20070824 tpd src/algebra/cycles.spad   add CycleIndicators.help 
+20070824 tpd src/algebra/cycles.spad   add CycleIndicators.input
+20070824 tpd src/input/Makefile implement new algebra regression testing
+20070823 tpd src/doc/spadhelp          add ContinuedFraction
+20070823 tpd src/algebra/Makefile      add ContinuedFraction.help 
+20070823 tpd src/algebra/contfrac.spad add ContinuedFraction.help 
+20070823 tpd src/algebra/contfrac.spad add ContinuedFraction.input
+20070823 tpd src/doc/spadhelp          add Complex
+20070823 tpd src/algebra/Makefile      add Complex.help 
+20070823 tpd src/algebra/gaussian.spad add Complex.help 
+20070823 tpd src/algebra/gaussian.spad add Complex.input
+20070823 tpd src/doc/spadhelp          add CliffordAlgebra
+20070823 tpd src/algebra/Makefile      add CliffordAlgebra.help 
+20070823 tpd src/algebra/clifford.spad add CliffordAlgebra.help 
+20070823 tpd src/algebra/clifford.spad add CliffordAlgebra.input
+20070823 tpd src/doc/spadhelp          add CharacterClass
+20070823 tpd src/algebra/Makefile      add CharacterClass.help 
+20070823 tpd src/algebra/string.spad   add CharacterClass.help 
+20070823 tpd src/algebra/string.spad   add CharacterClass.input
+20070823 tpd src/doc/spadhelp          add Character
+20070823 tpd src/algebra/Makefile      add Character.help 
+20070823 tpd src/algebra/string.spad   add Character.help 
+20070823 tpd src/algebra/string.spad   add Character.input
+20070823 tpd src/doc/spadhelp          add CartesianTensor
+20070823 tpd src/algebra/Makefile      add CartesianTensor.help 
+20070823 tpd src/algebra/carten.spad   add CartesianTensor.help 
+20070823 tpd src/algebra/carten.spad   add CartesianTensor.input
+20070823 tpd src/doc/spadhelp          add CardinalNumber
+20070823 tpd src/algebra/Makefile      add CardinalNumber.help 
+20070823 tpd src/algebra/card.spad     add CardinalNumber.help 
+20070823 tpd src/algebra/card.spad     add CardinalNumber.input
+20070823 tpd src/doc/spadhelp          add BinarySearchTree
+20070823 tpd src/algebra/Makefile      add BinarySearchTree.help 
+20070823 tpd src/algebra/tree.spad     add BinarySearchTree.help 
+20070823 tpd src/algebra/tree.spad     add BinarySearchTree.input
+20070823 tpd src/doc/spadhelp          add BinaryExpansion
+20070823 tpd src/algebra/Makefile      add BinaryExpansion.help 
+20070823 tpd src/algebra/radix.spad    add BinaryExpansion.help 
+20070823 tpd src/algebra/radix.spad    add BinaryExpansion.input
+20070823 tpd src/doc/spadhelp          add BasicOperator
+20070823 tpd src/algebra/Makefile      add BasicOperator.help 
+20070823 tpd src/algebra/op.spad       add BasicOperator.help
+20070823 tpd src/algebra/op.spad       add BasicOperator.input
+20070823 tpd src/doc/spadhelp          add BalancedBinaryTree
+20070823 tpd src/algebra/Makefile      add BalancedBinaryTree.help
+20070823 tpd src/algebra/tree.spad     add BalancedBinaryTree.help
+20070823 tpd src/algebra/tree.spad     add BalancedBinaryTree.input
+20070823 tpd src/doc/spadhelp          add AssociationList
+20070823 tpd src/algebra/Makefile      add AssociationList.help
+20070823 tpd src/algebra/list.spad     add AssociationList.help
+20070823 tpd src/algebra/list.spad     add AssociationList.input
+20070823 tpd src/algebra/Makefile create spadhelp
+20070823 tpd src/Makefile mkdir int/input
+20070823 tpd src/Makefile mkdir mnt/sys/doc/spadhelp
+20070823 tpd src/doc/book.pamphlet fix typos
 20070823 tpd src/doc/spadhelp add additional spadhelp files
 20070823 tpd src/doc/Makefile add additional spadhelp files
 20070822 tpd src/doc/spadhelp add language help
diff --git a/src/Makefile.pamphlet b/src/Makefile.pamphlet
index 13bf3ff..5df04f4 100644
--- a/src/Makefile.pamphlet
+++ b/src/Makefile.pamphlet
@@ -307,6 +307,7 @@ Once {\bf bootsys} exists we need to build {\bf depsys}
 and {\bf interpsys}. Since these two images share a lot of
 files they are built in the interp subdirectory using the
 same Makefile.
+
 <<interpdir>>=
 interpdir: ${SRC}/interp/Makefile
 	@echo 25 making ${SRC}/interp
@@ -372,6 +373,13 @@ stanzas that describe the steps to extract the algebra from the
 [[src/algebra/*.pamphlet]] files into the [[int/algebra/*.spad]] files.
 Further details are provided in Makefile for src/algebra.
 
+The doc/spadhelp directory contains flat files of help text
+for the help system command. Algebra pamphlet contain examples
+that can be shown from these commands.
+
+We need to make the int/input file here because the algebra Makefile
+will extract input files for regression testing from the algebra pamphlets.
+
 <<algebradir>>=
 algebradir: ${SRC}/algebra/Makefile
 	@echo 29 making ${SRC}/algebra
@@ -380,7 +388,9 @@ algebradir: ${SRC}/algebra/Makefile
 	@mkdir -p ${OBJ}/${SYS}/algebra
 	@mkdir -p ${MNT}/${SYS}/algebra
 	@mkdir -p ${MNT}/${SYS}/doc/src/algebra
+	@mkdir -p ${MNT}/${SYS}/doc/spadhelp
 	@mkdir -p ${MNT}/${SYS}/src/algebra
+	@mkdir -p ${INT}/input
 	@(cd algebra ; ${ENV} ${MAKE} )
 
 ${SRC}/algebra/Makefile: ${SRC}/algebra/Makefile.pamphlet
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index 6a281bc..3fa3009 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -1148,6 +1148,9 @@ The [[OUTSRC=${MNT}/${SYS}/src/algebra]] subdirectory contains the
 algebra source files extracted from the pamphlet files. These sources 
 allow the end user to change the algebra if needed.
 
+The HELP variable points to the location of the files used for the
+[[)help]] system command. These are flat files used to provide command
+line help to Axiom. They are extracted from the algebra pamphlets.
 <<environment>>=
 
 IN=${SRC}/algebra
@@ -1156,6 +1159,7 @@ OUT=${MNT}/${SYS}/algebra
 DOC=${MNT}/${SYS}/doc/src/algebra
 OUTSRC=${MNT}/${SYS}/src/algebra
 INPUT=${INT}/input
+HELP=${MNT}/${SYS}/doc/spadhelp
 
 @
 \subsection{The depsys variable}
@@ -2013,6 +2017,156 @@ layer23done:
 	@ echo ==================================
 
 @
+<<environment>>=
+SPADHELP=\
+ ${HELP}/AssociationList.help  ${HELP}/BalancedBinaryTree.help \
+ ${HELP}/BasicOperator.help    ${HELP}/BinaryExpansion.help \
+ ${HELP}/BinarySearchTree.help ${HELP}/CardinalNumber.help \
+ ${HELP}/CartesianTensor.help  ${HELP}/Character.help \
+ ${HELP}/CharacterClass.help   ${HELP}/CliffordAlgebra.help \
+ ${HELP}/Complex.help          ${HELP}/ContinuedFraction.help \
+ ${HELP}/CycleIndicators.help  ${HELP}/DeRhamComplex.help \
+ ${HELP}/DecimalExpansion.help 
+
+@
+The algebra files contain input chunks in regress format.
+This stanza is extracted by the src/input/Makefile after
+all of the other regression tests are complete. This stanza
+is put into a int/Makefile.algebra and then executed by make.
+<<algebra.regress>>=
+TESTSYS=  ${OBJ}/${SYS}/bin/interpsys
+
+REGRESS=\
+ AssociationList.regress  BalancedBinaryTree.regress \
+ BasicOperator.regress    BinaryExpansion.regress \
+ BinarySearchTree.regress CardinalNumber.regress \
+ CartesianTensor.regress  Character.regress \
+ CharacterClass.regress   CliffordAlgebra.regress \
+ Complex.regress          ContinuedFraction.regress \
+ CycleIndicators.regress  DeRhamComplex.regress \
+ DecimalExpansion.regress
+
+%.regress: %.input
+	@ echo algebra regression testing $*
+	@ rm -f $*.output
+	@ echo ')read $*.input' | ${TESTSYS} 
+	@ echo ')lisp (regress "$*.output")' | ${TESTSYS} \
+                | egrep -v '(Timestamp|Version)' | tee $*.regress
+
+all: ${REGRESS}
+	@echo algebra test cases complete.
+@
+<<spadhelp>>=
+${HELP}/AssociationList.help: ${IN}/list.spad.pamphlet
+	@echo 7000 create AssociationList.help from ${IN}/list.spad.pamphlet
+	@${TANGLE} -R"AssociationList.help" ${IN}/list.spad.pamphlet \
+            >${HELP}/AssociationList.help
+	@${TANGLE} -R"AssociationList.input" ${IN}/list.spad.pamphlet \
+            >${INPUT}/AssociationList.input
+
+${HELP}/BalancedBinaryTree.help: ${IN}/tree.spad.pamphlet
+	@echo 7001 create BalancedBinaryTree.help from ${IN}/tree.spad.pamphlet
+	@${TANGLE} -R"BalancedBinaryTree.help" ${IN}/tree.spad.pamphlet \
+            >${HELP}/BalancedBinaryTree.help
+	@${TANGLE} -R"BalancedBinaryTree.input" ${IN}/tree.spad.pamphlet \
+            >${INPUT}/BalancedBinaryTree.input
+
+${HELP}/BasicOperator.help: ${IN}/op.spad.pamphlet
+	@echo 7002 create BasicOperator.help from ${IN}/op.spad.pamphlet
+	@${TANGLE} -R"BasicOperator.help" ${IN}/op.spad.pamphlet \
+            >${HELP}/BasicOperator.help
+	@${TANGLE} -R"BasicOperator.input" ${IN}/op.spad.pamphlet \
+            >${INPUT}/BasicOperator.input
+
+${HELP}/BinaryExpansion.help: ${IN}/radix.spad.pamphlet
+	@echo 7003 create BinaryExpansion.help from ${IN}/radix.spad.pamphlet
+	@${TANGLE} -R"BinaryExpansion.help" ${IN}/radix.spad.pamphlet \
+            >${HELP}/BinaryExpansion.help
+	@${TANGLE} -R"BinaryExpansion.input" ${IN}/radix.spad.pamphlet \
+            >${INPUT}/BinaryExpansion.input
+
+${HELP}/BinarySearchTree.help: ${IN}/tree.spad.pamphlet
+	@echo 7004 create BinarySearchTree.help from ${IN}/tree.spad.pamphlet
+	@${TANGLE} -R"BinarySearchTree.help" ${IN}/tree.spad.pamphlet \
+            >${HELP}/BinarySearchTree.help
+	@${TANGLE} -R"BinarySearchTree.input" ${IN}/tree.spad.pamphlet \
+            >${INPUT}/BinarySearchTree.input
+
+${HELP}/CardinalNumber.help: ${IN}/card.spad.pamphlet
+	@echo 7005 create CardinalNumber.help from ${IN}/card.spad.pamphlet
+	@${TANGLE} -R"CardinalNumber.help" ${IN}/card.spad.pamphlet \
+            >${HELP}/CardinalNumber.help
+	@${TANGLE} -R"CardinalNumber.input" ${IN}/card.spad.pamphlet \
+            >${INPUT}/CardinalNumber.input
+
+${HELP}/CartesianTensor.help: ${IN}/carten.spad.pamphlet
+	@echo 7006 create CartesianTensor.help from ${IN}/carten.spad.pamphlet
+	@${TANGLE} -R"CartesianTensor.help" ${IN}/carten.spad.pamphlet \
+            >${HELP}/CartesianTensor.help
+	@${TANGLE} -R"CartesianTensor.input" ${IN}/carten.spad.pamphlet \
+            >${INPUT}/CartesianTensor.input
+
+${HELP}/Character.help: ${IN}/string.spad.pamphlet
+	@echo 7007 create Character.help from ${IN}/string.spad.pamphlet
+	@${TANGLE} -R"Character.help" ${IN}/string.spad.pamphlet \
+            >${HELP}/Character.help
+	@${TANGLE} -R"Character.input" ${IN}/string.spad.pamphlet \
+            >${INPUT}/Character.input
+
+${HELP}/CharacterClass.help: ${IN}/string.spad.pamphlet
+	@echo 7008 create CharacterClass.help from ${IN}/string.spad.pamphlet
+	@${TANGLE} -R"CharacterClass.help" ${IN}/string.spad.pamphlet \
+            >${HELP}/CharacterClass.help
+	@${TANGLE} -R"CharacterClass.input" ${IN}/string.spad.pamphlet \
+            >${INPUT}/CharacterClass.input
+
+${HELP}/CliffordAlgebra.help: ${IN}/clifford.spad.pamphlet
+	@echo 7009 create CliffordAlgebra.help from \
+          ${IN}/clifford.spad.pamphlet
+	@${TANGLE} -R"CliffordAlgebra.help" ${IN}/clifford.spad.pamphlet \
+            >${HELP}/CliffordAlgebra.help
+	@${TANGLE} -R"CliffordAlgebra.input" ${IN}/clifford.spad.pamphlet \
+            >${INPUT}/CliffordAlgebra.input
+
+${HELP}/Complex.help: ${IN}/gaussian.spad.pamphlet
+	@echo 7010 create Complex.help from ${IN}/gaussian.spad.pamphlet
+	@${TANGLE} -R"Complex.help" ${IN}/gaussian.spad.pamphlet \
+            >${HELP}/Complex.help
+	@${TANGLE} -R"Complex.input" ${IN}/gaussian.spad.pamphlet \
+            >${INPUT}/Complex.input
+
+${HELP}/ContinuedFraction.help: ${IN}/contfrac.spad.pamphlet
+	@echo 7011 create ContinuedFraction.help from \
+            ${IN}/contfrac.spad.pamphlet
+	@${TANGLE} -R"ContinuedFraction.help" ${IN}/contfrac.spad.pamphlet \
+            >${HELP}/ContinuedFraction.help
+	@${TANGLE} -R"ContinuedFraction.input" ${IN}/contfrac.spad.pamphlet \
+            >${INPUT}/ContinuedFraction.input
+
+${HELP}/CycleIndicators.help: ${IN}/cycles.spad.pamphlet
+	@echo 7012 create CycleIndicators.help from \
+            ${IN}/cycles.spad.pamphlet
+	@${TANGLE} -R"CycleIndicators.help" ${IN}/cycles.spad.pamphlet \
+            >${HELP}/CycleIndicators.help
+	@${TANGLE} -R"CycleIndicators.input" ${IN}/cycles.spad.pamphlet \
+            >${INPUT}/CycleIndicators.input
+
+${HELP}/DeRhamComplex.help: ${IN}/derham.spad.pamphlet
+	@echo 7013 create DeRhamComplex.help from ${IN}/derham.spad.pamphlet
+	@${TANGLE} -R"DeRhamComplex.help" ${IN}/derham.spad.pamphlet \
+            >${HELP}/DeRhamComplex.help
+	@${TANGLE} -R"DeRhamComplex.input" ${IN}/derham.spad.pamphlet \
+            >${INPUT}/DeRhamComplex.input
+
+${HELP}/DecimalExpansion.help: ${IN}/radix.spad.pamphlet
+	@echo 7014 create DecimalExpansion.help from ${IN}/radix.spad.pamphlet
+	@${TANGLE} -R"DecimalExpansion.help" ${IN}/radix.spad.pamphlet \
+            >${HELP}/DecimalExpansion.help
+	@${TANGLE} -R"DecimalExpansion.input" ${IN}/radix.spad.pamphlet \
+            >${INPUT}/DecimalExpansion.input
+
+@
+
 \section{The Makefile}
 
 <<*>>=
@@ -2048,7 +2202,8 @@ layer23done:
 <<USERLAYER>>
 <<order>>
 
-all: src ${OUT}/libdb.text ${DOCFILES} ${TESTS} ${SPADBIN}/index.html
+all: src ${OUT}/libdb.text ${DOCFILES} ${TESTS} ${SPADBIN}/index.html \
+        ${SPADHELP}
 	@ echo 4302 finished ${IN}
 
 ${SPADBIN}/index.html:
@@ -2086,6 +2241,7 @@ document: ${DOCFILES}
 
 <<genericRules>>
 
+<<spadhelp>>
 <<testrules>>
 <<ps (DOC from SRC)>>
 <<libdb.text (OUT from IN)>>
diff --git a/src/algebra/card.spad.pamphlet b/src/algebra/card.spad.pamphlet
index a158508..4d02a4d 100644
--- a/src/algebra/card.spad.pamphlet
+++ b/src/algebra/card.spad.pamphlet
@@ -10,6 +10,324 @@
 \tableofcontents
 \eject
 \section{domain CARD CardinalNumber}
+<<CardinalNumber.input>>=
+-- card.spad.pamphlet CardinalNumber.input
+)spool CardinalNumber.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 20
+c0 := 0 :: CardinalNumber
+--R 
+--R
+--R   (1)  0
+--R                                                         Type: CardinalNumber
+--E 1
+
+--S 2 of 20
+c1 := 1 :: CardinalNumber
+--R 
+--R
+--R   (2)  1
+--R                                                         Type: CardinalNumber
+--E 2
+
+--S 3 of 20
+c2 := 2 :: CardinalNumber
+--R 
+--R
+--R   (3)  2
+--R                                                         Type: CardinalNumber
+--E 3
+
+--S 4 of 20
+c3 := 3 :: CardinalNumber
+--R 
+--R
+--R   (4)  3
+--R                                                         Type: CardinalNumber
+--E 4
+
+--S 5 of 20
+A0 := Aleph 0
+--R 
+--R
+--R   (5)  Aleph(0)
+--R                                                         Type: CardinalNumber
+--E 5
+
+--S 6 of 20
+A1 := Aleph 1
+--R 
+--R
+--R   (6)  Aleph(1)
+--R                                                         Type: CardinalNumber
+--E 6
+
+--S 7 of 20
+finite? c2
+--R 
+--R
+--R   (7)  true
+--R                                                                Type: Boolean
+--E 7
+
+--S 8 of 20
+finite? A0
+--R 
+--R
+--R   (8)  false
+--R                                                                Type: Boolean
+--E 8
+
+--S 9 of 20
+countable? c2
+--R 
+--R
+--R   (9)  true
+--R                                                                Type: Boolean
+--E 9
+
+--S 10 of 20
+countable? A0
+--R 
+--R
+--R   (10)  true
+--R                                                                Type: Boolean
+--E 10
+
+--S 11 of 20
+countable? A1
+--R 
+--R
+--R   (11)  false
+--R                                                                Type: Boolean
+--E 11
+
+--S 12 of 20
+[c2 + c2, c2 + A1]
+--R 
+--R
+--R   (12)  [4,Aleph(1)]
+--R                                                    Type: List CardinalNumber
+--E 12
+
+--S 13 of 20
+[c0*c2, c1*c2, c2*c2, c0*A1, c1*A1, c2*A1, A0*A1]
+--R 
+--R
+--R   (13)  [0,2,4,0,Aleph(1),Aleph(1),Aleph(1)]
+--R                                                    Type: List CardinalNumber
+--E 13
+
+--S 14 of 20
+[c2**c0, c2**c1, c2**c2, A1**c0, A1**c1, A1**c2]
+--R 
+--R
+--R   (14)  [1,2,4,1,Aleph(1),Aleph(1)]
+--R                                                    Type: List CardinalNumber
+--E 14
+
+--S 15 of 20
+[c2-c1, c2-c2, c2-c3, A1-c2, A1-A0, A1-A1]
+--R 
+--R
+--R   (15)  [1,0,"failed",Aleph(1),Aleph(1),"failed"]
+--R                                    Type: List Union(CardinalNumber,"failed")
+--E 15
+
+--S 16 of 20
+generalizedContinuumHypothesisAssumed true
+--R 
+--R
+--R   (16)  true
+--R                                                                Type: Boolean
+--E 16
+
+--S 17 of 20
+[c0**A0, c1**A0, c2**A0, A0**A0, A0**A1, A1**A0, A1**A1]
+--R 
+--R
+--R   (17)  [0,1,Aleph(1),Aleph(1),Aleph(2),Aleph(1),Aleph(2)]
+--R                                                    Type: List CardinalNumber
+--E 17
+
+--S 18 of 20
+a := Aleph 0
+--R 
+--R
+--R   (18)  Aleph(0)
+--R                                                         Type: CardinalNumber
+--E 18
+
+--S 19 of 20
+c := 2**a
+--R 
+--R
+--R   (19)  Aleph(1)
+--R                                                         Type: CardinalNumber
+--E 19
+
+--S 20 of 20
+f := 2**c
+--R 
+--R
+--R   (20)  Aleph(2)
+--R                                                         Type: CardinalNumber
+--E 20
+)spool
+)lisp (bye)
+@
+<<CardinalNumber.help>>=
+====================================================================
+CardinalNumber examples
+====================================================================
+
+The CardinalNumber domain can be used for values indicating the
+cardinality of sets, both finite and infinite.  For example, the
+dimension operation in the category VectorSpace returns a cardinal
+number.
+
+The non-negative integers have a natural construction as cardinals
+
+  0 = #{ }, 1 = {0}, 2 = {0, 1}, ..., n = {i | 0 <= i < n}.
+
+The fact that 0 acts as a zero for the multiplication of cardinals is
+equivalent to the axiom of choice.
+
+Cardinal numbers can be created by conversion from non-negative integers.
+
+  c0 := 0 :: CardinalNumber
+   0 
+                      Type: CardinalNumber
+
+  c1 := 1 :: CardinalNumber
+   1 
+                      Type: CardinalNumber
+
+  c2 := 2 :: CardinalNumber
+   2 
+                      Type: CardinalNumber
+
+  c3 := 3 :: CardinalNumber
+   3 
+                      Type: CardinalNumber
+
+They can also be obtained as the named cardinal Aleph(n).
+
+  A0 := Aleph 0
+   Aleph(0)
+                      Type: CardinalNumber
+
+  A1 := Aleph 1
+   Aleph(1)
+                      Type: CardinalNumber
+
+The finite? operation tests whether a value is a finite cardinal, that
+is, a non-negative integer.
+
+  finite? c2
+   true
+                      Type: Boolean
+
+  finite? A0
+   false
+                      Type: Boolean
+
+Similarly, the countable?  operation determines whether a value is a
+countable cardinal, that is, finite or Aleph(0).
+
+  countable? c2
+   true
+                      Type: Boolean
+
+  countable? A0
+   true
+                      Type: Boolean
+
+  countable? A1
+   false
+                      Type: Boolean
+
+Arithmetic operations are defined on cardinal numbers as follows:
+If x = #X  and y = #Y then
+
+  x+y  = #(X+Y) cardinality of the disjoint union
+  x-y  = #(X-Y) cardinality of the relative complement
+  x*y  = #(X*Y) cardinality of the Cartesian product
+  x**y = #(X**Y) cardinality of the set of maps from Y to X
+
+Here are some arithmetic examples.
+
+  [c2 + c2, c2 + A1]
+   [4, Aleph(1)]
+                      Type: List CardinalNumber
+
+  [c0*c2, c1*c2, c2*c2, c0*A1, c1*A1, c2*A1, A0*A1]
+   [0, 2, 4, 0, Aleph(1), Aleph(1), Aleph(1)]
+                      Type: List CardinalNumber
+
+  [c2**c0, c2**c1, c2**c2, A1**c0, A1**c1, A1**c2]
+   [1, 2, 4, 1, Aleph(1), Aleph(1)]
+                      Type: List CardinalNumber
+
+Subtraction is a partial operation: it is not defined when subtracting
+a larger cardinal from a smaller one, nor when subtracting two equal
+infinite cardinals.
+
+  [c2-c1, c2-c2, c2-c3, A1-c2, A1-A0, A1-A1]
+   [1, 0, "failed", Aleph(1), Aleph(1), "failed"]
+                      Type: List Union(CardinalNumber,"failed")
+
+The generalized continuum hypothesis asserts that
+
+  2**Aleph i = Aleph(i+1)
+
+and is independent of the axioms of set theory.
+
+(reference: Goedel, The consistency of the continuum hypothesis,
+Ann. Math. Studies, Princeton Univ. Press, 1940.)
+
+The CardinalNumber domain provides an operation to assert whether the
+hypothesis is to be assumed.
+
+  generalizedContinuumHypothesisAssumed true
+   true
+                      Type: Boolean
+
+When the generalized continuum hypothesis is assumed, exponentiation
+to a transfinite power is allowed.
+
+  [c0**A0, c1**A0, c2**A0, A0**A0, A0**A1, A1**A0, A1**A1]
+   [0, 1, Aleph(1), Aleph(1), Aleph(2), Aleph(1), Aleph(2)]
+                      Type: List CardinalNumber
+
+Three commonly encountered cardinal numbers are
+
+  a = #Z countable infinity
+  c = #R the continuum
+  f = #{g| g: [0,1] -> R}
+
+In this domain, these values are obtained under the generalized
+continuum hypothesis in this way.
+
+  a := Aleph 0
+   Aleph(0)
+                      Type: CardinalNumber
+
+  c := 2**a
+   Aleph(1)
+                      Type: CardinalNumber
+
+  f := 2**c
+   Aleph(2)
+                      Type: CardinalNumber
+
+See Also:
+o )show CardinalNumber
+o $AXIOM/doc/src/algebra/card.spad.dvi
+
+@
 <<domain CARD CardinalNumber>>=
 )abbrev domain CARD CardinalNumber
 ++ Author: S.M. Watt
diff --git a/src/algebra/carten.spad.pamphlet b/src/algebra/carten.spad.pamphlet
index 0f1d295..5bcaa75 100644
--- a/src/algebra/carten.spad.pamphlet
+++ b/src/algebra/carten.spad.pamphlet
@@ -102,6 +102,954 @@ GradedAlgebra(R: CommutativeRing, E: AbelianMonoid): Category ==
 
 @
 \section{domain CARTEN CartesianTensor}
+<<CartesianTensor.input>>=
+-- carten.spad.pamphlet CartesianTensor.input
+)spool CartesianTensor.output
+)set message test on
+)set message auto off
+)clear all
+--S 1
+CT := CARTEN(i0 := 1, 2, Integer)
+--R 
+--R
+--R   (1)  CartesianTensor(1,2,Integer)
+--R                                                                 Type: Domain
+--E 1
+
+--S 2
+t0: CT := 8
+--R 
+--R
+--R   (2)  8
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 2
+
+--S 3
+rank t0
+--R 
+--R
+--R   (3)  0
+--R                                                     Type: NonNegativeInteger
+--E 3
+
+--S 4
+v: DirectProduct(2, Integer) := directProduct [3,4]
+--R 
+--R
+--R   (4)  [3,4]
+--R                                               Type: DirectProduct(2,Integer)
+--E 4
+
+--S 5
+Tv: CT := v
+--R 
+--R
+--R   (5)  [3,4]
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 5
+
+--S 6
+m: SquareMatrix(2, Integer) := matrix [ [1,2],[4,5] ]
+--R 
+--R
+--R        +1  2+
+--R   (6)  |    |
+--R        +4  5+
+--R                                                Type: SquareMatrix(2,Integer)
+--E 6
+
+--S 7
+Tm: CT := m
+--R 
+--R
+--R        +1  2+
+--R   (7)  |    |
+--R        +4  5+
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 7
+
+--S 8
+n: SquareMatrix(2, Integer) := matrix [ [2,3],[0,1] ]
+--R 
+--R
+--R        +2  3+
+--R   (8)  |    |
+--R        +0  1+
+--R                                                Type: SquareMatrix(2,Integer)
+--E 8
+
+--S 9
+Tn: CT := n
+--R 
+--R
+--R        +2  3+
+--R   (9)  |    |
+--R        +0  1+
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 9
+
+--S 10
+t1: CT := [2, 3]
+--R 
+--R
+--R   (10)  [2,3]
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 10
+
+--S 11
+rank t1
+--R 
+--R
+--R   (11)  1
+--R                                                        Type: PositiveInteger
+--E 11
+
+--S 12
+t2: CT := [t1, t1]
+--R 
+--R
+--R         +2  3+
+--R   (12)  |    |
+--R         +2  3+
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 12
+
+--S 13
+t3: CT := [t2, t2]
+--R 
+--R
+--R          +2  3+ +2  3+
+--R   (13)  [|    |,|    |]
+--R          +2  3+ +2  3+
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 13
+
+--S 14
+tt: CT := [t3, t3]; tt := [tt, tt]
+--R 
+--R
+--R          ++2  3+  +2  3++ ++2  3+  +2  3++
+--R          ||    |  |    || ||    |  |    ||
+--R          |+2  3+  +2  3+| |+2  3+  +2  3+|
+--R   (14)  [|              |,|              |]
+--R          |+2  3+  +2  3+| |+2  3+  +2  3+|
+--R          ||    |  |    || ||    |  |    ||
+--R          ++2  3+  +2  3++ ++2  3+  +2  3++
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 14
+
+--S 15
+rank tt
+--R 
+--R
+--R   (15)  5
+--R                                                        Type: PositiveInteger
+--E 15
+
+--S 16
+Tmn := product(Tm, Tn)
+--R 
+--R
+--R         ++2  3+    +4  6+ +
+--R         ||    |    |    | |
+--R         |+0  1+    +0  2+ |
+--R   (16)  |                 |
+--R         |+8  12+  +10  15+|
+--R         ||     |  |      ||
+--R         ++0  4 +  +0   5 ++
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 16
+
+--S 17
+Tmv := contract(Tm,2,Tv,1)
+--R 
+--R
+--R   (17)  [11,32]
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 17
+
+--S 18
+Tm*Tv
+--R 
+--R
+--R   (18)  [11,32]
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 18
+
+--S 19
+Tmv = m * v
+--R 
+--R
+--R   (19)  [11,32]= [11,32]
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 19
+
+--S 20
+t0()
+--R 
+--R
+--R   (20)  8
+--R                                                        Type: PositiveInteger
+--E 20
+
+--S 21
+t1(1+1)
+--R 
+--R
+--R   (21)  3
+--R                                                        Type: PositiveInteger
+--E 21
+
+--S 22
+t2(2,1)
+--R 
+--R
+--R   (22)  2
+--R                                                        Type: PositiveInteger
+--E 22
+
+--S 23
+t3(2,1,2)
+--R 
+--R
+--R   (23)  3
+--R                                                        Type: PositiveInteger
+--E 23
+
+--S 24
+Tmn(2,1,2,1)
+--R 
+--R
+--R   (24)  0
+--R                                                     Type: NonNegativeInteger
+--E 24
+
+--S 25
+t0[]
+--R 
+--R
+--R   (25)  8
+--R                                                        Type: PositiveInteger
+--E 25
+
+--S 26
+t1[2]
+--R 
+--R
+--R   (26)  3
+--R                                                        Type: PositiveInteger
+--E 26
+
+--S 27
+t2[2,1]
+--R 
+--R
+--R   (27)  2
+--R                                                        Type: PositiveInteger
+--E 27
+
+--S 28
+t3[2,1,2]
+--R 
+--R
+--R   (28)  3
+--R                                                        Type: PositiveInteger
+--E 28
+
+--S 29
+Tmn[2,1,2,1]
+--R 
+--R
+--R   (29)  0
+--R                                                     Type: NonNegativeInteger
+--E 29
+
+--S 30
+cTmn := contract(Tmn,1,2)
+--R 
+--R
+--R         +12  18+
+--R   (30)  |      |
+--R         +0   6 +
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 30
+
+--S 31
+trace(m) * n
+--R 
+--R
+--R         +12  18+
+--R   (31)  |      |
+--R         +0   6 +
+--R                                                Type: SquareMatrix(2,Integer)
+--E 31
+
+--S 32
+contract(Tmn,1,2) = trace(m) * n
+--R 
+--R
+--R         +12  18+  +12  18+
+--R   (32)  |      |= |      |
+--R         +0   6 +  +0   6 +
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 32
+
+--S 33
+contract(Tmn,1,3) = transpose(m) * n
+--R 
+--R
+--R         +2  7 +  +2  7 +
+--R   (33)  |     |= |     |
+--R         +4  11+  +4  11+
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 33
+
+--S 34
+contract(Tmn,1,4) = transpose(m) * transpose(n)
+--R 
+--R
+--R         +14  4+  +14  4+
+--R   (34)  |     |= |     |
+--R         +19  5+  +19  5+
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 34
+
+--S 35
+contract(Tmn,2,3) = m * n
+--R 
+--R
+--R         +2  5 +  +2  5 +
+--R   (35)  |     |= |     |
+--R         +8  17+  +8  17+
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 35
+
+--S 36
+contract(Tmn,2,4) = m * transpose(n)
+--R 
+--R
+--R         +8   2+  +8   2+
+--R   (36)  |     |= |     |
+--R         +23  5+  +23  5+
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 36
+
+--S 37
+contract(Tmn,3,4) = trace(n) * m
+--R 
+--R
+--R         +3   6 +  +3   6 +
+--R   (37)  |      |= |      |
+--R         +12  15+  +12  15+
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 37
+
+--S 38
+tTmn := transpose(Tmn,1,3)
+--R 
+--R
+--R         ++2  3 +  +4   6 ++
+--R         ||     |  |      ||
+--R         |+8  12+  +10  15+|
+--R   (38)  |                 |
+--R         |+0  1+    +0  2+ |
+--R         ||    |    |    | |
+--R         ++0  4+    +0  5+ +
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 38
+
+--S 39
+transpose Tmn
+--R 
+--R
+--R         ++2  8+   +4  10++
+--R         ||    |   |     ||
+--R         |+0  0+   +0  0 +|
+--R   (39)  |                |
+--R         |+3  12+  +6  15+|
+--R         ||     |  |     ||
+--R         ++1  4 +  +2  5 ++
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 39
+
+--S 40
+transpose Tm = transpose m
+--R 
+--R
+--R         +1  4+  +1  4+
+--R   (40)  |    |= |    |
+--R         +2  5+  +2  5+
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 40
+
+--S 41
+rTmn := reindex(Tmn, [1,4,2,3])
+--R 
+--R
+--R         ++2  0+   +3  1+ +
+--R         ||    |   |    | |
+--R         |+4  0+   +6  2+ |
+--R   (41)  |                |
+--R         |+8   0+  +12  4+|
+--R         ||     |  |     ||
+--R         ++10  0+  +15  5++
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 41
+
+--S 42
+tt := transpose(Tm)*Tn - Tn*transpose(Tm)
+--R 
+--R
+--R         +- 6  - 16+
+--R   (42)  |         |
+--R         + 2    6  +
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 42
+
+--S 43
+Tv*(tt+Tn)
+--R 
+--R
+--R   (43)  [- 4,- 11]
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 43
+
+--S 44
+reindex(product(Tn,Tn),[4,3,2,1])+3*Tn*product(Tm,Tm)
+--R 
+--R
+--R         ++46   84 +  +57   114++
+--R         ||        |  |        ||
+--R         |+174  212+  +228  285+|
+--R   (44)  |                      |
+--R         | +18  24+    +17  30+ |
+--R         | |      |    |      | |
+--R         + +57  63+    +63  76+ +
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 44
+
+--S 45
+delta:  CT := kroneckerDelta()
+--R 
+--R
+--R         +1  0+
+--R   (45)  |    |
+--R         +0  1+
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 45
+
+--S 46
+contract(Tmn, 2, delta, 1) = reindex(Tmn, [1,3,4,2])
+--R 
+--R
+--R         + +2  4+   +0  0++  + +2  4+   +0  0++
+--R         | |    |   |    ||  | |    |   |    ||
+--R         | +3  6+   +1  2+|  | +3  6+   +1  2+|
+--R   (46)  |                |= |                |
+--R         |+8   10+  +0  0+|  |+8   10+  +0  0+|
+--R         ||      |  |    ||  ||      |  |    ||
+--R         ++12  15+  +4  5++  ++12  15+  +4  5++
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 46
+
+--S 47
+epsilon:CT := leviCivitaSymbol()
+--R 
+--R
+--R         + 0   1+
+--R   (47)  |      |
+--R         +- 1  0+
+--R                                           Type: CartesianTensor(1,2,Integer)
+--E 47
+
+--S 48
+contract(epsilon*Tm*epsilon, 1,2) = 2 * determinant m
+--R 
+--R
+--R   (48)  - 6= - 6
+--R                                  Type: Equation CartesianTensor(1,2,Integer)
+--E 48
+)spool
+)lisp (bye)
+@
+<<CartesianTensor.help>>=
+====================================================================
+CartesianTensor
+====================================================================
+
+CartesianTensor(i0,dim,R) provides Cartesian tensors with components
+belonging to a commutative ring R.  Tensors can be described as a
+generalization of vectors and matrices.  This gives a concise tensor
+algebra for multilinear objects supported by the CartesianTensor
+domain.  You can form the inner or outer product of any two tensors
+and you can add or subtract tensors with the same number of components.  
+Additionally, various forms of traces and transpositions are useful.
+
+The CartesianTensor constructor allows you to specify the minimum
+index for subscripting.  In what follows we discuss in detail how to
+manipulate tensors.
+
+Here we construct the domain of Cartesian tensors of dimension 2 over the
+integers, with indices starting at 1.
+
+  CT := CARTEN(i0 := 1, 2, Integer)
+   CartesianTensor(1,2,Integer) 
+                      Type: Domain
+
+====================================================================
+Forming tensors
+====================================================================
+
+Scalars can be converted to tensors of rank zero.
+
+  t0: CT := 8
+   8 
+                      Type: CartesianTensor(1,2,Integer)
+
+  rank t0
+   0 
+                      Type: NonNegativeInteger
+
+Vectors (mathematical direct products, rather than one dimensional array
+structures) can be converted to tensors of rank one.
+
+  v: DirectProduct(2, Integer) := directProduct [3,4]
+   [3, 4]
+                      Type: DirectProduct(2,Integer)
+
+  Tv: CT := v
+   [3, 4]
+                      Type: CartesianTensor(1,2,Integer)
+
+Matrices can be converted to tensors of rank two.
+
+  m: SquareMatrix(2, Integer) := matrix [ [1,2],[4,5] ]
+   +1  2+
+   |    |
+   +4  5+
+                      Type: SquareMatrix(2,Integer)
+
+  Tm: CT := m
+   +1  2+
+   |    |
+   +4  5+
+                      Type: CartesianTensor(1,2,Integer)
+
+  n: SquareMatrix(2, Integer) := matrix [ [2,3],[0,1] ]
+   +2  3+
+   |    |
+   +0  1+
+                      Type: SquareMatrix(2,Integer)
+
+  Tn: CT := n
+   +2  3+
+   |    |
+   +0  1+
+                      Type: CartesianTensor(1,2,Integer)
+
+In general, a tensor of rank k can be formed by making a list of
+rank k-1 tensors or, alternatively, a k-deep nested list of lists.
+
+  t1: CT := [2, 3]
+   [2, 3]
+                      Type: CartesianTensor(1,2,Integer)
+
+  rank t1
+   1 
+                      Type: PositiveInteger
+
+  t2: CT := [t1, t1]
+   +2  3+
+   |    |
+   +2  3+
+                      Type: CartesianTensor(1,2,Integer)
+
+  t3: CT := [t2, t2]
+
+    +2  3+ +2  3+
+   [|    |,|    |]
+    +2  3+ +2  3+
+                      Type: CartesianTensor(1,2,Integer)
+
+  tt: CT := [t3, t3]; tt := [tt, tt]
+    ++2  3+  +2  3++ ++2  3+  +2  3++
+    ||    |  |    || ||    |  |    ||
+    |+2  3+  +2  3+| |+2  3+  +2  3+|
+   [|              |,|              |]
+    |+2  3+  +2  3+| |+2  3+  +2  3+|
+    ||    |  |    || ||    |  |    ||
+    ++2  3+  +2  3++ ++2  3+  +2  3++
+                      Type: CartesianTensor(1,2,Integer)
+
+  rank tt
+   5 
+                      Type: PositiveInteger
+
+====================================================================
+Multiplication
+====================================================================
+
+Given two tensors of rank k1 and k2, the outer product forms a new
+tensor of rank k1+k2. Here
+
+  Tmn(i,j,k,l) = Tm(i,j)Tn(k,l)
+
+  Tmn := product(Tm, Tn)
+    ++2  3+    +4  6+ +
+    ||    |    |    | |
+    |+0  1+    +0  2+ |
+    |                 |
+    |+8  12+  +10  15+|
+    ||     |  |      ||
+    ++0  4 +  +0   5 ++
+                      Type: CartesianTensor(1,2,Integer)
+
+The inner product (contract) forms a tensor of rank k1+k2-2.  This
+product generalizes the vector dot product and matrix-vector product
+by summing component products along two indices.
+
+Here we sum along the second index of Tm and the first index of Tv. Here 
+
+ Tmv = sum {j=1..dim} Tm(i,j) Tv(j)
+
+ Tmv := contract(Tm,2,Tv,1)
+   [11,32]
+                      Type: CartesianTensor(1,2,Integer)
+
+The multiplication operator * is scalar multiplication or an inner
+product depending on the ranks of the arguments.
+
+If either argument is rank zero it is treated as scalar multiplication.  
+Otherwise, a*b is the inner product summing the last index of a with the 
+first index of b.
+
+  Tm*Tv
+   [11,32]
+                     Type: CartesianTensor(1,2,Integer)
+
+This definition is consistent with the inner product on matrices
+and vectors.
+
+  Tmv = m * v
+   [11,32] = [11,32]
+                     Type: Equation CartesianTensor(1,2,Integer)
+
+====================================================================
+Selecting Components
+====================================================================
+
+For tensors of low rank (that is, four or less), components can be selected
+by applying the tensor to its indices.
+
+  t0()
+   8
+                     Type: PositiveInteger
+
+  t1(1+1)
+   3
+                     Type: PositiveInteger
+
+  t2(2,1)
+   2
+                     Type: PositiveInteger
+
+  t3(2,1,2)
+    3
+                     Type: PositiveInteger
+
+  Tmn(2,1,2,1)
+    0
+                     Type: NonNegativeInteger
+
+A general indexing mechanism is provided for a list of indices.
+
+  t0[]
+    8
+                     Type: PositiveInteger
+
+  t1[2]
+    3
+                     Type: PositiveInteger
+
+  t2[2,1]
+    2
+                     Type: PositiveInteger
+
+The general mechanism works for tensors of arbitrary rank, but is
+somewhat less efficient since the intermediate index list must be created.
+
+  t3[2,1,2]
+    3
+                     Type: PositiveInteger
+
+  Tmn[2,1,2,1]
+    0
+                     Type: NonNegativeInteger
+
+====================================================================
+Contraction
+====================================================================
+
+A "contraction" between two tensors is an inner product, as we have
+seen above.  You can also contract a pair of indices of a single
+tensor.  This corresponds to a "trace" in linear algebra.  The
+expression contract(t,k1,k2) forms a new tensor by summing the
+diagonal given by indices in position k1 and k2.
+
+This is the tensor given by
+  xTmn = sum{k=1..dim} Tmn(k,k,i,j)
+
+  cTmn := contract(Tmn,1,2)
+    +12  18+
+    |      |
+    +0   6 +
+                         Type: CartesianTensor(1,2,Integer)
+
+Since Tmn is the outer product of matrix m and matrix n, the above is
+equivalent to this.
+
+  trace(m) * n
+    +12  18+
+    |      |
+    +0   6 +
+                         Type: SquareMatrix(2,Integer)
+
+In this and the next few examples, we show all possible contractions
+of Tmn and their matrix algebra equivalents.
+
+  contract(Tmn,1,2) = trace(m) * n
+   +12  18+  +12  18+
+   |      |= |      |
+   +0   6 +  +0   6 +
+                          Type: Equation CartesianTensor(1,2,Integer)
+
+  contract(Tmn,1,3) = transpose(m) * n
+   +2  7 +  +2  7 +
+   |     |= |     |
+   +4  11+  +4  11+
+                          Type: Equation CartesianTensor(1,2,Integer)
+
+  contract(Tmn,1,4) = transpose(m) * transpose(n)
+   +14  4+  +14  4+
+   |     |= |     |
+   +19  5+  +19  5+
+                          Type: Equation CartesianTensor(1,2,Integer)
+
+  contract(Tmn,2,3) = m * n
+   +2  5 +  +2  5 +
+   |     |= |     |
+   +8  17+  +8  17+
+                          Type: Equation CartesianTensor(1,2,Integer)
+
+  contract(Tmn,2,4) = m * transpose(n)
+   +8   2+  +8   2+
+   |     |= |     |
+   +23  5+  +23  5+
+                          Type: Equation CartesianTensor(1,2,Integer)
+
+  contract(Tmn,3,4) = trace(n) * m
+   +3   6 +  +3   6 +
+   |      |= |      |
+   +12  15+  +12  15+
+                          Type: Equation CartesianTensor(1,2,Integer)
+
+====================================================================
+Transpositions
+====================================================================
+
+You can exchange any desired pair of indices using the transpose
+operation.
+
+Here the indices in positions one and three are exchanged, that is,
+  tTmn(i,j,k,l) = Tmn(k,j,i,l)
+
+  tTmn := transpose(Tmn,1,3)
+   ++2  3 +  +4   6 ++
+   ||     |  |      ||
+   |+8  12+  +10  15+|
+   |                 |
+   |+0  1+    +0  2+ |
+   ||    |    |    | |
+   ++0  4+    +0  5+ +
+                             Type: CartesianTensor(1,2,Integer)
+
+If no indices are specified, the first and last index are exchanged.
+
+  transpose Tmn
+   ++2  8+   +4  10++
+   ||    |   |     ||
+   |+0  0+   +0  0 +|
+   |                |
+   |+3  12+  +6  15+|
+   ||     |  |     ||
+   ++1  4 +  +2  5 ++
+                             Type: CartesianTensor(1,2,Integer)
+
+This is consistent with the matrix transpose.
+
+  transpose Tm = transpose m
+   +1  4+  +1  4+
+   |    |= |    |
+   +2  5+  +2  5+
+                             Type: Equation CartesianTensor(1,2,Integer)
+
+
+If a more complicated reordering of the indices is required, then the
+reindex operation can be used.  This operation allows the indices to
+be arbitrarily permuted.
+
+  rTmn(i,j,k,l) = Tmn(i,l,j,k)
+
+  rTmn := reindex(Tmn, [1,4,2,3])
+   ++2  0+   +3  1+ +
+   ||    |   |    | |
+   |+4  0+   +6  2+ |
+   |                |
+   |+8   0+  +12  4+|
+   ||     |  |     ||
+   ++10  0+  +15  5++
+                              Type: CartesianTensor(1,2,Integer)
+
+====================================================================
+Arithmetic
+====================================================================
+
+Tensors of equal rank can be added or subtracted so arithmetic
+expressions can be used to produce new tensors.
+
+  tt := transpose(Tm)*Tn - Tn*transpose(Tm)
+   +- 6  - 16+
+   |         |
+   + 2    6  +
+                              Type: CartesianTensor(1,2,Integer)
+
+
+  Tv*(tt+Tn)
+   [- 4,- 11]
+                              Type: CartesianTensor(1,2,Integer)
+
+  reindex(product(Tn,Tn),[4,3,2,1])+3*Tn*product(Tm,Tm)
+   ++46   84 +  +57   114++
+   ||        |  |        ||
+   |+174  212+  +228  285+|
+   |                      |
+   | +18  24+    +17  30+ |
+   | |      |    |      | |
+   + +57  63+    +63  76+ +
+                              Type: CartesianTensor(1,2,Integer)
+
+====================================================================
+Specific Tensors
+====================================================================
+
+Two specific tensors have properties which depend only on the dimension.
+
+The Kronecker delta satisfies
+
+             +-              -+
+             |   1  if i  = j |
+delta(i,j) = |                |
+             |   0  if i ^= j |
+             +-              -+
+
+
+  delta:  CT := kroneckerDelta()
+   +1  0+
+   |    |
+   +0  1+
+                              Type: CartesianTensor(1,2,Integer)
+
+This can be used to reindex via contraction.
+
+  contract(Tmn, 2, delta, 1) = reindex(Tmn, [1,3,4,2])
+   + +2  4+   +0  0++  + +2  4+   +0  0++
+   | |    |   |    ||  | |    |   |    ||
+   | +3  6+   +1  2+|  | +3  6+   +1  2+|
+   |                |= |                |
+   |+8   10+  +0  0+|  |+8   10+  +0  0+|
+   ||      |  |    ||  ||      |  |    ||
+   ++12  15+  +4  5++  ++12  15+  +4  5++
+                             Type: Equation CartesianTensor(1,2,Integer)
+
+The Levi Civita symbol determines the sign of a permutation of indices.
+
+  epsilon:CT := leviCivitaSymbol()
+   + 0   1+
+   |      |
+   +- 1  0+
+                              Type: CartesianTensor(1,2,Integer)
+
+Here we have:
+
+  epsilon(i1,...,idim)
+     = +1  if i1,...,idim is an even permutation of i0,...,i0+dim-1
+     = -1  if i1,...,idim is an  odd permutation of i0,...,i0+dim-1
+     =  0  if i1,...,idim is not   a permutation of i0,...,i0+dim-1
+
+This property can be used to form determinants.
+
+  contract(epsilon*Tm*epsilon, 1,2) = 2 * determinant m
+   - 6= - 6
+                            Type: Equation CartesianTensor(1,2,Integer)
+
+
+====================================================================
+Properties of the CartesianTensor domain
+====================================================================
+
+GradedModule(R,E) denotes "E-graded R-module", that is, a collection
+of R-modules indexed by an abelian monoid E. An element g of G[s] for
+some specific s in E is said to be an element of G with degree s.
+Sums are defined in each module G[s] so two elements of G can be added
+if they have the same degree.  Morphisms can be defined and composed
+by degree to give the mathematical category of graded modules.
+
+GradedAlgebra(R,E) denotes "E-graded R-algebra".  A graded algebra is
+a graded module together with a degree preserving R-bilinear map,
+called the product.
+
+  degree(product(a,b))    = degree(a) + degree(b)
+
+  product(r*a,b)          = product(a,r*b) = r*product(a,b)
+  product(a1+a2,b)        = product(a1,b) + product(a2,b)
+  product(a,b1+b2)        = product(a,b1) + product(a,b2)
+  product(a,product(b,c)) = product(product(a,b),c)
+
+The domain CartesianTensor(i0, dim, R) belongs to the category
+GradedAlgebra(R, NonNegativeInteger).  The non-negative integer degree
+is the tensor rank and the graded algebra product is the tensor outer
+product.  The graded module addition captures the notion that only
+tensors of equal rank can be added.
+
+If V is a vector space of dimension dim over R, then the tensor module
+T[k](V) is defined as
+
+ T[0](V) = R
+  T[k](V) = T[k-1](V) * V
+
+where * denotes the R-module tensor product. CartesianTensor(i0,dim,R) 
+is the graded algebra in which the degree k module is T[k](V).
+
+====================================================================
+Tensor Calculus
+====================================================================
+
+It should be noted here that often tensors are used in the context of
+tensor-valued manifold maps.  This leads to the notion of covariant
+and contravariant bases with tensor component functions transforming
+in specific ways under a change of coordinates on the manifold.  This
+is no more directly supported by the CartesianTensor domain than it is
+by the Vector domain.  However, it is possible to have the components
+implicitly represent component maps by choosing a polynomial or
+expression type for the components.  In this case, it is up to the
+user to satisfy any constraints which arise on the basis of this
+interpretation.
+
+See Also
+o )show CartesianTensor
+o $AXIOM/doc/src/algebra/carten.spad.dvi
+
+@
 <<domain CARTEN CartesianTensor>>=
 )abbrev domain CARTEN CartesianTensor
 ++ Author: Stephen M. Watt
diff --git a/src/algebra/clifford.spad.pamphlet b/src/algebra/clifford.spad.pamphlet
index 88b7b3d..cd94dd5 100644
--- a/src/algebra/clifford.spad.pamphlet
+++ b/src/algebra/clifford.spad.pamphlet
@@ -236,6 +236,624 @@ $\mathbb{R}_{m,m}$      & --------$>$ & $\mathbb{R}^{4^m}$ \\
  $\mathbb{R}(2^m)$      & --------$>$ &  $\mathbb{R}^{4^m}$\\
                &  reshape  &           \\
 \end{tabular}
+<<CliffordAlgebra.input>>=
+-- clifford.spad.pamphlet CliffordAlgebra.input
+)spool CliffordAlgebra.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 36
+K := Fraction Polynomial Integer
+--R 
+--R
+--R   (1)  Fraction Polynomial Integer
+--R                                                                 Type: Domain
+--E 1
+
+--S 2 of 36
+m := matrix [ [-1] ]
+--R 
+--R
+--R   (2)  [- 1]
+--R                                                         Type: Matrix Integer
+--E 2
+
+--S 3 of 36
+C := CliffordAlgebra(1, K, quadraticForm m)
+--R 
+--R
+--R   (3)  CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+--R                                                                 Type: Domain
+--E 3
+
+--S 4 of 36
+i: C := e(1)
+--R 
+--R
+--R   (4)  e
+--R         1
+--R                  Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+--E 4
+
+--S 5 of 36
+x := a + b * i
+--R 
+--R
+--R   (5)  a + b e
+--R               1
+--R                  Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+--E 5
+
+--S 6 of 36
+y := c + d * i
+--R 
+--R
+--R   (6)  c + d e
+--R               1
+--R                  Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+--E 6
+
+--S 7 of 36
+x * y
+--R 
+--R
+--R   (7)  - b d + a c + (a d + b c)e
+--R                                  1
+--R                  Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+--E 7
+)clear all
+ 
+--S 8 of 36
+K := Fraction Polynomial Integer
+--R 
+--R
+--R   (1)  Fraction Polynomial Integer
+--R                                                                 Type: Domain
+--E 8
+
+--S 9 of 36
+m := matrix [ [-1,0],[0,-1] ]
+--R 
+--R
+--R        +- 1   0 +
+--R   (2)  |        |
+--R        + 0   - 1+
+--R                                                         Type: Matrix Integer
+--E 9
+
+--S 10 of 36
+H  := CliffordAlgebra(2, K, quadraticForm m)
+--R 
+--R
+--R   (3)  CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--R                                                                 Type: Domain
+--E 10
+
+--S 11 of 36
+i: H  := e(1)
+--R 
+--R
+--R   (4)  e
+--R         1
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 11
+
+--S 12 of 36
+j: H  := e(2)
+--R 
+--R
+--R   (5)  e
+--R         2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 12
+
+--S 13 of 36
+k: H  := i * j
+--R 
+--R
+--R   (6)  e e
+--R         1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 13
+
+--S 14 of 36
+x := a + b * i + c * j + d * k
+--R 
+--R
+--R   (7)  a + b e  + c e  + d e e
+--R               1      2      1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 14
+
+--S 15 of 36
+y := e + f * i + g * j + h * k 
+--R 
+--R
+--R   (8)  e + f e  + g e  + h e e
+--R               1      2      1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 15
+
+--S 16 of 36
+x + y
+--R 
+--R
+--R   (9)  e + a + (f + b)e  + (g + c)e  + (h + d)e e
+--R                        1           2           1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 16
+
+--S 17 of 36
+x * y
+--R 
+--R
+--R   (10)
+--R     - d h - c g - b f + a e + (c h - d g + a f + b e)e
+--R                                                       1
+--R   + 
+--R     (- b h + a g + d f + c e)e  + (a h + b g - c f + d e)e e
+--R                               2                           1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 17
+
+--S 18 of 36
+y * x
+--R 
+--R
+--R   (11)
+--R     - d h - c g - b f + a e + (- c h + d g + a f + b e)e
+--R                                                         1
+--R   + 
+--R     (b h + a g - d f + c e)e  + (a h - b g + c f + d e)e e
+--R                             2                           1 2
+--R                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+--E 18
+)clear all
+ 
+--S 19 of 36
+K := Fraction Polynomial Integer
+--R 
+--R
+--R   (1)  Fraction Polynomial Integer
+--R                                                                 Type: Domain
+--E 19
+
+--S 20 of 36
+Ext := CliffordAlgebra(3, K, quadraticForm 0)
+--R 
+--R
+--R   (2)  CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--R                                                                 Type: Domain
+--E 20
+
+--S 21 of 36
+i: Ext := e(1)
+--R 
+--R
+--R   (3)  e
+--R         1
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 21
+
+--S 22 of 36
+j: Ext := e(2)
+--R 
+--R
+--R   (4)  e
+--R         2
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 22
+
+--S 23 of 36
+k: Ext := e(3)
+--R 
+--R
+--R   (5)  e
+--R         3
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 23
+
+--S 24 of 36
+x := x1*i + x2*j + x3*k
+--R 
+--R
+--R   (6)  x1 e  + x2 e  + x3 e
+--R            1       2       3
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 24
+
+--S 25 of 36
+y := y1*i + y2*j + y3*k
+--R 
+--R
+--R   (7)  y1 e  + y2 e  + y3 e
+--R            1       2       3
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 25
+
+--S 26 of 36
+x + y
+--R 
+--R
+--R   (8)  (y1 + x1)e  + (y2 + x2)e  + (y3 + x3)e
+--R                  1             2             3
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 26
+
+--S 27 of 36
+x * y + y * x
+--R 
+--R
+--R   (9)  0
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 27
+
+--S 28 of 36
+dual2 a == coefficient(a,[2,3]) * i + coefficient(a,[3,1]) * j + coefficient(a,[1,2]) * k 
+--R 
+--R                                                                   Type: Void
+--E 28
+
+--S 29 of 36
+dual2(x*y)
+--R 
+--R   Compiling function dual2 with type CliffordAlgebra(3,Fraction 
+--R      Polynomial Integer,MATRIX) -> CliffordAlgebra(3,Fraction 
+--R      Polynomial Integer,MATRIX) 
+--R
+--R   (11)  (x2 y3 - x3 y2)e  + (- x1 y3 + x3 y1)e  + (x1 y2 - x2 y1)e
+--R                         1                     2                   3
+--R                  Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+--E 29
+)clear all
+ 
+--S 30 of 36
+K := Fraction Integer
+--R 
+--R
+--R   (1)  Fraction Integer
+--R                                                                 Type: Domain
+--E 30
+
+--S 31 of 36
+g := matrix [ [1,0,0,0], [0,-1,0,0], [0,0,-1,0], [0,0,0,-1] ]
+--R 
+--R
+--R        +1   0    0    0 +
+--R        |                |
+--R        |0  - 1   0    0 |
+--R   (2)  |                |
+--R        |0   0   - 1   0 |
+--R        |                |
+--R        +0   0    0   - 1+
+--R                                                         Type: Matrix Integer
+--E 31
+
+--S 32 of 36
+D := CliffordAlgebra(4,K, quadraticForm g)
+--R 
+--R
+--R   (3)  CliffordAlgebra(4,Fraction Integer,MATRIX)
+--R                                                                 Type: Domain
+--E 32
+
+--S 33 of 36
+gam := [e(i)$D for i in 1..4]
+--R 
+--R
+--R   (4)  [e ,e ,e ,e ]
+--R          1  2  3  4
+--R                        Type: List CliffordAlgebra(4,Fraction Integer,MATRIX)
+--E 33
+
+--S 34 of 36
+m := 1; n:= 2; r := 3; s := 4;
+--R 
+--R
+--R                                                        Type: PositiveInteger
+--E 34
+
+--S 35 of 36
+lhs := reduce(+, [reduce(+, [ g(l,t)*gam(l)*gam(m)*gam(n)*gam(r)*gam(s)*gam(t) for l in 1..4]) for t in 1..4])
+--R 
+--R
+--R   (6)  - 4e e e e
+--R            1 2 3 4
+--R                             Type: CliffordAlgebra(4,Fraction Integer,MATRIX)
+--E 35
+
+--S 36 of 36
+rhs := 2*(gam s * gam m*gam n*gam r + gam r*gam n*gam m*gam s) 
+--R 
+--R
+--R   (7)  - 4e e e e
+--R            1 2 3 4
+--R                             Type: CliffordAlgebra(4,Fraction Integer,MATRIX)
+--E 36
+)spool
+)lisp (bye)
+@
+<<CliffordAlgebra.help>>=
+====================================================================
+CliffordAlgebra examples
+====================================================================
+
+CliffordAlgebra(n,K,Q) defines a vector space of dimension 2^n over
+the field K with a given quadratic form Q.  If {e1..en} is a basis for
+K^n then
+
+
+{ 1,
+  e(i)         1 <= i <= n,
+  e(i1)*e(i2)  1 <= i1 < i2 <=n,
+  ...,
+  e(1)*e(2)*...*e(n) }
+
+is a basis for the Clifford algebra. The algebra is defined by the relations
+
+  e(i)*e(i) = Q(e(i))
+  e(i)*e(j) = -e(j)*e(i),  for i ^= j
+
+Examples of Clifford Algebras are gaussians (complex numbers),
+quaternions, exterior algebras and spin algebras.
+
+====================================================================
+The Complex Numbers as a Clifford Algebra
+====================================================================
+
+This is the field over which we will work, rational functions with
+integer coefficients.
+
+  K := Fraction Polynomial Integer
+   Fraction Polynomial Integer
+                         Type: Domain
+
+We use this matrix for the quadratic form.
+
+  m := matrix [ [-1] ]
+   [- 1]
+                         Type: Matrix Integer
+
+We get complex arithmetic by using this domain.
+
+  C := CliffordAlgebra(1, K, quadraticForm m)
+   CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+                         Type: Domain
+
+Here is i, the usual square root of -1.
+
+  i: C := e(1)
+   e
+    1
+               Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+
+Here are some examples of the arithmetic.
+
+  x := a + b * i
+   a + b e
+          1
+               Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+
+  y := c + d * i
+   c + d e
+          1
+               Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+
+  x * y
+   - b d + a c + (a d + b c)e
+                             1
+               Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
+
+====================================================================
+The Quaternion Numbers as a Clifford Algebra
+====================================================================
+
+This is the field over which we will work, rational functions with
+integer coefficients.
+
+  K := Fraction Polynomial Integer
+   Fraction Polynomial Integer
+                      Type: Domain
+
+We use this matrix for the quadratic form.
+
+  m := matrix [ [-1,0],[0,-1] ]
+   +- 1   0 +
+   |        |
+   + 0   - 1+
+                      Type: Matrix Integer
+
+The resulting domain is the quaternions.
+
+  H  := CliffordAlgebra(2, K, quadraticForm m)
+   CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+                      Type: Domain
+
+We use Hamilton's notation for i, j, k.
+
+  i: H  := e(1)
+   e
+    1
+              Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+  j: H  := e(2)
+   e
+    2
+              Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+  k: H  := i * j
+   e e
+    1 2
+              Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+  x := a + b * i + c * j + d * k
+   a + b e  + c e  + d e e
+          1      2      1 2
+              Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+  y := e + f * i + g * j + h * k 
+   e + f e  + g e  + h e e
+          1      2      1 2
+              Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+  x + y
+   e + a + (f + b)e  + (g + c)e  + (h + d)e e
+                   1           2           1 2
+              Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+  x * y
+   - d h - c g - b f + a e + (c h - d g + a f + b e)e
+                                                     1
+   + 
+     (- b h + a g + d f + c e)e  + (a h + b g - c f + d e)e e
+                               2                           1 2
+              Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+  y * x
+   - d h - c g - b f + a e + (- c h + d g + a f + b e)e
+                                                       1
+   + 
+     (b h + a g - d f + c e)e  + (a h - b g + c f + d e)e e
+                             2                           1 2
+                  Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
+
+====================================================================
+The Exterior Algebra on a Three Space
+====================================================================
+
+This is the field over which we will work, rational functions with
+integer coefficients.
+
+  K := Fraction Polynomial Integer
+   Fraction Polynomial Integer
+                  Type: Domain
+
+If we chose the three by three zero quadratic form, we obtain
+the exterior algebra on e(1),e(2),e(3).
+
+  Ext := CliffordAlgebra(3, K, quadraticForm 0)
+   CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+                  Type: Domain
+
+This is a three dimensional vector algebra.  We define i, j, k as the
+unit vectors.
+
+  i: Ext := e(1)
+   e
+    1
+             Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+  j: Ext := e(2)
+   e
+    2
+             Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+  k: Ext := e(3)
+   e
+    3
+             Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+Now it is possible to do arithmetic.
+
+  x := x1*i + x2*j + x3*k
+   x1 e  + x2 e  + x3 e
+       1       2       3
+             Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+  y := y1*i + y2*j + y3*k
+   y1 e  + y2 e  + y3 e
+       1       2       3
+             Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+  x + y
+   (y1 + x1)e  + (y2 + x2)e  + (y3 + x3)e
+             1             2             3
+             Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+  x * y + y * x
+   0
+             Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+On an n space, a grade p form has a dual n-p form.  In particular, in
+three space the dual of a grade two element identifies 
+ 
+  e1*e2 -> e3, e2*e3 -> e1, e3*e1 -> e2.
+
+  dual2 a == coefficient(a,[2,3]) * i + coefficient(a,[3,1]) * j + coefficient(a,[1,2]) * k 
+                      Type: Void
+
+The vector cross product is then given by this.
+
+  dual2(x*y)
+   (x2 y3 - x3 y2)e  + (- x1 y3 + x3 y1)e  + (x1 y2 - x2 y1)e
+                   1                     2                   3
+           Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
+
+====================================================================
+The Dirac Spin Algebra
+====================================================================
+
+In this section we will work over the field of rational numbers.
+
+  K := Fraction Integer
+   Fraction Integer
+                       Type: Domain
+
+We define the quadratic form to be the Minkowski space-time metric.
+
+  g := matrix [ [1,0,0,0], [0,-1,0,0], [0,0,-1,0], [0,0,0,-1] ]
+   +1   0    0    0 +
+   |                |
+   |0  - 1   0    0 |
+   |                |
+   |0   0   - 1   0 |
+   |                |
+   +0   0    0   - 1+
+                       Type: Matrix Integer
+
+We obtain the Dirac spin algebra used in Relativistic Quantum Field Theory.
+
+  D := CliffordAlgebra(4,K, quadraticForm g)
+   CliffordAlgebra(4,Fraction Integer,MATRIX)
+                       Type: Domain
+
+The usual notation for the basis is gamma with a superscript.  For
+Axiom input we will use gam(i):
+
+  gam := [e(i)$D for i in 1..4]
+   [e ,e ,e ,e ]
+     1  2  3  4
+                 Type: List CliffordAlgebra(4,Fraction Integer,MATRIX)
+
+There are various contraction identities of the form
+
+  g(l,t)*gam(l)*gam(m)*gam(n)*gam(r)*gam(s)*gam(t) =
+      2*(gam(s)gam(m)gam(n)gam(r) + gam(r)*gam(n)*gam(m)*gam(s))
+
+where a sum over l and t is implied.
+
+Verify this identity for particular values of m,n,r,s.
+
+  m := 1; n:= 2; r := 3; s := 4;
+                      Type: PositiveInteger
+
+  lhs := reduce(+, [reduce(+, [ g(l,t)*gam(l)*gam(m)*gam(n)*gam(r)*gam(s)*gam(t) for l in 1..4]) for t in 1..4])
+   - 4e e e e
+       1 2 3 4
+                      Type: CliffordAlgebra(4,Fraction Integer,MATRIX)
+
+  rhs := 2*(gam s * gam m*gam n*gam r + gam r*gam n*gam m*gam s) 
+   - 4e e e e
+       1 2 3 4
+                      Type: CliffordAlgebra(4,Fraction Integer,MATRIX)
+
+See Also:
+o )help Complex
+o )help Quaternion
+o )show CliffordAlgebra
+o $AXIOM/doc/src/algebra/clifford.spad
+
+@
 <<domain CLIF CliffordAlgebra>>=
 )abbrev domain CLIF CliffordAlgebra
 ++ Author: Stephen M. Watt
diff --git a/src/algebra/contfrac.spad.pamphlet b/src/algebra/contfrac.spad.pamphlet
index 2261d76..d6c24af 100644
--- a/src/algebra/contfrac.spad.pamphlet
+++ b/src/algebra/contfrac.spad.pamphlet
@@ -2,7 +2,7 @@
 \usepackage{axiom}
 \begin{document}
 \title{\$SPAD/src/algebra contfrac.spad}
-\author{Stephen M. Watt, Clifton J. Williamson}
+\author{Stephen M. Watt, Clifton J. Williamson, Timothy Daly}
 \maketitle
 \begin{abstract}
 \end{abstract}
@@ -10,6 +10,550 @@
 \tableofcontents
 \eject
 \section{domain CONTFRAC ContinuedFraction}
+<<ContinuedFraction.input>>=
+-- contfrac.spad.pamphlet ContinuedFraction.input
+)spool ContinuedFraction.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 22
+c := continuedFraction(314159/100000)
+--R 
+--R
+--R              1 |     1  |     1 |     1  |     1 |     1 |     1 |
+--R   (1)  3 + +---+ + +----+ + +---+ + +----+ + +---+ + +---+ + +---+
+--R            | 7     | 15     | 1     | 25     | 1     | 7     | 4
+--R                                              Type: ContinuedFraction Integer
+--E 1
+
+--S 2 of 22
+partialQuotients c
+--R 
+--R
+--R   (2)  [3,7,15,1,25,1,7,4]
+--R                                                         Type: Stream Integer
+--E 2
+
+--S 3 of 22
+convergents c
+--R 
+--R
+--R           22 333 355 9208 9563 76149 314159
+--R   (3)  [3,--,---,---,----,----,-----,------]
+--R            7 106 113 2931 3044 24239 100000
+--R                                                Type: Stream Fraction Integer
+--E 3
+
+--S 4 of 22
+approximants c
+--R 
+--R
+--R                                      ______
+--R           22 333 355 9208 9563 76149 314159
+--R   (4)  [3,--,---,---,----,----,-----,------]
+--R            7 106 113 2931 3044 24239 100000
+--R                                                Type: Stream Fraction Integer
+--E 4
+
+--S 5 of 22
+pq := partialQuotients(1/c)
+--R 
+--R
+--R   (5)  [0,3,7,15,1,25,1,7,4]
+--R                                                         Type: Stream Integer
+--E 5
+
+--S 6 of 22
+continuedFraction(first pq,repeating [1],rest pq)
+--R 
+--R
+--R          1 |     1 |     1  |     1 |     1  |     1 |     1 |     1 |
+--R   (6)  +---+ + +---+ + +----+ + +---+ + +----+ + +---+ + +---+ + +---+
+--R        | 3     | 7     | 15     | 1     | 25     | 1     | 7     | 4
+--R                                              Type: ContinuedFraction Integer
+--E 6
+
+--S 7 of 22
+z:=continuedFraction(3,repeating [1],repeating [3,6])
+--R 
+--R
+--R   (7)
+--R           1 |     1 |     1 |     1 |     1 |     1 |     1 |     1 |     1 |
+--R     3 + +---+ + +---+ + +---+ + +---+ + +---+ + +---+ + +---+ + +---+ + +---+
+--R         | 3     | 6     | 3     | 6     | 3     | 6     | 3     | 6     | 3
+--R   + 
+--R       1 |
+--R     +---+ + ...
+--R     | 6
+--R                                              Type: ContinuedFraction Integer
+--E 7
+
+--S 8 of 22
+dens:Stream Integer := cons(1,generate((x+->x+4),6))
+--R 
+--R
+--R   (8)  [1,6,10,14,18,22,26,30,34,38,...]
+--R                                                         Type: Stream Integer
+--E 8
+
+--S 9 of 22
+cf := continuedFraction(0,repeating [1],dens)
+--R 
+--R
+--R   (9)
+--R       1 |     1 |     1  |     1  |     1  |     1  |     1  |     1  |
+--R     +---+ + +---+ + +----+ + +----+ + +----+ + +----+ + +----+ + +----+
+--R     | 1     | 6     | 10     | 14     | 18     | 22     | 26     | 30
+--R   + 
+--R       1  |     1  |
+--R     +----+ + +----+ + ...
+--R     | 34     | 38
+--R                                              Type: ContinuedFraction Integer
+--E 9
+
+--S 10 of 22
+ccf := convergents cf
+--R 
+--R
+--R              6 61  860 15541 342762  8927353 268163352  9126481321
+--R   (10)  [0,1,-,--,----,-----,------,--------,---------,-----------,...]
+--R              7 71 1001 18089 398959 10391023 312129649 10622799089
+--R                                                Type: Stream Fraction Integer
+--E 10
+
+--S 11 of 22
+eConvergents := [2*e + 1 for e in ccf]
+--R 
+--R
+--R              19 193 2721 49171 1084483 28245729 848456353 28875761731
+--R   (11)  [1,3,--,---,----,-----,-------,--------,---------,-----------,...]
+--R               7  71 1001 18089  398959 10391023 312129649 10622799089
+--R                                                Type: Stream Fraction Integer
+--E 11
+
+--S 12 of 22
+eConvergents :: Stream Float
+--R 
+--R
+--R   (12)
+--R   [1.0, 3.0, 2.7142857142 857142857, 2.7183098591 549295775,
+--R    2.7182817182 817182817, 2.7182818287 356957267, 2.7182818284 585634113,
+--R    2.7182818284 590458514, 2.7182818284 590452348, 2.7182818284 590452354,
+--R    ...]
+--R                                                           Type: Stream Float
+--E 12
+
+--S 13 of 22
+exp 1.0
+--R 
+--R
+--R   (13)  2.7182818284 590452354
+--R                                                                  Type: Float
+--E 13
+
+--S 14 of 22
+cf := continuedFraction(1,[(2*i+1)**2 for i in 0..],repeating [2])
+--R 
+--R
+--R   (14)
+--R           1 |     9 |     25 |     49 |     81 |     121 |     169 |     225 |
+--R     1 + +---+ + +---+ + +----+ + +----+ + +----+ + +-----+ + +-----+ + +-----+
+--R         | 2     | 2     | 2      | 2      | 2      |  2      |  2      |  2
+--R   + 
+--R       289 |     361 |
+--R     +-----+ + +-----+ + ...
+--R     |  2      |  2
+--R                                              Type: ContinuedFraction Integer
+--E 14
+
+--S 15 of 22
+ccf := convergents cf
+--R 
+--R
+--R            3 15 105 315 3465 45045 45045 765765 14549535
+--R   (15)  [1,-,--,---,---,----,-----,-----,------,--------,...]
+--R            2 13  76 263 2578 36979 33976 622637 11064338
+--R                                                Type: Stream Fraction Integer
+--E 15
+
+--S 16 of 22
+piConvergents := [4/p for p in ccf] 
+--R 
+--R
+--R            8 52 304 1052 10312 147916 135904 2490548 44257352
+--R   (16)  [4,-,--,---,----,-----,------,------,-------,--------,...]
+--R            3 15 105  315  3465  45045  45045  765765 14549535
+--R                                                Type: Stream Fraction Integer
+--E 16
+
+--S 17 of 22
+piConvergents :: Stream Float
+--R 
+--R
+--R   (17)
+--R   [4.0, 2.6666666666 666666667, 3.4666666666 666666667,
+--R    2.8952380952 380952381, 3.3396825396 825396825, 2.9760461760 461760462,
+--R    3.2837384837 384837385, 3.0170718170 718170718, 3.2523659347 188758953,
+--R    3.0418396189 294022111, ...]
+--R                                                           Type: Stream Float
+--E 17
+
+--S 18 of 22
+continuedFraction((- 122 + 597*%i)/(4 - 4*%i))
+--R 
+--R
+--R                            1    |         1     |
+--R   (18)  - 90 + 59%i + +---------+ + +-----------+
+--R                       | 1 - 2%i     | - 1 + 2%i
+--R                                      Type: ContinuedFraction Complex Integer
+--E 18
+
+--S 19 of 22
+r : Fraction UnivariatePolynomial(x,Fraction Integer) 
+--R 
+--R                                                                   Type: Void
+--E 19
+
+--S 20 of 22
+r := ((x - 1) * (x - 2)) / ((x-3) * (x-4))
+--R 
+--R
+--R           2
+--R          x  - 3x + 2
+--R   (20)  ------------
+--R          2
+--R         x  - 7x + 12
+--R                      Type: Fraction UnivariatePolynomial(x,Fraction Integer)
+--E 20
+
+--S 21 of 22
+continuedFraction r 
+--R 
+--R
+--R                  1    |         1     |
+--R   (21)  1 + +---------+ + +-----------+
+--R             | 1     9     | 16     40
+--R             | - x - -     | -- x - --
+--R             | 4     8     |  3      3
+--R             Type: ContinuedFraction UnivariatePolynomial(x,Fraction Integer)
+--E 21
+
+--S 22 of 22
+[i*i for i in convergents(z) :: Stream Float] 
+--R 
+--R
+--R   (22)
+--R   [9.0, 11.1111111111 11111111, 10.9944598337 9501385, 11.0002777777 77777778,
+--R    10.9999860763 98799786, 11.0000006979 29731039, 10.9999999650 15834446,
+--R    11.0000000017 53603304, 10.9999999999 12099531, 11.0000000000 04406066,
+--R    ...]
+--R                                                           Type: Stream Float
+--E 22
+)spool
+)lisp (bye)
+@
+<<ContinuedFraction.help>>=
+====================================================================
+ContinuedFraction examples
+====================================================================
+
+Continued fractions have been a fascinating and useful tool in
+mathematics for well over three hundred years.  Axiom implements
+continued fractions for fractions of any Euclidean domain.  In
+practice, this usually means rational numbers.  In this section we
+demonstrate some of the operations available for manipulating both
+finite and infinite continued fractions.  
+
+The ContinuedFraction domain is a field and therefore you can add,
+subtract, multiply and divide the fractions.
+
+The continuedFraction operation converts its fractional argument to a
+continued fraction.
+
+  c := continuedFraction(314159/100000)
+         1 |     1  |     1 |     1  |     1 |     1 |     1 |
+   3 + +---+ + +----+ + +---+ + +----+ + +---+ + +---+ + +---+
+       | 7     | 15     | 1     | 25     | 1     | 7     | 4
+                        Type: ContinuedFraction Integer
+
+This display is a compact form of the bulkier
+
+        3 +                 1
+            -------------------------------
+            7 +               1
+                ---------------------------
+                15 +            1
+                     ----------------------
+                     1 +          1
+                         ------------------
+                         25 +       1
+                              -------------
+                              1 +     1
+                                  ---------
+                                  7 +   1
+                                      -----
+                                        4
+
+You can write any rational number in a similar form.  The fraction
+will be finite and you can always take the "numerators" to be 1.
+That is, any rational number can be written as a simple, finite
+continued fraction of the form
+
+        a(1) +           1
+               -------------------------
+               a(2) +          1
+                      --------------------
+                      a(3) +
+                             .
+                              .
+                               .
+                                     1
+                               -------------
+                               a(n-1) +  1
+                                        ----
+                                        a(n)
+
+
+The a(i) are called partial quotients and the operation partialQuotients 
+creates a stream of them.
+
+  partialQuotients c
+   [3,7,15,1,25,1,7,4]
+                        Type: Stream Integer
+
+By considering more and more of the fraction, you get the convergents.
+For example, the first convergent is a(1), the second is a(1) + 1/a(2)
+and so on.
+
+  convergents c
+      22 333 355 9208 9563 76149 314159
+   [3,--,---,---,----,----,-----,------]
+       7 106 113 2931 3044 24239 100000
+                         Type: Stream Fraction Integer
+
+Since this is a finite continued fraction, the last convergent is the
+original rational number, in reduced form.  The result of approximants
+is always an infinite stream, though it may just repeat the "last" value.
+
+  approximants c
+                                 ______
+      22 333 355 9208 9563 76149 314159
+   [3,--,---,---,----,----,-----,------]
+       7 106 113 2931 3044 24239 100000
+                         Type: Stream Fraction Integer
+
+Inverting c only changes the partial quotients of its fraction by
+inserting a 0 at the beginning of the list.
+
+  pq := partialQuotients(1/c)
+   [0,3,7,15,1,25,1,7,4]
+                         Type: Stream Integer
+
+Do this to recover the original continued fraction from this list of
+partial quotients.  The three-argument form of the continuedFraction
+operation takes an element which is the whole part of the fraction, a
+stream of elements which are the numerators of the fraction, and a
+stream of elements which are the denominators of the fraction.
+
+  continuedFraction(first pq,repeating [1],rest pq)
+     1 |     1 |     1  |     1 |     1  |     1 |     1 |     1 |
+   +---+ + +---+ + +----+ + +---+ + +----+ + +---+ + +---+ + +---+
+   | 3     | 7     | 15     | 1     | 25     | 1     | 7     | 4
+                         Type: ContinuedFraction Integer
+
+The streams need not be finite for continuedFraction.  Can you guess
+which irrational number has the following continued fraction?  See the
+end of this section for the answer.
+
+  z:=continuedFraction(3,repeating [1],repeating [3,6])
+           1 |     1 |     1 |     1 |     1 |     1 |     1 |     1 |     1 |
+     3 + +---+ + +---+ + +---+ + +---+ + +---+ + +---+ + +---+ + +---+ + +---+
+         | 3     | 6     | 3     | 6     | 3     | 6     | 3     | 6     | 3
+   + 
+       1 |
+     +---+ + ...
+     | 6
+                         Type: ContinuedFraction Integer
+
+In 1737 Euler discovered the infinite continued fraction expansion
+
+        e - 1             1
+        ----- = ---------------------
+          2     1 +         1
+                    -----------------
+                    6 +       1
+                        -------------
+                        10 +    1
+                             --------
+                             14 + ...
+
+
+We use this expansion to compute rational and floating point
+approximations of e. For this and other interesting expansions, see
+C. D. Olds, Continued Fractions, New Mathematical Library, (New York:
+Random House, 1963), pp.  134--139.}
+
+By looking at the above expansion, we see that the whole part is 0 and
+the numerators are all equal to 1.  This constructs the stream of
+denominators.
+
+  dens:Stream Integer := cons(1,generate((x+->x+4),6))
+   [1,6,10,14,18,22,26,30,34,38,...]
+                        Type: Stream Integer
+
+Therefore this is the continued fraction expansion for (e - 1) / 2.
+
+  cf := continuedFraction(0,repeating [1],dens)
+       1 |     1 |     1  |     1  |     1  |     1  |     1  |     1  |
+     +---+ + +---+ + +----+ + +----+ + +----+ + +----+ + +----+ + +----+
+     | 1     | 6     | 10     | 14     | 18     | 22     | 26     | 30
+   + 
+       1  |     1  |
+     +----+ + +----+ + ...
+     | 34     | 38
+                    Type: ContinuedFraction Integer
+
+These are the rational number convergents.
+
+  ccf := convergents cf
+        6 61  860 15541 342762  8927353 268163352  9126481321
+   [0,1,-,--,----,-----,------,--------,---------,-----------,...]
+        7 71 1001 18089 398959 10391023 312129649 10622799089
+                    Type: Stream Fraction Integer
+
+You can get rational convergents for e by multiplying by 2 and adding 1.
+
+  eConvergents := [2*e + 1 for e in ccf]
+         19 193 2721 49171 1084483 28245729 848456353 28875761731
+    [1,3,--,---,----,-----,-------,--------,---------,-----------,...]
+          7  71 1001 18089  398959 10391023 312129649 10622799089
+                    Type: Stream Fraction Integer
+
+You can also compute the floating point approximations to these convergents.
+
+  eConvergents :: Stream Float
+   [1.0, 3.0, 2.7142857142 857142857, 2.7183098591 549295775,
+    2.7182817182 817182817, 2.7182818287 356957267, 2.7182818284 585634113,
+    2.7182818284 590458514, 2.7182818284 590452348, 2.7182818284 590452354,
+    ...]
+                       Type: Stream Float
+
+Compare this to the value of e computed by the exp operation in Float.
+
+  exp 1.0
+   2.7182818284 590452354
+                       Type: Float
+
+In about 1658, Lord Brouncker established the following expansion
+for 4 / pi,
+
+        1 +            1
+            -----------------------
+            2 +          9
+                -------------------
+                2 +        25
+                    ---------------
+                    2 +      49
+                        -----------
+                        2 +    81
+                            -------
+                            2 + ...
+
+Let's use this expansion to compute rational and floating point
+approximations for pi.
+
+  cf := continuedFraction(1,[(2*i+1)**2 for i in 0..],repeating [2])
+           1 |     9 |     25 |     49 |     81 |     121 |     169 |     225 |
+     1 + +---+ + +---+ + +----+ + +----+ + +----+ + +-----+ + +-----+ + +-----+
+         | 2     | 2     | 2      | 2      | 2      |  2      |  2      |  2
+   + 
+       289 |     361 |
+     +-----+ + +-----+ + ...
+     |  2      |  2
+                       Type: ContinuedFraction Integer
+
+  ccf := convergents cf
+      3 15 105 315 3465 45045 45045 765765 14549535
+   [1,-,--,---,---,----,-----,-----,------,--------,...]
+      2 13  76 263 2578 36979 33976 622637 11064338
+                       Type: Stream Fraction Integer
+
+  piConvergents := [4/p for p in ccf] 
+      8 52 304 1052 10312 147916 135904 2490548 44257352
+   [4,-,--,---,----,-----,------,------,-------,--------,...]
+      3 15 105  315  3465  45045  45045  765765 14549535
+                       Type: Stream Fraction Integer
+
+As you can see, the values are converging to
+pi = 3.14159265358979323846..., but not very quickly.
+
+  piConvergents :: Stream Float
+   [4.0, 2.6666666666 666666667, 3.4666666666 666666667,
+    2.8952380952 380952381, 3.3396825396 825396825, 2.9760461760 461760462,
+    3.2837384837 384837385, 3.0170718170 718170718, 3.2523659347 188758953,
+    3.0418396189 294022111, ...]
+                      Type: Stream Float
+
+You need not restrict yourself to continued fractions of integers.
+Here is an expansion for a quotient of Gaussian integers.
+
+  continuedFraction((- 122 + 597*%i)/(4 - 4*%i))
+                      1    |         1     |
+   - 90 + 59%i + +---------+ + +-----------+
+                 | 1 - 2%i     | - 1 + 2%i
+                      Type: ContinuedFraction Complex Integer
+
+This is an expansion for a quotient of polynomials in one variable
+with rational number coefficients.
+
+  r : Fraction UnivariatePolynomial(x,Fraction Integer) 
+                      Type: Void
+
+  r := ((x - 1) * (x - 2)) / ((x-3) * (x-4))
+     2
+    x  - 3x + 2
+   ------------
+    2
+   x  - 7x + 12
+                      Type: Fraction UnivariatePolynomial(x,Fraction Integer)
+
+  continuedFraction r 
+            1    |         1     |
+   1 + +---------+ + +-----------+
+       | 1     9     | 16     40
+       | - x - -     | -- x - --
+       | 4     8     |  3      3
+             Type: ContinuedFraction UnivariatePolynomial(x,Fraction Integer)
+
+To conclude this section, we give you evidence that
+
+    z = 3 +            1
+            -----------------------
+            3 +          1
+                -------------------
+                6 +        1
+                    ---------------
+                    3 +      1
+                        -----------
+                        6 +    1
+                            -------
+                            3 + ...
+
+is the expansion of sqrt(11).
+
+  [i*i for i in convergents(z) :: Stream Float] 
+   [9.0, 11.1111111111 11111111, 10.9944598337 9501385, 11.0002777777 77777778,
+    10.9999860763 98799786, 11.0000006979 29731039, 10.9999999650 15834446,
+    11.0000000017 53603304, 10.9999999999 12099531, 11.0000000000 04406066,
+    ...]
+                        Type: Stream Float
+
+See Also:
+o )help Stream
+o )show ContinuedFraction
+o $AXIOM/doc/src/algebra/contrac.spad.dvi
+
+@
 <<domain CONTFRAC ContinuedFraction>>=
 )abbrev domain CONTFRAC ContinuedFraction
 ++ Author: Stephen M. Watt
diff --git a/src/algebra/cycles.spad.pamphlet b/src/algebra/cycles.spad.pamphlet
index d5747f5..c831683 100644
--- a/src/algebra/cycles.spad.pamphlet
+++ b/src/algebra/cycles.spad.pamphlet
@@ -10,6 +10,913 @@
 \tableofcontents
 \eject
 \section{package CYCLES CycleIndicators}
+<<CycleIndicators.input>>=
+-- cycles.spad.pamphlet CycleIndicators.input
+)spool CycleIndicators.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 47
+complete 1
+--R 
+--R
+--R   (1)  (1)
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 1
+
+--S 2 of 47
+complete 2
+--R 
+--R
+--R        1       1   2
+--R   (2)  - (2) + - (1 )
+--R        2       2
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 2
+
+--S 3 of 47
+complete 3
+--R 
+--R
+--R        1       1         1   3
+--R   (3)  - (3) + - (2 1) + - (1 )
+--R        3       2         6
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 3
+
+--S 4 of 47
+complete 7
+--R 
+--R
+--R   (4)
+--R     1       1          1          1     2     1         1            1     3
+--R     - (7) + - (6 1) + -- (5 2) + -- (5 1 ) + -- (4 3) + - (4 2 1) + -- (4 1 )
+--R     7       6         10         10          12         8           24
+--R   + 
+--R      1   2      1     2     1       2     1     4     1   3      1   2 3
+--R     -- (3 1) + -- (3 2 ) + -- (3 2 1 ) + -- (3 1 ) + -- (2 1) + -- (2 1 )
+--R     18         24          12            72          48         48
+--R   + 
+--R      1      5      1    7
+--R     --- (2 1 ) + ---- (1 )
+--R     240          5040
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 4
+
+--S 5 of 47
+elementary 7
+--R 
+--R
+--R   (5)
+--R     1       1          1          1     2     1         1            1     3
+--R     - (7) - - (6 1) - -- (5 2) + -- (5 1 ) - -- (4 3) + - (4 2 1) - -- (4 1 )
+--R     7       6         10         10          12         8           24
+--R   + 
+--R      1   2      1     2     1       2     1     4     1   3      1   2 3
+--R     -- (3 1) + -- (3 2 ) - -- (3 2 1 ) + -- (3 1 ) - -- (2 1) + -- (2 1 )
+--R     18         24          12            72          48         48
+--R   + 
+--R        1      5      1    7
+--R     - --- (2 1 ) + ---- (1 )
+--R       240          5040
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 5
+
+--S 6 of 47
+alternating 7
+--R 
+--R
+--R   (6)
+--R     2       1     2    1           1   2      1     2     1     4     1   2 3
+--R     - (7) + - (5 1 ) + - (4 2 1) + - (3 1) + -- (3 2 ) + -- (3 1 ) + -- (2 1 )
+--R     7       5          4           9         12          36          24
+--R   + 
+--R       1    7
+--R     ---- (1 )
+--R     2520
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 6
+
+--S 7 of 47
+cyclic 7
+--R 
+--R
+--R        6       1   7
+--R   (7)  - (7) + - (1 )
+--R        7       7
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 7
+
+--S 8 of 47
+dihedral 7
+--R 
+--R
+--R        3       1   3      1   7
+--R   (8)  - (7) + - (2 1) + -- (1 )
+--R        7       2         14
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 8
+
+--S 9 of 47
+graphs 5
+--R 
+--R
+--R   (9)
+--R   1           1   2    1   2     1   3     1   4 2     1   3 4     1    10
+--R   - (6 3 1) + - (5 ) + - (4 2) + - (3 1) + - (2 1 ) + -- (2 1 ) + --- (1  )
+--R   6           5        4         6         8          12          120
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 9
+
+--S 10 of 47
+cap(complete 2**2, complete 2*complete 1**2)
+--R 
+--R
+--R   (10)  4
+--R                                                       Type: Fraction Integer
+--E 10
+
+--S 11 of 47
+cap(elementary 2**2, complete 2*complete 1**2)
+--R 
+--R
+--R   (11)  2
+--R                                                       Type: Fraction Integer
+--E 11
+
+--S 12 of 47
+cap(complete 3*complete 2*complete 1,complete 2**2*complete 1**2)
+--R 
+--R
+--R   (12)  24
+--R                                                       Type: Fraction Integer
+--E 12
+
+--S 13 of 47
+cap(elementary 3*elementary 2*elementary 1,complete 2**2*complete 1**2)
+--R 
+--R
+--R   (13)  8
+--R                                                       Type: Fraction Integer
+--E 13
+
+--S 14 of 47
+cap(complete 3*complete 2*complete 1,elementary 2**2*elementary 1**2)
+--R 
+--R
+--R   (14)  8
+--R                                                       Type: Fraction Integer
+--E 14
+
+--S 15 of 47
+eval(cup(complete 3*complete 2*complete 1, cup(complete 2**2*complete 1**2,complete 2**3)))
+--R 
+--R
+--R   (15)  1500
+--R                                                       Type: Fraction Integer
+--E 15
+
+--S 16 of 47
+square:=dihedral 4
+--R 
+--R
+--R         1       3   2    1     2    1   4
+--R   (16)  - (4) + - (2 ) + - (2 1 ) + - (1 )
+--R         4       8        4          8
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 16
+
+--S 17 of 47
+cap(complete 2**2,square)
+--R 
+--R
+--R   (17)  2
+--R                                                       Type: Fraction Integer
+--E 17
+
+--S 18 of 47
+cap(complete 3*complete 2**2,dihedral 7)
+--R 
+--R
+--R   (18)  18
+--R                                                       Type: Fraction Integer
+--E 18
+
+--S 19 of 47
+cap(graphs 5,complete 7*complete 3)
+--R 
+--R
+--R   (19)  4
+--R                                                       Type: Fraction Integer
+--E 19
+
+--S 20 of 47
+s(x) == powerSum(x)
+--R 
+--R                                                                   Type: Void
+--E 20
+
+--S 21 of 47
+cube:=(1/24)*(s 1**8+9*s 2**4 + 8*s 3**2*s 1**2+6*s 4**2)
+--R 
+--R   Compiling function s with type PositiveInteger -> 
+--R      SymmetricPolynomial Fraction Integer 
+--R
+--R         1   2    1   2 2    3   4     1   8
+--R   (21)  - (4 ) + - (3 1 ) + - (2 ) + -- (1 )
+--R         4        3          8        24
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 21
+
+--S 22 of 47
+cap(complete 4**2,cube)
+--R 
+--R
+--R   (22)  7
+--R                                                       Type: Fraction Integer
+--E 22
+
+--S 23 of 47
+cap(complete 2**3*complete 1**2,wreath(elementary 4,elementary 2))
+--R 
+--R
+--R   (23)  7
+--R                                                       Type: Fraction Integer
+--E 23
+
+--S 24 of 47
+cap(complete 2**3*complete 1**2,wreath(elementary 4,complete 2))
+--R 
+--R
+--R   (24)  17
+--R                                                       Type: Fraction Integer
+--E 24
+
+--S 25 of 47
+cap(complete 2**3*complete 1**2,wreath(complete 4,elementary 2))
+--R 
+--R
+--R   (25)  10
+--R                                                       Type: Fraction Integer
+--E 25
+
+--S 26 of 47
+cap(complete 2**3*complete 1**2,wreath(complete 4,complete 2))
+--R 
+--R
+--R   (26)  23
+--R                                                       Type: Fraction Integer
+--E 26
+
+--S 27 of 47
+x: ULS(FRAC INT,'x,0) := 'x 
+--R 
+--R
+--R   (27)  x
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 27
+
+--S 28 of 47
+ZeroOrOne: INT -> ULS(FRAC INT, 'x, 0) 
+--R 
+--R                                                                   Type: Void
+--E 28
+
+--S 29 of 47
+Integers: INT -> ULS(FRAC INT, 'x, 0) 
+--R 
+--R                                                                   Type: Void
+--E 29
+
+--S 30 of 47
+ZeroOrOne n == 1+x**n
+--R 
+--R                                                                   Type: Void
+--E 30
+
+--S 31 of 47
+ZeroOrOne 5 
+--R 
+--R   Compiling function ZeroOrOne with type Integer -> 
+--R      UnivariateLaurentSeries(Fraction Integer,x,0) 
+--R
+--R              5
+--R   (31)  1 + x
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 31
+
+--S 32 of 47
+Integers n == 1/(1-x**n) 
+--R 
+--R                                                                   Type: Void
+--E 32
+
+--S 33 of 47
+Integers 5 
+--R 
+--R   Compiling function Integers with type Integer -> 
+--R      UnivariateLaurentSeries(Fraction Integer,x,0) 
+--R
+--R              5    10      11
+--R   (33)  1 + x  + x   + O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 33
+
+--S 34 of 47
+)expose EVALCYC
+--R 
+--I   EvaluateCycleIndicators is now explicitly exposed in frame frame0 
+--E 34
+
+--S 35 of 47
+eval(ZeroOrOne, graphs 5) 
+--R 
+--R
+--R                   2     3     4     5     6     7     8    9    10      11
+--R   (34)  1 + x + 2x  + 4x  + 6x  + 6x  + 6x  + 4x  + 2x  + x  + x   + O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 35
+
+--S 36 of 47
+eval(ZeroOrOne,dihedral 8) 
+--R 
+--R
+--R                   2     3     4     5     6    7    8
+--R   (35)  1 + x + 4x  + 5x  + 8x  + 5x  + 4x  + x  + x
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 36
+
+--S 37 of 47
+eval(Integers,complete 4) 
+--R 
+--R
+--R   (36)
+--R             2     3     4     5     6      7      8      9      10      11
+--R   1 + x + 2x  + 3x  + 5x  + 6x  + 9x  + 11x  + 15x  + 18x  + 23x   + O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 37
+
+--S 38 of 47
+eval(Integers,elementary 4)
+--R 
+--R
+--R   (37)
+--R      6    7     8     9     10     11     12      13      14      15      16
+--R     x  + x  + 2x  + 3x  + 5x   + 6x   + 9x   + 11x   + 15x   + 18x   + 23x
+--R   + 
+--R        17
+--R     O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 38
+
+--S 39 of 47
+eval(ZeroOrOne,cube) 
+--R 
+--R
+--R                   2     3     4     5     6    7    8
+--R   (38)  1 + x + 3x  + 3x  + 7x  + 3x  + 3x  + x  + x
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 39
+
+--S 40 of 47
+eval(Integers,cube) 
+--R 
+--R
+--R   (39)
+--R               2     3      4      5      6       7       8       9       10
+--R     1 + x + 4x  + 7x  + 21x  + 37x  + 85x  + 151x  + 292x  + 490x  + 848x
+--R   + 
+--R        11
+--R     O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 40
+
+--S 41 of 47
+eval(Integers,graphs 5) 
+--R 
+--R
+--R   (40)
+--R               2     3      4      5      6       7       8       9       10
+--R     1 + x + 3x  + 7x  + 17x  + 35x  + 76x  + 149x  + 291x  + 539x  + 974x
+--R   + 
+--R        11
+--R     O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 41
+
+--S 42 of 47
+eval(ZeroOrOne ,graphs 15) 
+--R 
+--R
+--R   (41)
+--R               2     3      4      5      6       7       8        9        10
+--R     1 + x + 2x  + 5x  + 11x  + 26x  + 68x  + 177x  + 496x  + 1471x  + 4583x
+--R   + 
+--R        11
+--R     O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 42
+
+--S 43 of 47
+cap(dihedral 30,complete 7*complete 8*complete 5*complete 10)
+--R 
+--R
+--R   (42)  49958972383320
+--R                                                       Type: Fraction Integer
+--E 43
+
+--S 44 of 47
+sf3221:= SFunction [3,2,2,1] 
+--R 
+--R
+--R   (43)
+--R      1          1     2     1   2     1            1     4     1   2
+--R     -- (6 2) - -- (6 1 ) - -- (4 ) + -- (4 3 1) + -- (4 1 ) - -- (3 2)
+--R     12         12          16        12           24          36
+--R   + 
+--R      1   2 2     1     2      1       3     1     5     1    4     1   3 2
+--R     -- (3 1 ) - -- (3 2 1) - -- (3 2 1 ) - -- (3 1 ) - --- (2 ) + -- (2 1 )
+--R     36          24           36            72          192        48
+--R   + 
+--R      1   2 4     1      6     1    8
+--R     -- (2 1 ) - --- (2 1 ) + --- (1 )
+--R     96          144          576
+--R                                   Type: SymmetricPolynomial Fraction Integer
+--E 44
+
+--S 45 of 47
+cap(sf3221,complete 2**4) 
+--R 
+--R
+--R   (44)  3
+--R                                                       Type: Fraction Integer
+--E 45
+
+--S 46 of 47
+cap(sf3221, powerSum 1**8)
+--R 
+--R
+--R   (45)  70
+--R                                                       Type: Fraction Integer
+--E 46
+
+--S 47 of 47
+eval(Integers, sf3221)
+--R 
+--R
+--R   (46)
+--R      9     10     11      12      13      14      15       16       17       18
+--R     x  + 3x   + 7x   + 14x   + 27x   + 47x   + 79x   + 126x   + 196x   + 294x
+--R   + 
+--R         19      20
+--R     432x   + O(x  )
+--R                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+--E 47
+)spool
+)lisp (bye)
+@
+<<CycleIndicators.help>>=
+====================================================================
+\section{CycleIndicators}
+\label{CycleIndicatorsXmpPage}
+
+This section is based upon the paper J. H. Redfield, ``The Theory of
+Group-Reduced Distributions'', American J. Math.,49 (1927) 433-455,
+and is an application of group theory to enumeration problems.  It is
+a development of the work by P. A. MacMahon on the application of
+symmetric functions and Hammond operators to combinatorial theory.
+
+The theory is based upon the power sum symmetric functions s(i) which
+are the sum of the i-th powers of the variables.  The cycle index of a
+permutation is an expression that specifies the sizes of the cycles of
+a permutation, and may be represented as a partition.  A partition of
+a non-negative integer n is a collection of positive integers called
+its parts whose sum is n.  For example, the partition (3^2 2 1^2) will
+be used to represent s^2_3 s_2 s^2_1 and will indicate that the
+permutation has two cycles of length 3, one of length 2 and two of
+length 1.  The cycle index of a permutation group is the sum of the
+cycle indices of its permutations divided by the number of
+permutations.  The cycle indices of certain groups are provided.
+
+The operation complete returns the cycle index of the symmetric group
+of order n for argument n.  Alternatively, it is the n-th complete
+homogeneous symmetric function expressed in terms of power sum
+symmetric functions.
+
+  complete 1
+   (1)
+                      Type: SymmetricPolynomial Fraction Integer
+
+  complete 2
+   1       1   2
+   - (2) + - (1 )
+   2       2
+                      Type: SymmetricPolynomial Fraction Integer
+
+  complete 3
+   1       1         1   3
+   - (3) + - (2 1) + - (1 )
+   3       2         6
+                      Type: SymmetricPolynomial Fraction Integer
+
+  complete 7
+     1       1          1          1     2     1         1            1     3
+     - (7) + - (6 1) + -- (5 2) + -- (5 1 ) + -- (4 3) + - (4 2 1) + -- (4 1 )
+     7       6         10         10          12         8           24
+   + 
+      1   2      1     2     1       2     1     4     1   3      1   2 3
+     -- (3 1) + -- (3 2 ) + -- (3 2 1 ) + -- (3 1 ) + -- (2 1) + -- (2 1 )
+     18         24          12            72          48         48
+   + 
+      1      5      1    7
+     --- (2 1 ) + ---- (1 )
+     240          5040
+                   Type: SymmetricPolynomial Fraction Integer
+
+The operation elementary computes the n-th elementary symmetric
+function for argument n.
+
+  elementary 7
+     1       1          1          1     2     1         1            1     3
+     - (7) - - (6 1) - -- (5 2) + -- (5 1 ) - -- (4 3) + - (4 2 1) - -- (4 1 )
+     7       6         10         10          12         8           24
+   + 
+      1   2      1     2     1       2     1     4     1   3      1   2 3
+     -- (3 1) + -- (3 2 ) - -- (3 2 1 ) + -- (3 1 ) - -- (2 1) + -- (2 1 )
+     18         24          12            72          48         48
+   + 
+        1      5      1    7
+     - --- (2 1 ) + ---- (1 )
+       240          5040
+                  Type: SymmetricPolynomial Fraction Integer
+
+The operation alternating returns the cycle index of the alternating 
+group having an even number of even parts in each cycle partition.
+
+  alternating 7
+     2       1     2    1           1   2      1     2     1     4     1   2 3
+     - (7) + - (5 1 ) + - (4 2 1) + - (3 1) + -- (3 2 ) + -- (3 1 ) + -- (2 1 )
+     7       5          4           9         12          36          24
+   + 
+       1    7
+     ---- (1 )
+     2520
+                  Type: SymmetricPolynomial Fraction Integer
+
+The operation cyclic returns the cycle index of the cyclic group.
+
+  cyclic 7
+   6       1   7
+   - (7) + - (1 )
+   7       7
+                  Type: SymmetricPolynomial Fraction Integer
+
+The operation dihedral is the cycle index of the dihedral group.
+
+  dihedral 7
+   3       1   3      1   7
+   - (7) + - (2 1) + -- (1 )
+   7       2         14
+                  Type: SymmetricPolynomial Fraction Integer
+
+The operation graphs for argument n returns the cycle index of the
+group of permutations on the edges of the complete graph with n nodes
+induced by applying the symmetric group to the nodes.
+
+  graphs 5
+   1           1   2    1   2     1   3     1   4 2     1   3 4     1    10
+   - (6 3 1) + - (5 ) + - (4 2) + - (3 1) + - (2 1 ) + -- (2 1 ) + --- (1  )
+   6           5        4         6         8          12          120
+                  Type: SymmetricPolynomial Fraction Integer
+
+The cycle index of a direct product of two groups is the product of
+the cycle indices of the groups.  Redfield provided two operations on
+two cycle indices which will be called "cup" and "cap" here.  The cup
+of two cycle indices is a kind of scalar product that combines
+monomials for permutations with the same cycles.  The cap operation
+provides the sum of the coefficients of the result of the cup
+operation which will be an integer that enumerates what Redfield
+called group-reduced distributions.
+
+We can, for example, represent complete 2 * complete 2 as the set of
+objects a a b b and complete 2 * complete 1 * complete 1 as c c d e.
+
+This integer is the number of different sets of four pairs.
+
+  cap(complete 2**2, complete 2*complete 1**2)
+    4
+                  Type: Fraction Integer
+
+For example,
+  a a b b     a a b b    a a b b   a a b b
+  c c d e     c d c e    c e c d   d e c c
+
+This integer is the number of different sets of four pairs no two
+pairs being equal.
+
+  cap(elementary 2**2, complete 2*complete 1**2)
+    2
+                  Type: Fraction Integer
+
+For example,
+
+  a a b b    a a b b
+  c d c e    c e c d
+
+In this case the configurations enumerated are easily constructed,
+however the theory merely enumerates them providing little help in
+actually constructing them.
+
+Here are the number of 6-pairs, first from a a a b b c, second
+from d d e e f g.
+
+  cap(complete 3*complete 2*complete 1,complete 2**2*complete 1**2)
+    24
+                     Type: Fraction Integer
+
+Here it is again, but with no equal pairs.
+
+  cap(elementary 3*elementary 2*elementary 1,complete 2**2*complete 1**2)
+    8
+                     Type: Fraction Integer
+
+  cap(complete 3*complete 2*complete 1,elementary 2**2*elementary 1**2)
+    8
+                     Type: Fraction Integer
+
+The number of 6-triples, first from a a a b b c, second from
+d d e e f g, third from h h i i j j.
+
+  eval(cup(complete 3*complete 2*complete 1, cup(complete 2**2*complete 1**2,complete 2**3)))
+    1500
+                     Type: Fraction Integer
+
+The cycle index of vertices of a square is dihedral 4.
+
+  square:=dihedral 4
+   1       3   2    1     2    1   4
+   - (4) + - (2 ) + - (2 1 ) + - (1 )
+   4       8        4          8
+                     Type: SymmetricPolynomial Fraction Integer
+
+The number of different squares with 2 red vertices and 2 blue vertices.
+
+  cap(complete 2**2,square)
+    2
+                     Type: Fraction Integer
+
+The number of necklaces with 3 red beads, 2 blue beads and 2 green beads.
+
+  cap(complete 3*complete 2**2,dihedral 7)
+    18
+                     Type: Fraction Integer
+
+The number of graphs with 5 nodes and 7 edges.
+
+  cap(graphs 5,complete 7*complete 3)
+    4
+                     Type: Fraction Integer
+
+The cycle index of rotations of vertices of a cube.
+
+  s(x) == powerSum(x)
+                     Type: Void
+
+  cube:=(1/24)*(s 1**8+9*s 2**4 + 8*s 3**2*s 1**2+6*s 4**2)
+   1   2    1   2 2    3   4     1   8
+   - (4 ) + - (3 1 ) + - (2 ) + -- (1 )
+   4        3          8        24
+                     Type: SymmetricPolynomial Fraction Integer
+
+The number of cubes with 4 red vertices and 4 blue vertices.
+
+  cap(complete 4**2,cube)
+    7
+                     Type: Fraction Integer
+
+The number of labeled graphs with degree sequence 2 2 2 1 1 with no 
+loops or multiple edges.
+
+  cap(complete 2**3*complete 1**2,wreath(elementary 4,elementary 2))
+    7
+                     Type: Fraction Integer
+
+Again, but with loops allowed but not multiple edges.
+
+  cap(complete 2**3*complete 1**2,wreath(elementary 4,complete 2))
+    17
+                     Type: Fraction Integer
+
+Again, but with multiple edges allowed, but not loops
+
+  cap(complete 2**3*complete 1**2,wreath(complete 4,elementary 2))
+    10
+                     Type: Fraction Integer
+
+Again, but with both multiple edges and loops allowed
+
+  cap(complete 2**3*complete 1**2,wreath(complete 4,complete 2))
+    23
+                     Type: Fraction Integer
+
+Having constructed a cycle index for a configuration we are at liberty
+to evaluate the s_i components any way we please.  For example we can
+produce enumerating generating functions.  This is done by providing a
+function f on an integer i to the value required of s_i, and then
+evaluating eval(f, cycleindex).
+
+  x: ULS(FRAC INT,'x,0) := 'x 
+   x
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+  ZeroOrOne: INT -> ULS(FRAC INT, 'x, 0) 
+                     Type: Void
+
+  Integers: INT -> ULS(FRAC INT, 'x, 0) 
+                     Type: Void
+
+For the integers 0 and 1, or two colors.
+
+  ZeroOrOne n == 1+x**n
+                     Type: Void
+
+  ZeroOrOne 5 
+         5
+    1 + x
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+For the integers 0, 1, 2, ... we have this.
+
+  Integers n == 1/(1-x**n) 
+                     Type: Void
+
+  Integers 5 
+         5    10      11
+    1 + x  + x   + O(x  )
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The coefficient of x^n is the number of graphs with 5 nodes and n edges. 
+
+Note that there is an eval function that takes two arguments. It has the 
+signature:
+
+  ((Integer -> D1),SymmetricPolynomial Fraction Integer) -> D1
+    from EvaluateCycleIndicators D1 if D1 has ALGEBRA FRAC INT
+
+This function is not normally exposed (it will not normally be considered
+in the list of eval functions) as it is only useful for this particular
+domain. To use it we ask that it be considered thus:
+
+  )expose EVALCYC
+
+and now we can use it:
+
+  eval(ZeroOrOne, graphs 5) 
+              2     3     4     5     6     7     8    9    10      11
+    1 + x + 2x  + 4x  + 6x  + 6x  + 6x  + 4x  + 2x  + x  + x   + O(x  )
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The coefficient of x^n is the number of necklaces with n red beads 
+and n-8 green beads.
+
+  eval(ZeroOrOne,dihedral 8) 
+              2     3     4     5     6    7    8
+    1 + x + 4x  + 5x  + 8x  + 5x  + 4x  + x  + x
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The coefficient of x^n is the number of partitions of n into 4 or fewer parts.
+
+  eval(Integers,complete 4) 
+             2     3     4     5     6      7      8      9      10      11
+   1 + x + 2x  + 3x  + 5x  + 6x  + 9x  + 11x  + 15x  + 18x  + 23x   + O(x  )
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The coefficient of x^n is the number of partitions of n into 4 boxes
+containing ordered distinct parts.
+
+  eval(Integers,elementary 4)
+      6    7     8     9     10     11     12      13      14      15      16
+     x  + x  + 2x  + 3x  + 5x   + 6x   + 9x   + 11x   + 15x   + 18x   + 23x
+   + 
+        17
+     O(x  )
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The coefficient of x^n is the number of different cubes with n red
+vertices and 8-n green ones.
+
+  eval(ZeroOrOne,cube) 
+              2     3     4     5     6    7    8
+    1 + x + 3x  + 3x  + 7x  + 3x  + 3x  + x  + x
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The coefficient of x^n is the number of different cubes with integers
+on the vertices whose sum is n.
+
+  eval(Integers,cube) 
+               2     3      4      5      6       7       8       9       10
+     1 + x + 4x  + 7x  + 21x  + 37x  + 85x  + 151x  + 292x  + 490x  + 848x
+   + 
+        11
+     O(x  )
+                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The coefficient of x^n is the number of graphs with 5 nodes and with
+integers on the edges whose sum is n.  In other words, the enumeration
+is of multigraphs with 5 nodes and n edges.
+
+  eval(Integers,graphs 5) 
+               2     3      4      5      6       7       8       9       10
+     1 + x + 3x  + 7x  + 17x  + 35x  + 76x  + 149x  + 291x  + 539x  + 974x
+   + 
+        11
+     O(x  )
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+Graphs with 15 nodes enumerated with respect to number of edges.
+
+  eval(ZeroOrOne ,graphs 15) 
+               2     3      4      5      6       7       8        9        10
+     1 + x + 2x  + 5x  + 11x  + 26x  + 68x  + 177x  + 496x  + 1471x  + 4583x
+   + 
+        11
+     O(x  )
+                     Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+Necklaces with 7 green beads, 8 white beads, 5 yellow beads and 10
+red beads.
+
+  cap(dihedral 30,complete 7*complete 8*complete 5*complete 10)
+    49958972383320
+                     Type: Fraction Integer
+
+The operation SFunction is the S-function or Schur function of a
+partition written as a descending list of integers expressed in terms
+of power sum symmetric functions.
+
+In this case the argument partition represents a tableau shape.  For
+example 3,2,2,1 represents a tableau with three boxes in the first
+row, two boxes in the second and third rows, and one box in the fourth
+row.  SFunction [3,2,2,1] counts the number of different tableaux of
+shape 3, 2, 2, 1 filled with objects with an ascending order in the
+columns and a non-descending order in the rows.
+
+  sf3221:= SFunction [3,2,2,1] 
+      1          1     2     1   2     1            1     4     1   2
+     -- (6 2) - -- (6 1 ) - -- (4 ) + -- (4 3 1) + -- (4 1 ) - -- (3 2)
+     12         12          16        12           24          36
+   + 
+      1   2 2     1     2      1       3     1     5     1    4     1   3 2
+     -- (3 1 ) - -- (3 2 1) - -- (3 2 1 ) - -- (3 1 ) - --- (2 ) + -- (2 1 )
+     36          24           36            72          192        48
+   + 
+      1   2 4     1      6     1    8
+     -- (2 1 ) - --- (2 1 ) + --- (1 )
+     96          144          576
+                     Type: SymmetricPolynomial Fraction Integer
+
+This is the number filled with a a b b c c d d.
+
+  cap(sf3221,complete 2**4) 
+    3
+                     Type: Fraction Integer
+
+The configurations enumerated above are:
+
+  a a b    a a c    a a d
+  b c      b b      b b
+  c d      c d      c c
+  d        d        d
+
+This is the number of tableaux filled with 1..8.
+
+  cap(sf3221, powerSum 1**8)
+    70
+                     Type: Fraction Integer
+
+The coefficient of x^n is the number of column strict reverse plane
+partitions of n of shape 3 2 2 1.
+
+  eval(Integers, sf3221)
+      9     10     11      12      13      14      15       16       17
+     x  + 3x   + 7x   + 14x   + 27x   + 47x   + 79x   + 126x   + 196x  
+   + 
+        18      19      20
+    294x  + 432x   + O(x  )
+                          Type: UnivariateLaurentSeries(Fraction Integer,x,0)
+
+The smallest is
+
+  0 0 0
+  1 1
+  2 2
+  3
+
+See Also:
+o )show CycleIndicators
+o $AXIOM/doc/src/algebra/cycles.spad.dvi
+
+@
 <<package CYCLES CycleIndicators>>=
 )abbrev package CYCLES CycleIndicators
 ++ Polya-Redfield enumeration by cycle indices.
diff --git a/src/algebra/derham.spad.pamphlet b/src/algebra/derham.spad.pamphlet
index eb06ae8..47d2db1 100644
--- a/src/algebra/derham.spad.pamphlet
+++ b/src/algebra/derham.spad.pamphlet
@@ -307,6 +307,584 @@ AntiSymm(R:Ring, lVar:List Symbol): Export == Implement where
 
 @
 \section{domain DERHAM DeRhamComplex}
+<<DeRhamComplex.input>>=
+-- derham.spad.pamphlet DeRhamComplex.input
+)spool DeRhamComplex.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 34
+coefRing := Integer
+--R 
+--R
+--R   (1)  Integer
+--R                                                                 Type: Domain
+--E 1
+
+--S 2 of 34
+lv : List Symbol := [x,y,z] 
+--R 
+--R
+--R   (2)  [x,y,z]
+--R                                                            Type: List Symbol
+--E 2
+
+--S 3 of 34
+der := DERHAM(coefRing,lv) 
+--R 
+--R
+--R   (3)  DeRhamComplex(Integer,[x,y,z])
+--R                                                                 Type: Domain
+--E 3
+
+--S 4 of 34
+R := Expression coefRing
+--R 
+--R
+--R   (4)  Expression Integer
+--R                                                                 Type: Domain
+--E 4
+
+--S 5 of 34
+f : R := x**2*y*z-5*x**3*y**2*z**5
+--R 
+--R
+--R            3 2 5    2
+--R   (5)  - 5x y z  + x y z
+--R                                                     Type: Expression Integer
+--E 5
+
+--S 6 of 34
+g : R := z**2*y*cos(z)-7*sin(x**3*y**2)*z**2 
+--R 
+--R
+--R            2     3 2       2
+--R   (6)  - 7z sin(x y ) + y z cos(z)
+--R                                                     Type: Expression Integer
+--E 6
+
+--S 7 of 34
+h : R :=x*y*z-2*x**3*y*z**2 
+--R 
+--R
+--R            3   2
+--R   (7)  - 2x y z  + x y z
+--R                                                     Type: Expression Integer
+--E 7
+
+--S 8 of 34
+dx : der := generator(1)
+--R 
+--R
+--R   (8)  dx
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 8
+
+--S 9 of 34
+dy : der := generator(2)
+--R 
+--R
+--R   (9)  dy
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 9
+
+--S 10 of 34
+dz : der := generator(3)
+--R 
+--R
+--R   (10)  dz
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 10
+
+--S 11 of 34
+[dx,dy,dz] := [generator(i)$der for i in 1..3]
+--R 
+--R
+--R   (11)  [dx,dy,dz]
+--R                                    Type: List DeRhamComplex(Integer,[x,y,z])
+--E 11
+
+--S 12 of 34
+alpha : der := f*dx + g*dy + h*dz
+--R 
+--R
+--R   (12)
+--R          3   2                   2     3 2       2
+--R     (- 2x y z  + x y z)dz + (- 7z sin(x y ) + y z cos(z))dy
+--R   + 
+--R          3 2 5    2
+--R     (- 5x y z  + x y z)dx
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 12
+
+--S 13 of 34
+beta  : der := cos(tan(x*y*z)+x*y*z)*dx + x*dy
+--R 
+--R
+--R   (13)  x dy + cos(tan(x y z) + x y z)dx
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 13
+
+--S 14 of 34
+exteriorDifferential alpha
+--R 
+--R
+--R   (14)
+--R         2                  3 2                    3 2
+--R     (y z sin(z) + 14z sin(x y ) - 2y z cos(z) - 2x z  + x z)dy dz
+--R   + 
+--R         3 2 4     2   2          2
+--R     (25x y z  - 6x y z  + y z - x y)dx dz
+--R   + 
+--R           2 2 2     3 2       3   5    2
+--R     (- 21x y z cos(x y ) + 10x y z  - x z)dx dy
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 14
+
+--S 15 of 34
+exteriorDifferential %
+--R 
+--R
+--R   (15)  0
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 15
+
+--S 16 of 34
+gamma := alpha * beta
+--R 
+--R
+--R   (16)
+--R        4   2    2               3   2
+--R     (2x y z  - x y z)dy dz + (2x y z  - x y z)cos(tan(x y z) + x y z)dx dz
+--R   + 
+--R       2     3 2       2                                   4 2 5    3
+--R   ((7z sin(x y ) - y z cos(z))cos(tan(x y z) + x y z) - 5x y z  + x y z)dx dy
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 16
+
+--S 17 of 34
+exteriorDifferential(gamma) - (exteriorDifferential(alpha)*beta - alpha * exteriorDifferential(beta)) 
+--R 
+--R
+--R   (17)  0
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 17
+
+--S 18 of 34
+a : BOP := operator('a)
+--R 
+--R
+--R   (18)  a
+--R                                                          Type: BasicOperator
+--E 18
+
+--S 19 of 34
+b : BOP := operator('b)
+--R 
+--R
+--R   (19)  b
+--R                                                          Type: BasicOperator
+--E 19
+
+--S 20 of 34
+c : BOP := operator('c)
+--R 
+--R
+--R   (20)  c
+--R                                                          Type: BasicOperator
+--E 20
+
+--S 21 of 34
+sigma := a(x,y,z) * dx + b(x,y,z) * dy + c(x,y,z) * dz 
+--R 
+--R
+--R   (21)  c(x,y,z)dz + b(x,y,z)dy + a(x,y,z)dx
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 21
+
+--S 22 of 34
+theta  := a(x,y,z) * dx * dy + b(x,y,z) * dx * dz + c(x,y,z) * dy * dz 
+--R 
+--R
+--R   (22)  c(x,y,z)dy dz + b(x,y,z)dx dz + a(x,y,z)dx dy
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 22
+
+--S 23 of 34
+totalDifferential(a(x,y,z))$der 
+--R 
+--R
+--R   (23)  a  (x,y,z)dz + a  (x,y,z)dy + a  (x,y,z)dx
+--R          ,3             ,2             ,1
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 23
+
+--S 24 of 34
+exteriorDifferential sigma
+--R 
+--R
+--R   (24)
+--R     (c  (x,y,z) - b  (x,y,z))dy dz + (c  (x,y,z) - a  (x,y,z))dx dz
+--R       ,2           ,3                  ,1           ,3
+--R   + 
+--R     (b  (x,y,z) - a  (x,y,z))dx dy
+--R       ,1           ,2
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 24
+
+--S 25 of 34
+exteriorDifferential theta
+--R 
+--R
+--R   (25)  (c  (x,y,z) - b  (x,y,z) + a  (x,y,z))dx dy dz
+--R           ,1           ,2           ,3
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 25
+
+--S 26 of 34
+one : der := 1
+--R 
+--R
+--R   (26)  1
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 26
+
+--S 27 of 34
+g1 : der := a([x,t,y,u,v,z,e]) * one 
+--R 
+--R
+--R   (27)  a(x,t,y,u,v,z,e)
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 27
+
+--S 28 of 34
+h1 : der := a([x,y,x,t,x,z,y,r,u,x]) * one 
+--R 
+--R
+--R   (28)  a(x,y,x,t,x,z,y,r,u,x)
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 28
+
+--S 29 of 34
+exteriorDifferential g1 
+--R 
+--R
+--R   (29)  a  (x,t,y,u,v,z,e)dz + a  (x,t,y,u,v,z,e)dy + a  (x,t,y,u,v,z,e)dx
+--R          ,6                     ,3                     ,1
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 29
+
+--S 30 of 34
+exteriorDifferential h1
+--R 
+--R
+--R   (30)
+--R     a  (x,y,x,t,x,z,y,r,u,x)dz
+--R      ,6
+--R   + 
+--R     (a  (x,y,x,t,x,z,y,r,u,x) + a  (x,y,x,t,x,z,y,r,u,x))dy
+--R       ,7                         ,2
+--R   + 
+--R         a   (x,y,x,t,x,z,y,r,u,x) + a  (x,y,x,t,x,z,y,r,u,x)
+--R          ,10                         ,5
+--R       + 
+--R         a  (x,y,x,t,x,z,y,r,u,x) + a  (x,y,x,t,x,z,y,r,u,x)
+--R          ,3                         ,1
+--R    *
+--R       dx
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 30
+
+--S 31 of 34
+coefficient(gamma, dx*dy)
+--R 
+--R
+--R            2     3 2       2                                   4 2 5    3
+--R   (31)  (7z sin(x y ) - y z cos(z))cos(tan(x y z) + x y z) - 5x y z  + x y z
+--R                                                     Type: Expression Integer
+--E 31
+
+--S 32 of 34
+coefficient(gamma, one)
+--R 
+--R
+--R   (32)  0
+--R                                                     Type: Expression Integer
+--E 32
+
+--S 33 of 34
+coefficient(g1,one)
+--R 
+--R
+--R   (33)  a(x,t,y,u,v,z,e)
+--R                                                     Type: Expression Integer
+--E 33
+
+--S 34 of 34
+gamma := alpha * beta
+--R 
+--R
+--R   (34)
+--R        4   2    2               3   2
+--R     (2x y z  - x y z)dy dz + (2x y z  - x y z)cos(tan(x y z) + x y z)dx dz
+--R   + 
+--R       2     3 2       2                                   4 2 5    3
+--R   ((7z sin(x y ) - y z cos(z))cos(tan(x y z) + x y z) - 5x y z  + x y z)dx dy
+--R                                         Type: DeRhamComplex(Integer,[x,y,z])
+--E 34
+)spool
+)lisp (bye)
+@
+<<DeRhamComplex.help>>=
+====================================================================
+DeRhamComplex
+====================================================================
+
+The domain constructor DeRhamComplex creates the class of differential
+forms of arbitrary degree over a coefficient ring.  The De Rham
+complex constructor takes two arguments: a ring, coefRing, and a list
+of coordinate variables.
+
+This is the ring of coefficients.
+
+  coefRing := Integer
+   Integer
+                      Type: Domain
+
+These are the coordinate variables.
+
+  lv : List Symbol := [x,y,z] 
+   [x,y,z]
+                      Type: List Symbol
+
+
+This is the De Rham complex of Euclidean three-space using coordinates
+x, y and z.
+
+  der := DERHAM(coefRing,lv) 
+   DeRhamComplex(Integer,[x,y,z])
+                      Type: Domain
+
+This complex allows us to describe differential forms having
+expressions of integers as coefficients.  These coefficients can
+involve any number of variables, for example, f(x,t,r,y,u,z).  As
+we've chosen to work with ordinary Euclidean three-space, expressions
+involving these forms are treated as functions of x, y and z with the
+additional arguments t, r and u regarded as symbolic constants.
+
+Here are some examples of coefficients.
+
+  R := Expression coefRing
+   Expression Integer
+                     Type: Domain
+
+  f : R := x**2*y*z-5*x**3*y**2*z**5
+       3 2 5    2
+   - 5x y z  + x y z
+                     Type: Expression Integer
+
+  g : R := z**2*y*cos(z)-7*sin(x**3*y**2)*z**2 
+       2     3 2       2
+   - 7z sin(x y ) + y z cos(z)
+                     Type: Expression Integer
+
+  h : R :=x*y*z-2*x**3*y*z**2 
+       3   2
+   - 2x y z  + x y z
+                     Type: Expression Integer
+
+We now define the multiplicative basis elements for the exterior
+algebra over R.
+
+  dx : der := generator(1)
+   dx
+                     Type: DeRhamComplex(Integer,[x,y,z])
+
+  dy : der := generator(2)
+   dy
+                     Type: DeRhamComplex(Integer,[x,y,z])
+
+  dz : der := generator(3)
+   dz
+                     Type: DeRhamComplex(Integer,[x,y,z])
+
+This is an alternative way to give the above assignments.
+
+  [dx,dy,dz] := [generator(i)$der for i in 1..3]
+    [dx,dy,dz]
+                     Type: List DeRhamComplex(Integer,[x,y,z])
+
+Now we define some one-forms.
+
+  alpha : der := f*dx + g*dy + h*dz
+          3   2                   2     3 2       2
+     (- 2x y z  + x y z)dz + (- 7z sin(x y ) + y z cos(z))dy
+   + 
+          3 2 5    2
+     (- 5x y z  + x y z)dx
+                     Type: DeRhamComplex(Integer,[x,y,z])
+
+  beta  : der := cos(tan(x*y*z)+x*y*z)*dx + x*dy
+    x dy + cos(tan(x y z) + x y z)dx
+                     Type: DeRhamComplex(Integer,[x,y,z])
+
+A well-known theorem states that the composition of exteriorDifferential 
+with itself is the zero map for continuous forms. Let's verify this 
+theorem for alpha.
+
+  exteriorDifferential alpha
+         2                  3 2                    3 2
+     (y z sin(z) + 14z sin(x y ) - 2y z cos(z) - 2x z  + x z)dy dz
+   + 
+         3 2 4     2   2          2
+     (25x y z  - 6x y z  + y z - x y)dx dz
+   + 
+           2 2 2     3 2       3   5    2
+     (- 21x y z cos(x y ) + 10x y z  - x z)dx dy
+                      Type: DeRhamComplex(Integer,[x,y,z])
+
+We see a lengthy output of the last expression, but nevertheless, the
+composition is zero.
+
+  exteriorDifferential %
+    0
+                      Type: DeRhamComplex(Integer,[x,y,z])
+
+Now we check that exteriorDifferential is a "graded derivation" D,
+that is, D satisfies:
+
+  D(a*b) = D(a)*b + (-1)**degree(a)*a*D(b)
+
+  gamma := alpha * beta
+        4   2    2               3   2
+     (2x y z  - x y z)dy dz + (2x y z  - x y z)cos(tan(x y z) + x y z)dx dz
+   + 
+       2     3 2       2                                   4 2 5    3
+   ((7z sin(x y ) - y z cos(z))cos(tan(x y z) + x y z) - 5x y z  + x y z)dx dy
+                      Type: DeRhamComplex(Integer,[x,y,z])
+
+We try this for the one-forms alpha and beta.
+
+  exteriorDifferential(gamma) - (exteriorDifferential(alpha)*beta - alpha * exteriorDifferential(beta)) 
+    0
+                      Type: DeRhamComplex(Integer,[x,y,z])
+
+Now we define some "basic operators"
+
+  a : BOP := operator('a)
+    a
+                      Type: BasicOperator
+
+  b : BOP := operator('b)
+    b
+                      Type: BasicOperator
+
+  c : BOP := operator('c)
+    c
+                      Type: BasicOperator
+
+We also define some indeterminate one- and two-forms using these
+operators.
+
+  sigma := a(x,y,z) * dx + b(x,y,z) * dy + c(x,y,z) * dz 
+    c(x,y,z)dz + b(x,y,z)dy + a(x,y,z)dx
+                      Type: DeRhamComplex(Integer,[x,y,z])
+
+  theta  := a(x,y,z) * dx * dy + b(x,y,z) * dx * dz + c(x,y,z) * dy * dz 
+    c(x,y,z)dy dz + b(x,y,z)dx dz + a(x,y,z)dx dy
+                      Type: DeRhamComplex(Integer,[x,y,z])
+
+This allows us to get formal definitions for the "gradient" ...
+
+  totalDifferential(a(x,y,z))$der 
+   (23)  a  (x,y,z)dz + a  (x,y,z)dy + a  (x,y,z)dx
+          ,3             ,2             ,1
+                      Type: DeRhamComplex(Integer,[x,y,z])
+the "curl" ...
+
+  exteriorDifferential sigma
+     (c  (x,y,z) - b  (x,y,z))dy dz + (c  (x,y,z) - a  (x,y,z))dx dz
+       ,2           ,3                  ,1           ,3
+   + 
+     (b  (x,y,z) - a  (x,y,z))dx dy
+       ,1           ,2
+                       Type: DeRhamComplex(Integer,[x,y,z])
+
+and the "divergence."
+
+  exteriorDifferential theta
+    (c  (x,y,z) - b  (x,y,z) + a  (x,y,z))dx dy dz
+      ,1           ,2           ,3
+                       Type: DeRhamComplex(Integer,[x,y,z])
+
+Note that the De Rham complex is an algebra with unity.  This element
+1 is the basis for elements for zero-forms, that is, functions in our
+space.
+
+  one : der := 1
+    1
+                       Type: DeRhamComplex(Integer,[x,y,z])
+
+To convert a function to a function lying in the De Rham complex,
+multiply the function by "one."
+
+  g1 : der := a([x,t,y,u,v,z,e]) * one 
+    a(x,t,y,u,v,z,e)
+                       Type: DeRhamComplex(Integer,[x,y,z])
+
+A current limitation of Axiom forces you to write functions with more
+than four arguments using square brackets in this way.
+
+  h1 : der := a([x,y,x,t,x,z,y,r,u,x]) * one 
+    a(x,y,x,t,x,z,y,r,u,x)
+                        Type: DeRhamComplex(Integer,[x,y,z])
+
+Now note how the system keeps track of where your coordinate functions
+are located in expressions.
+
+  exteriorDifferential g1 
+    a  (x,t,y,u,v,z,e)dz + a  (x,t,y,u,v,z,e)dy + a  (x,t,y,u,v,z,e)dx
+     ,6                     ,3                     ,1
+                        Type: DeRhamComplex(Integer,[x,y,z])
+
+  exteriorDifferential h1
+     a  (x,y,x,t,x,z,y,r,u,x)dz
+      ,6
+   + 
+     (a  (x,y,x,t,x,z,y,r,u,x) + a  (x,y,x,t,x,z,y,r,u,x))dy
+       ,7                         ,2
+   + 
+         a   (x,y,x,t,x,z,y,r,u,x) + a  (x,y,x,t,x,z,y,r,u,x)
+          ,10                         ,5
+       + 
+         a  (x,y,x,t,x,z,y,r,u,x) + a  (x,y,x,t,x,z,y,r,u,x)
+          ,3                         ,1
+    *
+       dx
+                       Type: DeRhamComplex(Integer,[x,y,z])
+
+In this example of Euclidean three-space, the basis for the De Rham complex
+consists of the eight forms: 1, dx, dy, dz, dx*dy, dx*dz, dy*dz, and dx*dy*dz.
+
+  coefficient(gamma, dx*dy)
+       2     3 2       2                                   4 2 5    3
+    (7z sin(x y ) - y z cos(z))cos(tan(x y z) + x y z) - 5x y z  + x y z
+                       Type: Expression Integer
+
+  coefficient(gamma, one)
+    0
+                       Type: Expression Integer
+
+  coefficient(g1,one)
+    a(x,t,y,u,v,z,e)
+                       Type: Expression Integer
+
+See Also:
+o )help Operator
+o )show DeRhamComplex
+o $AXIOM/doc/src/algebra/derham.spad.dvi
+
+@
 <<domain DERHAM DeRhamComplex>>=
 )abbrev domain DERHAM DeRhamComplex
 ++ Author: Larry A. Lambe
diff --git a/src/algebra/gaussian.spad.pamphlet b/src/algebra/gaussian.spad.pamphlet
index ccbd072..744488b 100644
--- a/src/algebra/gaussian.spad.pamphlet
+++ b/src/algebra/gaussian.spad.pamphlet
@@ -529,6 +529,286 @@ ComplexPatternMatch(R, S, CS) : C == T where
 
 @
 \section{domain COMPLEX Complex}
+<<Complex.input>>=
+-- gaussian.spad.pamphlet Complex.input
+)spool Complex.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 16
+a := complex(4/3,5/2)
+--R 
+--R
+--R        4   5
+--R   (1)  - + - %i
+--R        3   2
+--R                                               Type: Complex Fraction Integer
+--E 1
+
+--S 2 of 16
+b := complex(4/3,-5/2)
+--R 
+--R
+--R        4   5
+--R   (2)  - - - %i
+--R        3   2
+--R                                               Type: Complex Fraction Integer
+--E 2
+
+--S 3 of 16
+a + b
+--R 
+--R
+--R        8
+--R   (3)  -
+--R        3
+--R                                               Type: Complex Fraction Integer
+--E 3
+
+--S 4 of 16
+a - b
+--R 
+--R
+--R   (4)  5%i
+--R                                               Type: Complex Fraction Integer
+--E 4
+
+--S 5 of 16
+a * b
+--R 
+--R
+--R        289
+--R   (5)  ---
+--R         36
+--R                                               Type: Complex Fraction Integer
+--E 5
+
+--S 6 of 16
+a / b
+--R 
+--R
+--R          161   240
+--R   (6)  - --- + --- %i
+--R          289   289
+--R                                               Type: Complex Fraction Integer
+--E 6
+
+--S 7 of 16
+% :: Fraction Complex Integer
+--R 
+--R
+--R        - 15 + 8%i
+--R   (7)  ----------
+--R         15 + 8%i
+--R                                               Type: Fraction Complex Integer
+--E 7
+
+--S 8 of 16
+3.4 + 6.7 * %i
+--R 
+--R
+--R   (8)  3.4 + 6.7 %i
+--R                                                          Type: Complex Float
+--E 8
+
+--S 9 of 16
+conjugate a
+--R 
+--R
+--R        4   5
+--R   (9)  - - - %i
+--R        3   2
+--R                                               Type: Complex Fraction Integer
+--E 9
+
+--S 10 of 16
+norm a
+--R 
+--R
+--R         289
+--R   (10)  ---
+--R          36
+--R                                                       Type: Fraction Integer
+--E 10
+
+--S 11 of 16
+real a
+--R 
+--R
+--R         4
+--R   (11)  -
+--R         3
+--R                                                       Type: Fraction Integer
+--E 11
+
+--S 12 of 16
+imag a
+--R 
+--R
+--R         5
+--R   (12)  -
+--R         2
+--R                                                       Type: Fraction Integer
+--E 12
+
+--S 13 of 16
+gcd(13 - 13*%i,31 + 27*%i)
+--R 
+--R
+--R   (13)  5 + %i
+--R                                                        Type: Complex Integer
+--E 13
+
+--S 14 of 16
+lcm(13 - 13*%i,31 + 27*%i)
+--R 
+--R
+--R   (14)  143 - 39%i
+--R                                                        Type: Complex Integer
+--E 14
+
+--S 15 of 16
+factor(13 - 13*%i)
+--R 
+--R
+--R   (15)  - (1 + %i)(2 + 3%i)(3 + 2%i)
+--R                                               Type: Factored Complex Integer
+--E 15
+
+--S 16 of 16
+factor complex(2,0)
+--R 
+--R
+--R                      2
+--R   (16)  - %i (1 + %i)
+--R                                               Type: Factored Complex Integer
+--E 16
+)spool
+)lisp (bye)
+@
+<<Complex.help>>=
+====================================================================
+Complex
+====================================================================
+
+The Complex constructor implements complex objects over a commutative
+ring R.  Typically, the ring R is Integer, Fraction Integer, Float or
+DoubleFloat.  R can also be a symbolic type, like Polynomial Integer.
+
+Complex objects are created by the complex operation.
+
+  a := complex(4/3,5/2)
+   4   5
+   - + - %i
+   3   2
+                        Type: Complex Fraction Integer
+
+  b := complex(4/3,-5/2)
+   4   5
+   - - - %i
+   3   2
+                        Type: Complex Fraction Integer
+
+The standard arithmetic operations are available.
+
+  a + b
+   8
+   -
+   3
+                        Type: Complex Fraction Integer
+
+  a - b
+   5%i
+                        Type: Complex Fraction Integer
+
+  a * b
+   289
+   ---
+    36
+                        Type: Complex Fraction Integer
+
+If  R is a field, you can also divide the complex objects.
+
+  a / b
+     161   240
+   - --- + --- %i
+     289   289
+                        Type: Complex Fraction Integer
+
+
+We can view the last object as a fraction of complex integers.
+
+  % :: Fraction Complex Integer
+   - 15 + 8%i
+   ----------
+     15 + 8%i
+                       Type: Fraction Complex Integer
+
+The predefined macro %i is defined to be complex(0,1).
+
+  3.4 + 6.7 * %i
+   3.4 + 6.7 %i
+                      Type: Complex Float
+
+You can also compute the conjugate and norm of a complex number.
+
+  conjugate a
+   4   5
+   - - - %i
+   3   2
+                      Type: Complex Fraction Integer
+
+  norm a
+   289
+   ---
+    36
+                      Type: Fraction Integer
+
+The real and imag operations are provided to extract the real and
+imaginary parts, respectively.
+
+  real a
+   4
+   -
+   3
+                      Type: Fraction Integer
+
+  imag a
+   5
+   -
+   2
+                      Type: Fraction Integer
+
+The domain Complex Integer is also called the Gaussian integers.  If R
+is the integers (or, more generally, a EuclideanDomain), you can compute 
+greatest common divisors.
+
+  gcd(13 - 13*%i,31 + 27*%i)
+   5 + %i
+                      Type: Complex Integer
+
+You can also compute least common multiples.
+
+  lcm(13 - 13*%i,31 + 27*%i)
+   143 - 39%i
+                      Type: Complex Integer
+
+You can factor Gaussian integers.
+
+  factor(13 - 13*%i)
+   - (1 + %i)(2 + 3%i)(3 + 2%i)
+                      Type: Factored Complex Integer
+
+  factor complex(2,0)
+                2
+   - %i (1 + %i)
+                      Type: Factored Complex Integer
+
+See Also
+o )show Complex
+o $AXIOM/doc/src/algebra/gaussian.spad.dvi 
+
+@
 <<domain COMPLEX Complex>>=
 )abbrev domain COMPLEX Complex
 ++ Author:
diff --git a/src/algebra/list.spad.pamphlet b/src/algebra/list.spad.pamphlet
index d773bb6..1c534e9 100644
--- a/src/algebra/list.spad.pamphlet
+++ b/src/algebra/list.spad.pamphlet
@@ -671,6 +671,194 @@ ListToMap(A:SetCategory, B:Type): Exports == Implementation where
 
 @
 \section{domain ALIST AssociationList}
+<<AssociationList.input>>=
+-- list.spad.pamphlet AssociationList.input
+)spool AssociationList.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 10
+Data := Record(monthsOld : Integer, gender : String)
+--R 
+--R
+--R   (1)  Record(monthsOld: Integer,gender: String)
+--R                                                                 Type: Domain
+--E 1
+
+--S 2 of 10
+al : AssociationList(String,Data)
+--R 
+--R                                                                   Type: Void
+--E 2
+
+--S 3 of 10
+al := table()
+--R 
+--R
+--R   (3)  table()
+--R      Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
+--E 3
+
+--S 4 of 10
+al."bob" := [407,"male"]$Data
+--R 
+--R
+--R   (4)  [monthsOld= 407,gender= "male"]
+--R                              Type: Record(monthsOld: Integer,gender: String)
+--E 4
+
+--S 5 of 10
+al."judith" := [366,"female"]$Data
+--R 
+--R
+--R   (5)  [monthsOld= 366,gender= "female"]
+--R                              Type: Record(monthsOld: Integer,gender: String)
+--E 5
+
+--S 6 of 10
+al."katie" := [24,"female"]$Data
+--R 
+--R
+--R   (6)  [monthsOld= 24,gender= "female"]
+--R                              Type: Record(monthsOld: Integer,gender: String)
+--E 6
+
+--S 7 of 10
+al."smokie" := [200,"female"]$Data
+--R 
+--R
+--R   (7)  [monthsOld= 200,gender= "female"]
+--R                              Type: Record(monthsOld: Integer,gender: String)
+--E 7
+
+--S 8 of 10
+al
+--R 
+--R
+--R   (8)
+--R   table
+--R      "smokie"= [monthsOld= 200,gender= "female"]
+--R  ,
+--R      "katie"= [monthsOld= 24,gender= "female"]
+--R  ,
+--R      "judith"= [monthsOld= 366,gender= "female"]
+--R  ,
+--R      "bob"= [monthsOld= 407,gender= "male"]
+--R      Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
+--E 8
+
+--S 9 of 10
+al."katie" := [23,"female"]$Data
+--R 
+--R
+--R   (9)  [monthsOld= 23,gender= "female"]
+--R                              Type: Record(monthsOld: Integer,gender: String)
+--E 9
+
+--S 10 of 10
+delete!(al,1)
+--R 
+--R
+--R   (10)
+--R   table
+--R      "katie"= [monthsOld= 23,gender= "female"]
+--R  ,
+--R      "judith"= [monthsOld= 366,gender= "female"]
+--R  ,
+--R      "bob"= [monthsOld= 407,gender= "male"]
+--R      Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
+--E 10
+)spool
+)lisp (bye)
+@
+<<AssociationList.help>>=
+====================================================================
+AssociationList examples
+====================================================================
+
+The AssociationList constructor provides a general structure for
+associative storage.  This type provides association lists in which
+data objects can be saved according to keys of any type.  For a given
+association list, specific types must be chosen for the keys and
+entries.  You can think of the representation of an association list
+as a list of records with key and entry fields.
+
+Association lists are a form of table and so most of the operations
+available for Table are also available for AssociationList.  They can
+also be viewed as lists and can be manipulated accordingly.
+
+This is a Record type with age and gender fields.
+
+  Data := Record(monthsOld : Integer, gender : String)
+    Record(monthsOld: Integer,gender: String)
+                      Type: Domain
+
+In this expression, al is declared to be an association
+list whose keys are strings and whose entries are the above records.
+
+  al : AssociationList(String,Data)
+                      Type: Void
+
+The table operation is used to create an empty association list.
+
+  al := table()
+   table() 
+    Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
+
+You can use assignment syntax to add things to the association list.
+
+  al."bob" := [407,"male"]$Data
+   [monthsOld=407, gender= "male"]
+                      Type: Record(monthsOld: Integer,gender: String)
+
+  al."judith" := [366,"female"]$Data
+   [monthsOld=366, gender= "female"]
+                      Type: Record(monthsOld: Integer,gender: String)
+
+  al."katie" := [24,"female"]$Data
+   [monthsOld=24, gender= "female"]
+                      Type: Record(monthsOld: Integer,gender: String)
+
+Perhaps we should have included a species field.
+
+  al."smokie" := [200,"female"]$Data
+   [monthsOld0, gender= "female"]
+                      Type: Record(monthsOld: Integer,gender: String)
+
+Now look at what is in the association list.  Note that the last-added
+(key, entry) pair is at the beginning of the list.
+
+  al
+   table("smokie" = [monthsOld0, gender= "female"],
+         "katie" = [monthsOld=24, gender= "female"],
+         "judith" = [monthsOld=366, gender= "female"],
+         "bob" = [monthsOld=407, gender= "male"])
+      Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
+
+You can reset the entry for an existing key.
+
+  al."katie" := [23,"female"]$Data
+   [monthsOld=23, gender= "female"]
+                      Type: Record(monthsOld: Integer,gender: String)
+
+Use delete! to destructively remove an element of the association
+list.  Use delete to return a copy of the association list with the
+element deleted.  The second argument is the index of the element to
+delete.
+
+  delete!(al,1)
+   table("katie" = [monthsOld=23, gender= "female"],
+         "judith" = [monthsOld=366, gender= "female"],
+         "bob" = [monthsOld=407, gender= "male"])
+    Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
+
+See Also:
+o )help Table
+o )help List
+o )show AssociationList
+o $AXIOM/doc/src/algebra/list.spad.dvi
+
+@
 <<domain ALIST AssociationList>>=
 )abbrev domain ALIST AssociationList
 ++ Author:
diff --git a/src/algebra/op.spad.pamphlet b/src/algebra/op.spad.pamphlet
index 5b93a6a..e443d3c 100644
--- a/src/algebra/op.spad.pamphlet
+++ b/src/algebra/op.spad.pamphlet
@@ -10,6 +10,310 @@
 \tableofcontents
 \eject
 \section{domain BOP BasicOperator}
+<<BasicOperator.input>>=
+-- op.spad.pamphlet BasicOperator.input
+)spool BasicOperator.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 18
+y := operator 'y
+--R 
+--R
+--R   (1)  y
+--R                                                          Type: BasicOperator
+--E 1
+
+--S 2 of 18
+deq := D(y x, x, 2) + D(y x, x) + y x = 0
+--R 
+--R
+--R         ,,       ,
+--R   (2)  y  (x) + y (x) + y(x)= 0
+--R
+--R                                            Type: Equation Expression Integer
+--E 2
+
+--S 3 of 18
+solve(deq, y, x)
+--R 
+--R
+--R                                             x     x
+--R                                     +-+   - -   - -      +-+
+--R                                   x\|3      2     2    x\|3
+--R   (3)  [particular= 0,basis= [cos(-----)%e   ,%e   sin(-----)]]
+--R                                     2                    2
+--RType: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
+--E 3
+
+--S 4 of 18
+nary? y
+--R 
+--R
+--R   (4)  true
+--R                                                                Type: Boolean
+--E 4
+
+--S 5 of 18
+unary? y
+--R 
+--R
+--R   (5)  false
+--R                                                                Type: Boolean
+--E 5
+
+--S 6 of 18
+opOne := operator('opOne, 1)
+--R 
+--R
+--R   (6)  opOne
+--R                                                          Type: BasicOperator
+--E 6
+
+--S 7 of 18
+nary? opOne
+--R 
+--R
+--R   (7)  false
+--R                                                                Type: Boolean
+--E 7
+
+--S 8 of 18
+unary? opOne
+--R 
+--R
+--R   (8)  true
+--R                                                                Type: Boolean
+--E 8
+
+--S 9 of 18
+arity opOne
+--R 
+--R
+--R   (9)  1
+--R                                          Type: Union(NonNegativeInteger,...)
+--E 9
+
+--S 10 of 18
+name opOne
+--R 
+--R
+--R   (10)  opOne
+--R                                                                 Type: Symbol
+--E 10
+
+--S 11 of 18
+is?(opOne, 'z2)
+--R 
+--R
+--R   (11)  false
+--R                                                                Type: Boolean
+--E 11
+
+--S 12 of 18
+is?(opOne, "opOne")
+--R 
+--R
+--R   (12)  true
+--R                                                                Type: Boolean
+--E 12
+
+--S 13 of 18
+properties y
+--R 
+--R
+--R   (13)  table()
+--R                                           Type: AssociationList(String,None)
+--E 13
+
+--S 14 of 18
+setProperty(y, "use", "unknown function" :: None )
+--R 
+--R
+--R   (14)  y
+--R                                                          Type: BasicOperator
+--E 14
+
+--S 15 of 18
+properties y
+--R 
+--R
+--R   (15)  table("use"= NONE)
+--R                                           Type: AssociationList(String,None)
+--E 15
+
+--S 16 of 18
+property(y, "use") :: None pretend String
+--R 
+--R
+--R   (16)  "unknown function"
+--R                                                                 Type: String
+--E 16
+
+--S 17 of 18
+deleteProperty!(y, "use")
+--R 
+--R
+--R   (17)  y
+--R                                                          Type: BasicOperator
+--E 17
+
+--S 18 of 18
+properties y
+--R 
+--R
+--R   (18)  table()
+--R                                           Type: AssociationList(String,None)
+--E 18
+)spool
+)lisp (bye)
+@
+<<BasicOperator.help>>=
+====================================================================
+BasicOperator examples
+====================================================================
+
+A basic operator is an object that can be symbolically applied to a
+list of arguments from a set, the result being a kernel over that set
+or an expression.  
+
+You create an object of type BasicOperator by using the operator
+operation.  This first form of this operation has one argument and it
+must be a symbol.  The symbol should be quoted in case the name has
+been used as an identifier to which a value has been assigned.
+
+A frequent application of BasicOperator is the creation of an operator
+to represent the unknown function when solving a differential equation.
+
+Let y be the unknown function in terms of x.
+
+  y := operator 'y
+   y 
+                      Type: BasicOperator
+
+This is how you enter the equation y'' + y' + y = 0.
+
+  deq := D(y x, x, 2) + D(y x, x) + y x = 0
+    ,,       ,
+   y  (x) + y (x) + y(x) = 0
+                      Type: Equation Expression Integer
+
+To solve the above equation, enter this.
+
+  solve(deq, y, x)
+                                        x     x
+                                +-+   - -   - -      +-+
+                              x\|3      2     2    x\|3
+   [particular= 0,basis= [cos(-----)%e   ,%e   sin(-----)]]
+                                2                    2
+                      Type: Union(Record(particular: Expression Integer,
+                                  basis: List Expression Integer),...)
+
+Use the single argument form of BasicOperator (as above) when you
+intend to use the operator to create functional expressions with an
+arbitrary number of arguments
+
+Nary means an arbitrary number of arguments can be used in the
+functional expressions.
+
+  nary? y
+   true
+                      Type: Boolean
+
+  unary? y
+   false
+                      Type: Boolean
+
+Use the two-argument form when you want to restrict the number of
+arguments in the functional expressions created with the operator.
+
+This operator can only be used to create functional expressions
+with one argument.
+
+  opOne := operator('opOne, 1)
+   opOne 
+                      Type: BasicOperator
+
+  nary? opOne
+   false
+                      Type: Boolean
+
+  unary? opOne
+   true
+                      Type: Boolean
+
+Use arity to learn the number of arguments that can be used.  It
+returns "false" if the operator is nary.
+
+  arity opOne
+   1
+                      Type: Union(NonNegativeInteger,...)
+
+Use name to learn the name of an operator.
+
+  name opOne
+   opOne 
+                      Type: Symbol
+
+Use is? to learn if an operator has a particular name.
+
+  is?(opOne, 'z2)
+   false
+                      Type: Boolean
+
+You can also use a string as the name to be tested against.
+
+  is?(opOne, "opOne")
+   true
+                      Type: Boolean
+
+You can attached named properties to an operator.  These are rarely
+used at the top-level of the Axiom interactive environment but are
+used with Axiom library source code.
+
+By default, an operator has no properties.
+
+  properties y
+   table() 
+                      Type: AssociationList(String,None)
+
+The interface for setting and getting properties is somewhat awkward
+because the property values are stored as values of type None.
+
+Attach a property by using setProperty.
+
+  setProperty(y, "use", "unknown function" :: None )
+   y 
+                      Type: BasicOperator
+
+  properties y
+   table("use"=NONE)
+                      Type: AssociationList(String,None)
+
+We know the property value has type String.
+
+  property(y, "use") :: None pretend String
+   "unknown function"
+                      Type: String
+
+Use deleteProperty! to destructively remove a property.
+
+ deleteProperty!(y, "use")
+  y 
+                      Type: BasicOperator
+
+  properties y
+   table() 
+                      Type: AssociationList(String,None)
+
+
+See Also
+o )help Expression
+o )help Kernel
+o )show BasicOperator
+o $AXIOM/doc/src/algebra/op.spad.dvi
+
+@
 <<domain BOP BasicOperator>>=
 )abbrev domain BOP BasicOperator
 ++ Basic system operators
diff --git a/src/algebra/radix.spad.pamphlet b/src/algebra/radix.spad.pamphlet
index d26f7b5..f35780e 100644
--- a/src/algebra/radix.spad.pamphlet
+++ b/src/algebra/radix.spad.pamphlet
@@ -255,6 +255,168 @@ RadixExpansion(bb): Exports == Implementation where
 
 @
 \section{domain BINARY BinaryExpansion}
+<<BinaryExpansion.input>>=
+-- radix.spad.pamphlet BinaryExpansion.input
+)spool BinaryExpansion.output
+)set message test on
+)set message auto off
+)clear all
+--S 1
+r := binary(22/7)
+--R 
+--R
+--R           ___
+--R   (1)  11.001
+--R                                                        Type: BinaryExpansion
+--E 1
+
+--S 2
+r + binary(6/7)
+--R 
+--R
+--R   (2)  100
+--R                                                        Type: BinaryExpansion
+--E 2
+
+--S 3
+[binary(1/i) for i in 102..106]
+--R 
+--R
+--R   (3)
+--R       ________    ___________________________________________________
+--R   [0.000000101, 0.000000100111110001000101100101111001110010010101001,
+--R         ____________    ____________
+--R    0.000000100111011, 0.000000100111,
+--R       ____________________________________________________
+--R    0.00000010011010100100001110011111011001010110111100011]
+--R                                                   Type: List BinaryExpansion
+--E 3
+
+--S 4
+binary(1/1007)
+--R 
+--R
+--R   (4)
+--R   0.
+--R     OVERBAR
+--R        00000000010000010001010010010111100000111111000010111111001011000111110
+--R          100010011100100110011000110010010101011110110100110000000011000011001
+--R          111011100011010001011110100100011110110000101011101110011101010111001
+--R          100101001011100000001110001111001000000100100100110111001010100111010
+--R          001101110110101110001001000001100101101100000010110010111110001010000
+--R          010101010110101100000110110111010010101111111010111010100110010000101
+--R          0011011000100110001000100001000011000111010011110001
+--R                                                        Type: BinaryExpansion
+--E 4
+
+--S 5
+p := binary(1/4)*x**2 + binary(2/3)*x + binary(4/9)
+--R 
+--R
+--R             2     __      ______
+--R   (5)  0.01x  + 0.10x + 0.011100
+--R                                             Type: Polynomial BinaryExpansion
+--E 5
+
+--S 6
+q := D(p, x)
+--R 
+--R
+--R                 __
+--R   (6)  0.1x + 0.10
+--R                                             Type: Polynomial BinaryExpansion
+--E 6
+
+--S 7
+g := gcd(p, q)
+--R 
+--R
+--R              __
+--R   (7)  x + 1.01
+--R                                             Type: Polynomial BinaryExpansion
+--E 7
+)spool
+)lisp (bye)
+@
+<<BinaryExpansion.help>>=
+====================================================================
+BinaryExpansion examples
+====================================================================
+All rational numbers have repeating binary expansions.  Operations to
+access the individual bits of a binary expansion can be obtained by
+converting the value to RadixExpansion(2).  More examples of
+expansions are available with
+
+The expansion (of type BinaryExpansion) of a rational number is
+returned by the binary operation.
+
+  r := binary(22/7)
+      ___
+   11.001
+                      Type: BinaryExpansion
+
+Arithmetic is exact.
+
+  r + binary(6/7)
+   100 
+                      Type: BinaryExpansion
+
+The period of the expansion can be short or long.
+
+  [binary(1/i) for i in 102..106]
+      ________
+   [0.00000101,
+      ___________________________________________________
+    0.000000100111110001000101100101111001110010010101001,
+         ____________    ____________
+    0.000000100111011, 0.000000100111,
+       ____________________________________________________
+    0.00000010011010100100001110011111011001010110111100011]
+                      Type: List BinaryExpansion
+
+or very long.
+
+  binary(1/1007)
+     ________________________________________________________________________
+   0.000000000100000100010100100101111000001111110000101111110010110001111101
+     ________________________________________________________________________
+     000100111001001100110001100100101010111101101001100000000110000110011110
+     ________________________________________________________________________
+     111000110100010111101001000111101100001010111011100111010101110011001010
+     ________________________________________________________________________
+     010111000000011100011110010000001001001001101110010101001110100011011101
+     ________________________________________________________________________
+     101011100010010000011001011011000000101100101111100010100000101010101101
+     ________________________________________________________________________
+     011000001101101110100101011111110101110101001100100001010011011000100110
+     ____________________________________
+     001000100001000011000111010011110001
+                      Type: BinaryExpansion
+
+These numbers are bona fide algebraic objects.
+
+  p := binary(1/4)*x**2 + binary(2/3)*x + binary(4/9)
+               __       ______
+   0.01 x^2 +0.10 x + 0.011100
+                      Type: Polynomial BinaryExpansion
+
+  q := D(p, x)
+             __
+   0.1 x + 0.10
+                      Type: Polynomial BinaryExpansion
+
+  g := gcd(p, q)
+       __
+   x+1.01
+                      Type: Polynomial BinaryExpansion
+
+See Also:
+o )help DecimalExpansion
+o )help HexadecimalExpansion
+o )show BinaryExpansion
+o $AXIOM/doc/src/algebra/radix.spad.dvi
+
+@
 <<domain BINARY BinaryExpansion>>=
 )abbrev domain BINARY BinaryExpansion
 ++ Author: Clifton J. Williamson
@@ -288,6 +450,157 @@ BinaryExpansion(): Exports == Implementation where
 
 @
 \section{domain DECIMAL DecimalExpansion}
+<<DecimalExpansion.input>>=
+-- radix.spad.pamphlet DecimalExpansion.input
+)spool DecimalExpansion.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 7
+r := decimal(22/7)
+--R 
+--R
+--R          ______
+--R   (1)  3.142857
+--R                                                       Type: DecimalExpansion
+--E 1
+
+--S 2 of 7
+r + decimal(6/7)
+--R 
+--R
+--R   (2)  4
+--R                                                       Type: DecimalExpansion
+--E 2
+
+--S 3 of 7
+[decimal(1/i) for i in 350..354]
+--R 
+--R
+--R   (3)
+--R        ______    ______         __    ________________________________
+--R   [0.00285714, 0.002849, 0.0028409, 0.00283286118980169971671388101983,
+--R       __________________________________________________________
+--R    0.00282485875706214689265536723163841807909604519774011299435]
+--R                                                  Type: List DecimalExpansion
+--E 3
+
+--S 4 of 7
+decimal(1/2049)
+--R 
+--R
+--R   (4)
+--R   0.
+--R     OVERBAR
+--R        00048804294777940458760370912640312347486578818936066373840897999023914
+--R          104441190824792581747193753050268423621278672523182040019521717911176
+--R          183504148365056124938994631527574426549536359199609565641776476329917
+--R          032698877501220107369448511469009272816007808687164470473401659346022
+--R          449975597852611029770619814543679843826256710590531966813079551
+--R                                                       Type: DecimalExpansion
+--E 4
+
+--S 5 of 7
+p := decimal(1/4)*x**2 + decimal(2/3)*x + decimal(4/9) 
+--R 
+--R
+--R             2     _      _
+--R   (5)  0.25x  + 0.6x + 0.4
+--R                                            Type: Polynomial DecimalExpansion
+--E 5
+
+--S 6 of 7
+q := differentiate(p, x)
+--R 
+--R
+--R                 _
+--R   (6)  0.5x + 0.6
+--R                                            Type: Polynomial DecimalExpansion
+--E 6
+
+--S 7 of 7
+g := gcd(p, q)
+--R 
+--R
+--R              _
+--R   (7)  x + 1.3
+--R                                            Type: Polynomial DecimalExpansion
+--E 7
+)spool
+)lisp (bye)
+@
+<<DecimalExpansion.help>>=
+====================================================================
+DecimalExpansion examples
+====================================================================
+
+All rationals have repeating decimal expansions.  Operations to access
+the individual digits of a decimal expansion can be obtained by
+converting the value to RadixExpansion(10).  
+
+The operation decimal is used to create this expansion of type
+DecimalExpansion.
+
+  r := decimal(22/7)
+      ______
+    3.142857
+                      Type: DecimalExpansion
+
+Arithmetic is exact.
+
+  r + decimal(6/7)
+   4
+                      Type: DecimalExpansion
+
+The period of the expansion can be short or long ...
+
+  [decimal(1/i) for i in 350..354]
+        ______    ______         __    ________________________________
+   [0.00285714, 0.002849, 0.0028409, 0.00283286118980169971671388101983,
+       __________________________________________________________
+    0.00282485875706214689265536723163841807909604519774011299435]
+                      Type: List DecimalExpansion
+
+or very long.
+
+  decimal(1/2049)
+     _______________________________________________________________________
+   0.00048804294777940458760370912640312347486578818936066373840897999023914
+     _____________________________________________________________________
+     104441190824792581747193753050268423621278672523182040019521717911176
+     _____________________________________________________________________
+     183504148365056124938994631527574426549536359199609565641776476329917
+     _____________________________________________________________________
+     032698877501220107369448511469009272816007808687164470473401659346022
+     _______________________________________________________________
+     449975597852611029770619814543679843826256710590531966813079551
+                     Type: DecimalExpansion
+
+These numbers are bona fide algebraic objects.
+
+  p := decimal(1/4)*x**2 + decimal(2/3)*x + decimal(4/9) 
+        2     _      _
+   0.25x  + 0.6x + 0.4
+                     Type: Polynomial DecimalExpansion
+
+  q := differentiate(p, x)
+            _
+   0.5x + 0.6
+                     Type: Polynomial DecimalExpansion
+
+  g := gcd(p, q)
+         _
+   x + 1.3
+                     Type: Polynomial DecimalExpansion
+
+See Also:
+o )help RadixExpansion
+o )help BinaryExpansion
+o )help HexadecimalExpansion
+o )show DecimalExpansion
+o $AXIOM/doc/src/algebra/radix.spad.dvi
+
+@
 <<domain DECIMAL DecimalExpansion>>=
 )abbrev domain DECIMAL DecimalExpansion
 ++ Author: Stephen M. Watt
diff --git a/src/algebra/string.spad.pamphlet b/src/algebra/string.spad.pamphlet
index 6fb42a5..fe270fc 100644
--- a/src/algebra/string.spad.pamphlet
+++ b/src/algebra/string.spad.pamphlet
@@ -10,6 +10,208 @@
 \tableofcontents
 \eject
 \section{domain CHAR Character}
+<<Character.input>>=
+-- string.spad.pamphlet Character.input
+)spool Character.output
+)set message test on
+)set message auto off
+)clear all
+--S 1
+chars := [char "a", char "A", char "X", char "8", char "+"]
+--R 
+--R
+--R   (1)  [a,A,X,8,+]
+--R                                                         Type: List Character
+--E 1
+
+--S 2
+space()
+--R 
+--R
+--R   (2)
+--R                                                              Type: Character
+--E 2
+
+--S 3
+quote()
+--R 
+--R
+--R   (3)  "
+--R                                                              Type: Character
+--E 3
+
+--S 4
+escape()
+--R 
+--R
+--R   (4)  _
+--R                                                              Type: Character
+--E 4
+
+--S 5
+[ord c for c in chars]
+--R 
+--R
+--R   (5)  [97,65,88,56,43]
+--R                                                           Type: List Integer
+--E 5
+
+--S 6
+[upperCase c for c in chars]
+--R 
+--R
+--R   (6)  [A,A,X,8,+]
+--R                                                         Type: List Character
+--E 6
+
+--S 7
+[lowerCase c for c in chars]
+--R 
+--R
+--R   (7)  [a,a,x,8,+]
+--R                                                         Type: List Character
+--E 7
+
+--S 8
+[alphabetic? c for c in chars]
+--R 
+--R
+--R   (8)  [true,true,true,false,false]
+--R                                                           Type: List Boolean
+--E 8
+
+--S 9
+[upperCase? c for c in chars]
+--R 
+--R
+--R   (9)  [false,true,true,false,false]
+--R                                                           Type: List Boolean
+--E 9
+
+--S 10
+[lowerCase? c for c in chars]
+--R 
+--R
+--R   (10)  [true,false,false,false,false]
+--R                                                           Type: List Boolean
+--E 10
+
+--S 11
+[digit? c for c in chars]
+--R 
+--R
+--R   (11)  [false,false,false,true,false]
+--R                                                           Type: List Boolean
+--E 11
+
+--S 12
+[hexDigit? c for c in chars]
+--R 
+--R
+--R   (12)  [true,true,false,true,false]
+--R                                                           Type: List Boolean
+--E 12
+
+--S 13
+[alphanumeric? c for c in chars]
+--R 
+--R
+--R   (13)  [true,true,true,true,false]
+--R                                                           Type: List Boolean
+--E 13
+)spool
+)lisp (bye)
+@
+<<Character.help>>=
+====================================================================
+Character examples
+====================================================================
+
+The members of the domain Character are values representing letters,
+numerals and other text elements.
+
+Characters can be obtained using String notation.
+
+  chars := [char "a", char "A", char "X", char "8", char "+"]
+   [a,A,X,8,+]
+                      Type: List Character
+
+Certain characters are available by name. This is the blank character.
+
+  space()
+
+                      Type: Character
+
+This is the quote that is used in strings.
+
+  quote()
+   "
+                      Type: Character
+
+This is the escape character that allows quotes and other characters
+within strings.
+
+  escape()
+   _
+                      Type: Character
+
+Characters are represented as integers in a machine-dependent way.
+The integer value can be obtained using the ord operation.  It is
+always true that char(ord c) = c and ord(char i) = i, provided that i
+is in the range 0..size()$Character-1.
+
+  [ord c for c in chars]
+   [97,65,88,56,43]
+                      Type: List Integer
+ 
+The lowerCase operation converts an upper case letter to the
+corresponding lower case letter.  If the argument is not an upper case
+letter, then it is returned unchanged.
+
+  [upperCase c for c in chars]
+    [A,A,X,8,+]
+                      Type: List Character
+
+The upperCase operation converts lower case letters to upper case.
+
+  [lowerCase c for c in chars]
+   [a,a,x,8,+]
+                      Type: List Character
+
+A number of tests are available to determine whether characters
+belong to certain families.
+
+  [alphabetic? c for c in chars]
+   [true,true,true,false,false]
+                      Type: List Boolean
+
+  [upperCase? c for c in chars]
+   [false,true,true,false,false]
+                      Type: List Boolean
+
+  [lowerCase? c for c in chars]
+    [true,false,false,false,false]
+                      Type: List Boolean
+
+  [digit? c for c in chars]
+   [false,false,false,true,false]
+                      Type: List Boolean
+
+  [hexDigit? c for c in chars]
+   [true,true,false,true,false]
+                      Type: List Boolean
+
+  [alphanumeric? c for c in chars]
+   [true,true,true,true,false]
+                      Type: List Boolean
+
+See Also:
+o )help CharacterClass
+o )help String
+o )show Character
+o $AXIOM/doc/src/algebra/string.spad.dvi
+
+@
 <<domain CHAR Character>>=
 )abbrev domain CHAR Character
 ++ Author: Stephen M. Watt
@@ -202,6 +404,233 @@ Note that this code is not included in the generated catdef.spad file.
 (MAKEPROP (QUOTE |Character|) (QUOTE NILADIC) T) 
 @
 \section{domain CCLASS CharacterClass}
+<<CharacterClass.input>>=
+-- string.spad.pamphlet CharacterClass.input
+)spool CharacterClass.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 16
+cl1:=charClass[char "a",char "e",char "i",char "o",char "u",char "y"]
+--R 
+--R
+--R   (1)  "aeiouy"
+--R                                                         Type: CharacterClass
+--E 1
+
+--S 2 of 16
+cl2 := charClass "bcdfghjklmnpqrstvwxyz"
+--R 
+--R
+--R   (2)  "bcdfghjklmnpqrstvwxyz"
+--R                                                         Type: CharacterClass
+--E 2
+
+--S 3 of 16
+digit()
+--R 
+--R
+--R   (3)  "0123456789"
+--R                                                         Type: CharacterClass
+--E 3
+
+--S 4 of 16
+hexDigit()
+--R 
+--R
+--R   (4)  "0123456789ABCDEFabcdef"
+--R                                                         Type: CharacterClass
+--E 4
+
+--S 5 of 16
+upperCase()
+--R 
+--R
+--R   (5)  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+--R                                                         Type: CharacterClass
+--E 5
+
+--S 6 of 16
+lowerCase()
+--R 
+--R
+--R   (6)  "abcdefghijklmnopqrstuvwxyz"
+--R                                                         Type: CharacterClass
+--E 6
+
+--S 7 of 16
+alphabetic()
+--R 
+--R
+--R   (7)  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+--R                                                         Type: CharacterClass
+--E 7
+
+--S 8 of 16
+alphanumeric()
+--R 
+--R
+--R   (8)  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+--R                                                         Type: CharacterClass
+--E 8
+
+--S 9 of 16
+member?(char "a", cl1)
+--R 
+--R
+--R   (9)  true
+--R                                                                Type: Boolean
+--E 9
+
+--S 10 of 16
+member?(char "a", cl2)
+--R 
+--R
+--R   (10)  false
+--R                                                                Type: Boolean
+--E 10
+
+--S 11 of 16
+intersect(cl1, cl2)
+--R 
+--R
+--R   (11)  "y"
+--R                                                         Type: CharacterClass
+--E 11
+
+--S 12 of 16
+union(cl1,cl2)
+--R 
+--R
+--R   (12)  "abcdefghijklmnopqrstuvwxyz"
+--R                                                         Type: CharacterClass
+--E 12
+
+--S 13 of 16
+difference(cl1,cl2)
+--R 
+--R
+--R   (13)  "aeiou"
+--R                                                         Type: CharacterClass
+--E 13
+
+--S 14 of 16
+intersect(complement(cl1),cl2)
+--R 
+--R
+--R   (14)  "bcdfghjklmnpqrstvwxz"
+--R                                                         Type: CharacterClass
+--E 14
+
+--S 15 of 16
+insert!(char "a", cl2)
+--R 
+--R
+--R   (15)  "abcdfghjklmnpqrstvwxyz"
+--R                                                         Type: CharacterClass
+--E 15
+
+--S 16 of 16
+remove!(char "b", cl2)
+--R 
+--R
+--R   (16)  "acdfghjklmnpqrstvwxyz"
+--R                                                         Type: CharacterClass
+--E 16
+)spool
+)lisp (bye)
+@
+<<CharacterClass.help>>=
+====================================================================
+CharacterClass examples
+====================================================================
+
+The CharacterClass domain allows classes of characters to be defined
+and manipulated efficiently.
+ 
+Character classes can be created by giving either a string or a list
+of characters.
+
+  cl1:=charClass[char "a",char "e",char "i",char "o",char "u",char "y"]
+   "aeiouy"
+                      Type: CharacterClass
+
+  cl2 := charClass "bcdfghjklmnpqrstvwxyz"
+   "bcdfghjklmnpqrstvwxyz"
+                      Type: CharacterClass
+
+A number of character classes are predefined for convenience.
+
+  digit()
+   "0123456789"
+                      Type: CharacterClass
+
+  hexDigit()
+   "0123456789ABCDEFabcdef"
+                      Type: CharacterClass
+
+  upperCase()
+   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                      Type: CharacterClass
+
+  lowerCase()
+   "abcdefghijklmnopqrstuvwxyz"
+                      Type: CharacterClass
+
+  alphabetic()
+   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+                      Type: CharacterClass
+
+  alphanumeric()
+   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+                      Type: CharacterClass
+
+You can quickly test whether a character belongs to a class.
+
+  member?(char "a", cl1)
+   true
+                      Type: Boolean
+
+  member?(char "a", cl2)
+   false
+                      Type: Boolean
+
+Classes have the usual set operations because the CharacterClass
+domain belongs to the category FiniteSetAggregate(Character).
+
+  intersect(cl1, cl2)
+   "y"
+                      Type: CharacterClass
+
+  union(cl1,cl2)
+   "abcdefghijklmnopqrstuvwxyz"
+                      Type: CharacterClass
+
+  difference(cl1,cl2)
+   "aeiou"
+                      Type: CharacterClass
+
+  intersect(complement(cl1),cl2)
+   "bcdfghjklmnpqrstvwxz"
+                      Type: CharacterClass
+
+You can modify character classes by adding or removing characters.
+
+  insert!(char "a", cl2)
+   "abcdfghjklmnpqrstvwxyz"
+                      Type: CharacterClass
+
+  remove!(char "b", cl2)
+   "acdfghjklmnpqrstvwxyz"
+                      Type: CharacterClass
+ 
+See Also:
+o )help Character
+o )help String
+o )show CharacterClass
+o $AXIOM/doc/src/algebra/string.spad.dvi
+
+@
 <<domain CCLASS CharacterClass>>=
 )abbrev domain CCLASS CharacterClass
 ++ Author: Stephen M. Watt
diff --git a/src/algebra/tree.spad.pamphlet b/src/algebra/tree.spad.pamphlet
index ff8ba34..573f7f8 100644
--- a/src/algebra/tree.spad.pamphlet
+++ b/src/algebra/tree.spad.pamphlet
@@ -411,6 +411,210 @@ BinaryTree(S: SetCategory): Exports == Implementation where
 
 @
 \section{domain BSTREE BinarySearchTree}
+<<BinarySearchTree.input>>=
+-- tree.spad.pamphlet BinarySearchTree.input
+)spool BinarySearchTree.output
+)set message test on
+)set message auto off
+)clear all
+--S 1 of 12
+lv := [8,3,5,4,6,2,1,5,7]
+--R 
+--R
+--R   (1)  [8,3,5,4,6,2,1,5,7]
+--R                                                   Type: List PositiveInteger
+--E 1
+
+--S 2 of 12
+t := binarySearchTree lv
+--R 
+--R
+--R   (2)  [[[1,2,.],3,[4,5,[5,6,7]]],8,.]
+--R                                       Type: BinarySearchTree PositiveInteger
+--E 2
+
+--S 3 of 12
+emptybst := empty()$BSTREE(INT)
+--R 
+--R
+--R   (3)  []
+--R                                               Type: BinarySearchTree Integer
+--E 3
+
+--S 4 of 12
+t1 := insert!(8,emptybst)
+--R 
+--R
+--R   (4)  8
+--R                                               Type: BinarySearchTree Integer
+--E 4
+
+--S 5 of 12
+insert!(3,t1)
+--R 
+--R
+--R   (5)  [3,8,.]
+--R                                               Type: BinarySearchTree Integer
+--E 5
+
+--S 6 of 12
+leaves t
+--R 
+--R
+--R   (6)  [1,4,5,7]
+--R                                                   Type: List PositiveInteger
+--E 6
+
+--S 7 of 12
+split(3,t)
+--R 
+--R
+--R   (7)  [less= [1,2,.],greater= [[.,3,[4,5,[5,6,7]]],8,.]]
+--RType: Record(less: BinarySearchTree PositiveInteger,greater: BinarySearchTree PositiveInteger)
+--E 7
+
+--S 8 of 12
+insertRoot: (INT,BSTREE INT) -> BSTREE INT
+--R 
+--R                                                                   Type: Void
+--E 8
+
+--S 9 of 12
+insertRoot(x, t) ==
+    a := split(x, t)
+    node(a.less, x, a.greater)
+--R 
+--R                                                                   Type: Void
+--E 9
+
+--S 10 of 12
+buildFromRoot ls == reduce(insertRoot,ls,emptybst)
+--R 
+--R                                                                   Type: Void
+--E 10
+
+--S 11 of 12
+rt := buildFromRoot reverse lv
+--R 
+--R   Compiling function buildFromRoot with type List PositiveInteger -> 
+--R      BinarySearchTree Integer 
+--R   Compiling function insertRoot with type (Integer,BinarySearchTree 
+--R      Integer) -> BinarySearchTree Integer 
+--R
+--R   (11)  [[[1,2,.],3,[4,5,[5,6,7]]],8,.]
+--R                                               Type: BinarySearchTree Integer
+--E 11
+
+--S 12 of 12
+(t = rt)@Boolean
+--R 
+--R
+--R   (12)  true
+--R                                                                Type: Boolean
+--E 12
+)spool
+)lisp (bye)
+@
+<<BinarySearchTree.help>>=
+====================================================================
+BinarySearchTree examples
+====================================================================
+
+BinarySearchTree(R) is the domain of binary trees with elements of
+type R, ordered across the nodes of the tree.  A non-empty binary
+search tree has a value of type R, and right and left binary search
+subtrees.  If a subtree is empty, it is displayed as a period (".").
+
+Define a list of values to be placed across the tree.  The resulting
+tree has 8 at the root; all other elements are in the left subtree.
+
+  lv := [8,3,5,4,6,2,1,5,7]
+   [8, 3, 5, 4, 6, 2, 1, 5, 7]
+                      Type: List PositiveInteger
+
+A convenient way to create a binary search tree is to apply the
+operation binarySearchTree to a list of elements.
+
+  t := binarySearchTree lv
+   [[[1, 2, .], 3, [4, 5, [5, 6, 7]]], 8, .]
+                      Type: BinarySearchTree PositiveInteger
+
+Another approach is to first create an empty binary search tree of integers.
+
+  emptybst := empty()$BSTREE(INT)
+   [] 
+                      Type: BinarySearchTree Integer
+
+Insert the value 8.  This establishes 8 as the root of the binary
+search tree.  Values inserted later that are less than 8 get stored in
+the left subtree, others in the right subtree.
+
+  t1 := insert!(8,emptybst)
+   8 
+                      Type: BinarySearchTree Integer
+
+Insert the value 3. This number becomes the root of the left subtree
+of t1.  For optimal retrieval, it is thus important to insert the
+middle elements first.
+
+  insert!(3,t1)
+   [3, 8, .]
+                      Type: BinarySearchTree Integer
+
+We go back to the original tree t.  The leaves of the binary search
+tree are those which have empty left and right subtrees.
+
+  leaves t
+   [1, 4, 5, 7]
+                      Type: List PositiveInteger
+
+The operation split(k,t) returns a record containing the two subtrees:
+one with all elements "less" than k, another with elements "greater"
+than k.
+
+  split(3,t)
+   [less=[1, 2, .], greater=[[., 3, [4, 5, [5, 6, 7]]], 8, .]]
+              Type: Record(less: BinarySearchTree PositiveInteger,greater: 
+                           BinarySearchTree PositiveInteger)
+
+Define insertRoot to insert new elements by creating a new node.
+
+  insertRoot: (INT,BSTREE INT) -> BSTREE INT
+                      Type: Void
+
+The new node puts the inserted value between its "less" tree and
+"greater" tree.
+
+
+  insertRoot(x, t) ==
+    a := split(x, t)
+    node(a.less, x, a.greater)
+                      Type: Void
+
+
+Function buildFromRoot builds a binary search tree from a list
+of elements ls and the empty tree emptybst.
+
+  buildFromRoot ls == reduce(insertRoot,ls,emptybst)
+                      Type: Void
+
+Apply this to the reverse of the list lv.
+
+  rt := buildFromRoot reverse lv
+   [[[1, 2, . ], 3, [4, 5, [5, 6, 7]]], 8, .]
+                      Type: BinarySearchTree Integer
+
+Have Axiom check that these are equal.
+
+  (t = rt)@Boolean
+   true
+                      Type: Boolean
+
+See Also:
+o )show BinarySearchTree
+o $AXIOM/doc/src/algebra/tree.spad.dvi
+
+@
 <<domain BSTREE BinarySearchTree>>=
 )abbrev domain BSTREE BinarySearchTree
 ++ Description: BinarySearchTree(S) is the domain of
@@ -492,6 +696,198 @@ BinaryTournament(S: OrderedSet): Exports == Implementation where
 
 @
 \section{domain BBTREE BalancedBinaryTree}
+<<BalancedBinaryTree.input>>=
+-- tree.spad.pamphlet BalancedBinaryTree.input
+)spool BalancedBinaryTree.output
+)set message test on
+)set message auto off
+)clear all
+--S 1
+lm := [3,5,7,11]
+--R 
+--R
+--R   (1)  [3,5,7,11]
+--R                                                   Type: List PositiveInteger
+--E 1
+
+--S 2
+modTree(12,lm)
+--R 
+--R
+--R   (2)  [0,2,5,1]
+--R                                                           Type: List Integer
+--E 2
+
+--S 3
+t := balancedBinaryTree(#lm, 0)
+--R 
+--R
+--R   (3)  [[0,0,0],0,[0,0,0]]
+--R                                  Type: BalancedBinaryTree NonNegativeInteger
+--E 3
+
+--S 4
+setleaves!(t,lm)
+--R 
+--R
+--R   (4)  [[3,0,5],0,[7,0,11]]
+--R                                  Type: BalancedBinaryTree NonNegativeInteger
+--E 4
+
+--S 5
+mapUp!(t,_*)
+--R 
+--R
+--R   (5)  1155
+--R                                                        Type: PositiveInteger
+--E 5
+
+--S 6
+t
+--R 
+--R
+--R   (6)  [[3,15,5],1155,[7,77,11]]
+--R                                  Type: BalancedBinaryTree NonNegativeInteger
+--E 6
+
+--S 7
+mapDown!(t,12,_rem)
+--R 
+--R
+--R   (7)  [[0,12,2],12,[5,12,1]]
+--R                                  Type: BalancedBinaryTree NonNegativeInteger
+--E 7
+
+--S 8
+leaves %
+--R 
+--R
+--R   (8)  [0,2,5,1]
+--R                                                Type: List NonNegativeInteger
+--E 8
+
+--S 9
+squares := [x**2 rem m for x in % for m in lm]
+--R 
+--R
+--R   (9)  [0,4,4,1]
+--R                                                Type: List NonNegativeInteger
+--E 9
+
+--S 10
+chineseRemainder(%,lm)
+--R 
+--R
+--R   (10)  144
+--R                                                        Type: PositiveInteger
+--E 10
+)spool
+)lisp (bye)
+@
+<<BalancedBinaryTree.help>>=
+====================================================================
+BalancedBinaryTree examples
+====================================================================
+
+BalancedBinaryTrees(S) is the domain of balanced binary trees with
+elements of type S at the nodes.  A binary tree is either empty or
+else consists of a node having a value and two branches, each branch a
+binary tree.  A balanced binary tree is one that is balanced with
+respect its leaves.  One with 2^k leaves is perfectly "balanced": the
+tree has minimum depth, and the left and right branch of every
+interior node is identical in shape.
+
+Balanced binary trees are useful in algebraic computation for
+so-called "divide-and-conquer" algorithms.  Conceptually, the data
+for a problem is initially placed at the root of the tree.  The
+original data is then split into two subproblems, one for each
+subtree.  And so on.  Eventually, the problem is solved at the leaves
+of the tree.  A solution to the original problem is obtained by some
+mechanism that can reassemble the pieces.  In fact, an implementation
+of the Chinese Remainder Algorithm using balanced binary trees was
+first proposed by David Y. Y.  Yun at the IBM T. J.  Watson Research
+Center in Yorktown Heights, New York, in 1978.  It served as the
+prototype for polymorphic algorithms in Axiom.
+
+In what follows, rather than perform a series of computations with a
+single expression, the expression is reduced modulo a number of
+integer primes, a computation is done with modular arithmetic for each
+prime, and the Chinese Remainder Algorithm is used to obtain the
+answer to the original problem.  We illustrate this principle with the
+computation of 12^2 = 144.
+
+A list of moduli:
+
+  lm := [3,5,7,11]
+   [3,5,7,11]
+                      Type: PositiveInteger
+
+The expression modTree(n, lm) creates a balanced binary tree with leaf
+values n mod m for each modulus m in lm.
+
+  modTree(12,lm)
+   [0, 2, 5, 1]
+                      Type: List Integer
+
+Operation modTree does this using operations on balanced binary trees.
+We trace its steps.  Create a balanced binary tree t of zeros with
+four leaves.
+
+  t := balancedBinaryTree(#lm, 0)
+   [[0, 0, 0], 0, [0, 0, 0]]
+                      Type: BalancedBinaryTree NonNegativeInteger
+
+The leaves of the tree are set to the individual moduli.
+
+  setleaves!(t,lm)
+   [[3, 0, 5], 0, [7, 0, 11]]
+                      Type: BalancedBinaryTree NonNegativeInteger
+
+mapUp! to do a bottom-up traversal of t, setting each interior node to
+the product of the values at the nodes of its children.
+
+  mapUp!(t,_*)
+   1155 
+                      Type: PositiveInteger
+
+The value at the node of every subtree is the product of the moduli
+of the leaves of the subtree.
+
+  t
+   [[3, 15, 5], 1155, [7, 77, 11]]
+                      Type: BalancedBinaryTree NonNegativeInteger
+
+Operation mapDown!(t,a,fn) replaces the value v at each node of t by
+fn(a,v).
+
+  mapDown!(t,12,_rem)
+   [[0, 12, 2], 12, [5, 12, 1]]
+                      Type: BalancedBinaryTree NonNegativeInteger
+
+The operation leaves returns the leaves of the resulting tree.  In
+this case, it returns the list of 12 mod m for each modulus m.
+
+  leaves %
+   [0, 2, 5, 1]
+                      Type: List NonNegativeInteger
+
+Compute the square of the images of 12 modulo each m.
+
+  squares := [x**2 rem m for x in % for m in lm]
+   [0, 4, 4, 1]
+                      Type: List NonNegativeInteger
+
+Call the Chinese Remainder Algorithm to get the answer for 12^2.
+
+  chineseRemainder(%,lm)
+   144 
+                      Type: PositiveInteger
+
+See Also:
+o )show BalancedBinaryTree
+o $AXIOM/doc/src/algebra/tree.spad.dvi
+
+@
 <<domain BBTREE BalancedBinaryTree>>=
 )abbrev domain BBTREE BalancedBinaryTree
 ++ Description: \spadtype{BalancedBinaryTree(S)} is the domain of balanced
diff --git a/src/doc/Makefile.pamphlet b/src/doc/Makefile.pamphlet
index 7556528..cd17c11 100644
--- a/src/doc/Makefile.pamphlet
+++ b/src/doc/Makefile.pamphlet
@@ -146,7 +146,6 @@ syntax        trace      undo       what       while
 <<spadhelp.files>>=
 ${DVI}/spadhelp/spadhelp.files: ${IN}/spadhelp.pamphlet
 	@echo 9 making ${DVI}/spadhelp from ${IN}/spadhelp.pamphlet
-	@mkdir ${DVI}/spadhelp
 	@(cd ${DVI}/spadhelp ; \
           for i in ${SPADHELP} ; do \
             ${TANGLE} -R"$$i" ${IN}/spadhelp.pamphlet >$$i.help ; \
diff --git a/src/doc/book.pamphlet b/src/doc/book.pamphlet
index 7f74c97..4930c49 100644
--- a/src/doc/book.pamphlet
+++ b/src/doc/book.pamphlet
@@ -25004,7 +25004,7 @@ $$
 $$
 \returnType{Type: Record(monthsOld: Integer,gender: String)}
 
-Use \spadfunFrom{delete}{AssociationList} to destructively remove an
+Use \spadfunFrom{delete!}{AssociationList} to destructively remove an
 element of the association list.  Use
 \spadfunFrom{delete}{AssociationList} to return a copy of the
 association list with the element deleted.  The second argument is the
diff --git a/src/doc/spadhelp.pamphlet b/src/doc/spadhelp.pamphlet
index 54ea77c..f0e163d 100644
--- a/src/doc/spadhelp.pamphlet
+++ b/src/doc/spadhelp.pamphlet
@@ -1480,6 +1480,15 @@ parallel      pquit      quit       read       repeat     savesystem
 set           show       spool      suchthat   synonym    system     
 syntax        trace      undo       what       while
 
+Available algebra help topics are:
+
+AssociationList   BalancedBinaryTree   BasicOperator
+BinaryExpansion   BinarySearchTree     CardinalNumber
+CartesianTensor   Character            CharacterClass
+CliffordAlgebra   Complex              ContinuedFraction
+CycleIndicators   DeRhamComplex        DecimalExpansion
+
+
 @ 
 
 \section{command history}
diff --git a/src/input/Makefile.pamphlet b/src/input/Makefile.pamphlet
index 34850f2..6a8e7e0 100644
--- a/src/input/Makefile.pamphlet
+++ b/src/input/Makefile.pamphlet
@@ -361,7 +361,12 @@ REGRES= algaggr.regress algbrbf.regress  algfacob.regress alist.regress  \
 IN=     ${SRC}/input
 MID=	${INT}/input
 
-all: ${OUTS} ${ALGEBRA} ${REGRES}
+all: ${OUTS} ${ALGEBRA} ${REGRES} 
+	@ echo 0 starting algebra regression testing
+	@ (cd ${MID} ; \
+	  ${TANGLE} -t8 -R"algebra.regress" ${SRC}/algebra/Makefile.pamphlet \
+            >Makefile.algebra ; \
+          make -f Makefile.algebra )
 	@ echo 1 finished ${INT}/input
  
 %.input: ${IN}/%.input.pamphlet

\start
Date: Mon, 27 Aug 2007 02:37:46 -0500
From: Tim Daly
To: list
Subject: 20070819.01.tpd.patch applied to silver

diff --git a/changelog b/changelog
index 8579566..4b64859 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,15 @@
+20070819 tpd src/sman/Makefile rewrite to use bookvol6
+20070819 tpd src/sman/spadclient.c removed
+20070819 tpd src/sman/sman insert src/share/command.list
+20070819 tpd src/sman/nagman.c removed
+20070819 tpd src/sman/sman insert src/sman/nagman.c
+20070819 tpd src/sman/session.c removed
+20070819 tpd src/sman/sman insert src/sman/session.c
+20070819 tpd src/sman/spadclient.c removed
+20070819 tpd src/sman/sman insert src/sman/spadclient.c
+20070819 tpd src/sman/sman.c removed
+20070819 tpd src/sman/sman insert src/sman/sman.c
+20070819 tpd src/sman/sman start bookvol6, sman
 20070812 tpd src/doc/index.html added
 20070812 tpd src/algebra/Makefile newton.spad added
 20070812 tpd src/algebra/newton.spad added
diff --git a/src/sman/Makefile.pamphlet b/src/sman/Makefile.pamphlet
index 7c0ee4c..ca19ad0 100644
--- a/src/sman/Makefile.pamphlet
+++ b/src/sman/Makefile.pamphlet
@@ -31,13 +31,11 @@ INC=    ${SRC}/include
 LIB=	${OBJ}/${SYS}/lib
 
 # this is where the documentation ends up
-DOC=    ${MNT}/${SYS}/doc/src/sman
+DOC=    ${MNT}/${SYS}/doc
 CFLAGS=	${CCF} 
 LDFLAGS= -L${LIB} -lspad ${LDF}
 
-DOCFILES=${DOC}/session.c.dvi ${DOC}/nagman.c.dvi ${DOC}/sman.c.dvi \
-         ${DOC}/spadclient.c.dvi
-
+DOCFILES=${DOC}/bookvol6.dvi
 SMANOBJS= ${LIB}/libspad.a
 
 @
@@ -47,23 +45,15 @@ ${OUTLIB}/session: ${SMANOBJS} ${MIDOBJ}/session.o
 	@ echo 1 linking session
 	@ ${CC} -o ${OUTLIB}/session ${MIDOBJ}/session.o ${SMANOBJS} 
 
-${MID}/session.c: ${IN}/session.c.pamphlet
-	@ echo 2 making ${MID}/session.c from ${IN}/session.c.pamphlet
-	@ (cd ${MID} ; ${TANGLE} ${IN}/session.c.pamphlet >session.c )
+${MID}/session.c: ${IN}/bookvol6.pamphlet
+	@ echo 2 making ${MID}/session.c from ${IN}/bookvol6.pamphlet
+	@ (cd ${MID} ; \
+          ${TANGLE} -R"session" ${IN}/bookvol6.pamphlet >session.c )
 
 ${MIDOBJ}/session.o: ${MID}/session.c ${INC}/session.h1
 	@ echo 3 making ${MIDOBJ}/session.o from ${MID}/session.c
 	@ ( cd ${MIDOBJ} ; ${CC} -c ${CFLAGS} ${MID}/session.c -I${INC} )
 
-${DOC}/session.c.dvi: ${IN}/session.c.pamphlet 
-	@ echo 4 making ${DOC}/session.c.dvi from ${IN}/session.c.pamphlet
-	@ (cd ${DOC} ; \
-	cp ${IN}/session.c.pamphlet ${DOC} ; \
-	${DOCUMENT} ${NOISE} session.c ; \
-	rm -f ${DOC}/session.c.pamphlet ; \
-	rm -f ${DOC}/session.c.tex ; \
-	rm -f ${DOC}/session.c )
-
 @
 \section{nagman}
 Note that we do not build the nagman component as we do not have the
@@ -73,23 +63,15 @@ ${OUT}/nagman:	${SMANOBJS} ${MIDOBJ}/nagman.o
 	@ echo 5 linking nagman
 	@ ${CC} -o ${OUT}/nagman ${MIDOBJ}/nagman.o ${SMANOBJS} 
 
-${MID}/nagman.c: ${IN}/nagman.c.pamphlet
-	@ echo 6 making ${MID}/nagman.c from ${IN}/nagman.c.pamphlet
-	@ (cd ${MID} ; ${TANGLE} ${IN}/nagman.c.pamphlet >nagman.c )
+${MID}/nagman.c: ${IN}/bookvol6.pamphlet
+	@ echo 6 making ${MID}/nagman.c from ${IN}/bookvol6.pamphlet
+	@ (cd ${MID} ; \
+           ${TANGLE} -R"nagman" ${IN}/bookvol6.pamphlet >nagman.c )
 
 ${MIDOBJ}/nagman.o: ${MID}/nagman.c ${INC}/nagman.h1
 	@ echo 7 making ${MIDOBJ}/nagman.o from ${MID}/nagman.c
 	@ ( cd ${MIDOBJ} ; ${CC} -c ${CFLAGS} ${MID}/nagman.c -I${INC} )
 
-${DOC}/nagman.c.dvi: ${IN}/nagman.c.pamphlet 
-	@ echo 8 making ${DOC}/nagman.c.dvi from ${IN}/nagman.c.pamphlet
-	@ (cd ${DOC} ; \
-	cp ${IN}/nagman.c.pamphlet ${DOC} ; \
-	${DOCUMENT} ${NOISE} nagman.c ; \
-	rm -f ${DOC}/nagman.c.pamphlet ; \
-	rm -f ${DOC}/nagman.c.tex ; \
-	rm -f ${DOC}/nagman.c )
-
 @
 \section{spadclient}
 <<spadclient>>=
@@ -97,23 +79,15 @@ ${OUTLIB}/spadclient: ${SMANOBJS} ${MIDOBJ}/spadclient.o
 	@ echo 9 linking spadclient
 	@ ${CC} -o ${OUTLIB}/spadclient ${MIDOBJ}/spadclient.o  ${SMANOBJS} 
 
-${MID}/spadclient.c: ${IN}/spadclient.c.pamphlet
-	@ echo 10 making ${MID}/spadclient.c from ${IN}/spadclient.c.pamphlet
-	@ (cd ${MID} ; ${TANGLE} ${IN}/spadclient.c.pamphlet >spadclient.c )
+${MID}/spadclient.c: ${IN}/bookvol6.pamphlet
+	@ echo 10 making ${MID}/spadclient.c from ${IN}/bookvol6.pamphlet
+	@ (cd ${MID} ; \
+           ${TANGLE} -R"spadclient" ${IN}/bookvol6.pamphlet >spadclient.c )
 
 ${MIDOBJ}/spadclient.o: ${MID}/spadclient.c ${INC}/spadclient.h1
 	@ echo 11 making ${MIDOBJ}/spadclient.o from ${MID}/spadclient.c
 	@ ( cd ${MIDOBJ} ; ${CC} -c ${CFLAGS} ${MID}/spadclient.c -I${INC} )
 
-${DOC}/spadclient.c.dvi: ${IN}/spadclient.c.pamphlet 
-	@ echo 12 making ${DOC}/spadclient.c.dvi from ${IN}/spadclient.c.pamphlet
-	@ (cd ${DOC} ; \
-	cp ${IN}/spadclient.c.pamphlet ${DOC} ; \
-	${DOCUMENT} ${NOISE} spadclient.c ; \
-	rm -f ${DOC}/spadclient.c.pamphlet ; \
-	rm -f ${DOC}/spadclient.c.tex ; \
-	rm -f ${DOC}/spadclient.c )
-
 @
 \section{sman}
 <<sman>>=
@@ -121,26 +95,28 @@ ${OUT}/sman: ${SMANOBJS} ${MIDOBJ}/sman.o
 	@ echo 13 linking sman
 	@ ${CC} -o ${OUT}/sman ${MIDOBJ}/sman.o ${SMANOBJS} 
 
-${MID}/sman.h: ${IN}/sman.c.pamphlet
-	@ echo 00 making ${MID}/sman.h from ${IN}/sman.c.pamphlet
-	@ (cd ${MID} ; ${TANGLE} -R"sman.h" ${IN}/sman.c.pamphlet >sman.h )
+${MID}/sman.h: ${IN}/bookvol6.pamphlet
+	@ echo 00 making ${MID}/sman.h from ${IN}/bookvol6.pamphlet
+	@ (cd ${MID} ; \
+           ${TANGLE} -R"sman.h" ${IN}/bookvol6.pamphlet >sman.h )
 
-${MID}/sman.c: ${MID}/sman.h ${IN}/sman.c.pamphlet
-	@ echo 14 making ${MID}/sman.c from ${IN}/sman.c.pamphlet
-	@ (cd ${MID} ; ${TANGLE} ${IN}/sman.c.pamphlet >sman.c )
+${MID}/sman.c: ${MID}/sman.h ${IN}/bookvol6.pamphlet
+	@ echo 14 making ${MID}/sman.c from ${IN}/bookvol6.pamphlet
+	@ (cd ${MID} ; \
+           ${TANGLE} -R"sman" ${IN}/bookvol6.pamphlet >sman.c )
 
 ${MIDOBJ}/sman.o: ${MID}/sman.c ${INC}/sman.h1
 	@ echo 15 making ${MIDOBJ}/sman.o from ${MID}/sman.c
 	@ ( cd ${MIDOBJ} ; ${CC} -I${INC} -I${MID} -c ${CFLAGS} ${MID}/sman.c )
 
-${DOC}/sman.c.dvi: ${IN}/sman.c.pamphlet 
-	@ echo 16 making ${DOC}/sman.c.dvi from ${IN}/sman.c.pamphlet
+${DOC}/bookvol6.dvi: ${IN}/bookvol6.pamphlet 
+	@ echo 16 making ${DOC}/bookvol6.dvi from ${IN}/bookvol6.pamphlet
 	@ (cd ${DOC} ; \
-	cp ${IN}/sman.c.pamphlet ${DOC} ; \
-	${DOCUMENT} ${NOISE} sman.c ; \
-	rm -f ${DOC}/sman.c.pamphlet ; \
-	rm -f ${DOC}/sman.c.tex ; \
-	rm -f ${DOC}/sman.c )
+	cp ${IN}/bookvol6.pamphlet ${DOC} ; \
+	${DOCUMENT} ${NOISE} bookvol6 ; \
+	rm -f ${DOC}/bookvol6.pamphlet ; \
+	rm -f ${DOC}/bookvol6.tex ; \
+	rm -f ${DOC}/bookvol6 )
 
 @
 <<*>>=
diff --git a/src/sman/bookvol6.pamphlet b/src/sman/bookvol6.pamphlet
new file mode 100644
index 0000000..4ab4355
--- /dev/null
+++ b/src/sman/bookvol6.pamphlet
@@ -0,0 +1,6543 @@
+\documentclass{book}
+\usepackage{axiom}
+\usepackage{makeidx}
+\makeindex
+\usepackage{graphicx}
+\begin{document}
+\begin{titlepage}
+\center{\includegraphics{ps/axiomfront.ps}}
+\vskip 0.1in
+\includegraphics{ps/bluebayou.ps}\\
+\vskip 0.1in
+{\Huge{The 30 Year Horizon}}
+\vskip 0.1in
+$$
+\begin{array}{lll}
+Manuel\ Bronstein      & William\ Burge   & Timothy\ Daly \\
+James\ Davenport       & Michael\ Dewar   & Martin\ Dunstan \\
+Albrecht\ Fortenbacher & Patrizia\ Gianni & Johannes\ Grabmeier \\
+Jocelyn\ Guidry        & Richard\ Jenks   & Larry\ Lambe \\
+Michael\ Monagan       & Scott\ Morrison  & William\ Sit \\
+Jonathan\ Steinbach    & Robert\ Sutor    & Barry\ Trager \\
+Stephen\ Watt          & Jim\ Wen         & Clifton\ Williamson
+\end{array}
+$$
+\center{\large{VOLUME 6: SMAN}}
+\end{titlepage}
+\pagenumbering{roman}
+\begin{verbatim}
+Portions Copyright (c) 2005 Timothy Daly
+
+The Blue Bayou image Copyright (c) 2004 Jocelyn Guidry
+
+Portions Copyright (c) 2004 Martin Dunstan
+
+Portions Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+All rights reserved.
+
+This book and the Axiom software is licensed as follows:
+
+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.
+
+\end{verbatim}
+
+Inclusion of names in the list of credits is based on historical
+information and is as accurate as possible. Inclusion of names
+does not in any way imply an endorsement but represents historical
+influence on Axiom development.
+\vfill
+\eject
+\begin{tabular}{lll}
+Cyril Alberga         & Roy Adler             & Richard Anderson\\
+George Andrews        & Henry Baker           & Stephen Balzac\\
+Yurij Baransky        & David R. Barton       & Gerald Baumgartner\\
+Gilbert Baumslag      & Fred Blair            & Vladimir Bondarenko\\
+Mark Botch            & Alexandre Bouyer      & Peter A. Broadbery\\
+Martin Brock          & Manuel Bronstein      & Florian Bundschuh\\
+William Burge         & Quentin Carpent       & Bob Caviness\\
+Bruce Char            & Cheekai Chin          & David V. Chudnovsky\\
+Gregory V. Chudnovsky & Josh Cohen            & Christophe Conil\\
+Don Coppersmith       & George Corliss        & Robert Corless\\
+Gary Cornell          & Meino Cramer          & Claire Di Crescenzo\\
+Timothy Daly Sr.      & Timothy Daly Jr.      & James H. Davenport\\
+Jean Della Dora       & Gabriel Dos Reis      & Michael Dewar\\
+Claire DiCrescendo    & Sam Dooley            & Lionel Ducos\\
+Martin Dunstan        & Brian Dupee           & Dominique Duval\\
+Robert Edwards        & Heow Eide-Goodman     & Lars Erickson\\
+Richard Fateman       & Bertfried Fauser      & Stuart Feldman\\
+Brian Ford            & Albrecht Fortenbacher & George Frances\\
+Constantine Frangos   & Timothy Freeman       & Korrinn Fu\\
+Marc Gaetano          & Rudiger Gebauer       & Kathy Gerber\\
+Patricia Gianni       & Holger Gollan         & Teresa Gomez-Diaz\\
+Laureano Gonzalez-Vega& Stephen Gortler       & Johannes Grabmeier\\
+Matt Grayson          & James Griesmer        & Vladimir Grinberg\\
+Oswald Gschnitzer     & Jocelyn Guidry        & Steve Hague\\
+Vilya Harvey          & Satoshi Hamaguchi     & Martin Hassner\\
+Ralf Hemmecke         & Henderson             & Antoine Hersen\\
+Pietro Iglio          & Richard Jenks         & Kai Kaminski\\
+Grant Keady           & Tony Kennedy          & Paul Kosinski\\
+Klaus Kusche          & Bernhard Kutzler      & Larry Lambe\\
+Frederic Lehobey      & Michel Levaud         & Howard Levy\\
+Rudiger Loos          & Michael Lucks         & Richard Luczak\\
+Camm Maguire          & Bob McElrath          & Michael McGettrick\\
+Ian Meikle            & David Mentre          & Victor S. Miller\\
+Gerard Milmeister     & Mohammed Mobarak      & H. Michael Moeller\\
+Michael Monagan       & Marc Moreno-Maza      & Scott Morrison\\
+Mark Murray           & William Naylor        & C. Andrew Neff\\
+John Nelder           & Godfrey Nolan         & Arthur Norman\\
+Jinzhong Niu          & Michael O'Connor      & Kostas Oikonomou\\
+Julian A. Padget      & Bill Page             & Jaap Weel\\
+Susan Pelzel          & Michel Petitot        & Didier Pinchon\\
+Claude Quitte         & Norman Ramsey         & Michael Richardson\\
+Renaud Rioboo         & Jean Rivlin           & Nicolas Robidoux\\
+Simon Robinson        & Michael Rothstein     & Martin Rubey\\
+Philip Santas         & Alfred Scheerhorn     & William Schelter\\
+Gerhard Schneider     & Martin Schoenert      & Marshall Schor\\
+Fritz Schwarz         & Nick Simicich         & William Sit\\
+Elena Smirnova        & Jonathan Steinbach    & Christine Sundaresan\\
+Robert Sutor          & Moss E. Sweedler      & Eugene Surowitz\\
+James Thatcher        & Baldir Thomas         & Mike Thomas\\
+Dylan Thurston        & Barry Trager          & Themos T. Tsikas\\
+Gregory Vanuxem       & Bernhard Wall         & Stephen Watt\\
+Juergen Weiss         & M. Weller             & Mark Wegman\\
+James Wen             & Thorsten Werther      & Michael Wester\\
+John M. Wiley         & Berhard Will          & Clifton J. Williamson\\
+Stephen Wilson        & Shmuel Winograd       & Robert Wisbauer\\
+Sandra Wityak         & Waldemar Wiwianka     & Knut Wolf\\
+Clifford Yapp         & David Yun             & Richard Zippel\\
+Evelyn Zoernack       & Bruno Zuercher        & Dan Zwillinger 
+\end{tabular}
+\eject
+\tableofcontents
+\vfill
+\eject
+\setlength{\parindent}{0em}
+\setlength{\parskip}{1ex}
+{\Large{\bf New Foreword}}
+\vskip .25in
+
+On October 1, 2001 Axiom was withdrawn from the market and ended
+life as a commercial product.
+On September 3, 2002 Axiom was released under the Modified BSD
+license, including this document.
+On August 27, 2003 Axiom was released as free and open source
+software available for download from the Free Software Foundation's
+website, Savannah.
+
+Work on Axiom has had the generous support of the Center for 
+Algorithms and Interactive Scientific Computation (CAISS) at
+City College of New York. Special thanks go to Dr. Gilbert 
+Baumslag for his support of the long term goal.
+
+The online version of this documentation is roughly 1000 pages.
+In order to make printed versions we've broken it up into three
+volumes. The first volume is tutorial in nature. The second volume
+is for programmers. The third volume is reference material. We've
+also added a fourth volume for developers. All of these changes
+represent an experiment in print-on-demand delivery of documentation.
+Time will tell whether the experiment succeeded.
+
+Axiom has been in existence for over thirty years. It is estimated to
+contain about three hundred man-years of research and has, as of
+September 3, 2003, 143 people listed in the credits. All of these
+people have contributed directly or indirectly to making Axiom
+available.  Axiom is being passed to the next generation. I'm looking
+forward to future milestones.
+
+With that in mind I've introduced the theme of the ``30 year horizon''.
+We must invent the tools that support the Computational Mathematician
+working 30 years from now. How will research be done when every bit of
+mathematical knowledge is online and instantly available? What happens
+when we scale Axiom by a factor of 100, giving us 1.1 million domains?
+How can we integrate theory with code? How will we integrate theorems
+and proofs of the mathematics with space-time complexity proofs and
+running code? What visualization tools are needed? How do we support
+the conceptual structures and semantics of mathematics in effective
+ways? How do we support results from the sciences? How do we teach
+the next generation to be effective Computational Mathematicians?
+
+The ``30 year horizon'' is much nearer than it appears.
+
+\vskip .25in
+%\noindent
+Tim Daly\\
+CAISS, City College of New York\\
+November 10, 2003 ((iHy))
+\vfill
+\eject
+\pagenumbering{arabic}
+\setcounter{chapter}{0} % Chapter 1
+\chapter{Overview}
+The superman process, called sman, is normally invoked from the
+axiom shell script in order to start a tree of subprocesses.
+
+\chapter{Support Routines}
+\section{Command Completion}
+Hyperdoc has the ability to do command completion. The known commands
+are listed, one entry per line, in a file called command.list. 
+\chapter{The {\tt viewman} program}
+<<the viewman command line>>=
+char *GraphicsProgram = "$AXIOM/lib/viewman";
+@
+\chapter{The {\tt nagman} program}
+<<the nagman command line>>=
+char *NagManagerProgram = "$AXIOM/lib/nagman";
+@
+\section{nag.x}
+<<nag.nag.x>>=
+
+/*
+ * msg.x: Remote message printing protocol
+ */
+const MAXASP = 10;
+
+/*
+ * the nago structure is essentially a variable length string
+ */
+
+struct nago {
+  opaque z <>;
+  };
+struct nagerr {
+nago p;
+nago q;
+};
+
+struct host{
+nago h <>;
+};
+
+struct nagst {
+
+/* Okay, if you understand this bit you know the essentials of how the link
+ * works. h <> is an array of nago, which is an array of fortran source 
+ * code, the length of the array being the no. of asps (0 for most routines).
+ * y is the actual (XDR) input data for the routine. nm is the name of the
+ * routine. id is a tag identifying the host/axiom session. Finally per is a
+ * number telling whether or not to erase old fortran files on the remote
+ * machine (persistence - the number per distinct fortran files will be 
+ * stored, any more than this and earlier ones will be deleted.
+ */
+
+  nago h <>;
+  nago y;
+  nago nm;
+  nago id;
+  int per;
+  };
+program NAGPROG {
+   version NAGVERS {
+       nagerr CALLNAG(nagst) = 1;
+       nago NAGMON(int)=2;
+       void AXEND(nago)=3;
+   } = 1;
+/*
+ * the following number is very important. It tells the 
+ * portmapper what number to register the nag daemon under.
+ * There are rules about which number to pick - check SUN
+ * technical info for more details
+ */
+} = 100088;
+
+
+@
+\section{nagman}
+\subsection{includes}
+<<nag.includes>>=
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h> 
+#include <string.h>
+#include <errno.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <rpc/rpc.h>     /* always needed */ 
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include "nag.h"  /* generated by rpcgen */
+#include "com.h"
+#include "bsdsignal.h"
+#include "sockio-c.h1"
+#include "bsdsignal.h1"
+#include "nagman.h1"
+
+@
+\subsection{variables}
+<<nag.variables>>=
+#ifdef ALPHAplatform
+extern int getdomainname( char *, int );
+#endif
+#ifdef SUN4OS5platform
+extern int getdomainname( char *, int );
+extern int gethostname( char *, int );
+#endif
+
+nagerr * callnag_1(nagst *,CLIENT *);
+nago * nagmon_1(int *,CLIENT *);
+void * axend_1(nago *,CLIENT *);
+
+#define DO 1
+#define DONT 0
+
+int hnum, vmax;
+char *datafile, *resultsfile;
+
+struct hostnode {
+  char * name;
+  struct hostnode *next; 
+} *hlist=NULL;
+
+nagst nag4;
+Sock *sock1;
+
+@
+\subsection{term}
+this code runs when the user quits axiom. before nagman dies, it does
+an rpc call to nagd to tell it to get rid of files etc. The rpc call in
+question is [[axend_1]]
+we also send a USR1 to sman to beget another nagman
+<<nag.term>>=
+static void 
+term(int sig)
+{
+  CLIENT *cld;
+  void *res;
+  struct hostnode *pnode;
+
+#ifndef HP9platform /* can't figure out a way to do this on HP/UX 9 */
+  kill(atoi(getenv("SPADNUM")) , SIGUSR1);
+#endif
+
+
+  if(hnum!=0)
+    {
+      unlink(datafile);
+      unlink(resultsfile);
+    }
+
+  for(pnode=hlist;pnode!=NULL;pnode=pnode->next)
+    {
+      cld=clnt_create(pnode->name,NAGPROG, NAGVERS, "tcp");
+      if (cld == NULL)
+	goto NOHOST;
+
+      res=axend_1(&(nag4.id),cld);
+    NOHOST:
+      clnt_destroy(cld);
+    }
+  exit(0);
+}
+
+@
+\subsection{size\_of\_file}
+<<nag.sizeoffile>>=
+static long 
+size_of_file(char *filename)
+{
+  struct stat buf_stat;
+
+  stat(filename,&buf_stat);
+  return (buf_stat.st_size);
+
+}
+
+@
+\subsection{rpcloop}
+<<nag.rpcloop>>=
+static void 
+rpcloop(void)
+{
+  CLIENT *cl;
+  int res,j,v=0,u,showMessage;
+  long i;
+  register struct hostent *alias1, *alias2;
+  struct in_addr *addrnum;
+  u_long junk;
+  struct timeval tv;
+  nagerr *result;
+  char *Buf , *buf1;
+  char *ffile[MAXASP];
+  char routine[12], naghost[256];
+  FILE *nfp1, *nfp2, *nfp3;
+  struct hostnode *phost;
+  int fd;
+  
+  for (;;)
+    {
+      
+      if((Buf=get_string(sock1))==NULL) term(1); /* one string carries all */
+      
+      if(hnum!=0)
+	{
+	  /* call parameters */
+	  free(nag4.nm.z.z_val); /* the routine name */
+	  free(nag4.y.z.z_val);  /* the XDR data */
+	  for(i=0;i<v;i++)
+	    {
+	      unlink(ffile[i]);
+	      free(ffile[i]); /* the asp filenames */
+	      free(nag4.h.h_val[i].z.z_val); /* the asps themselves*/
+	    }
+	  free(nag4.h.h_val); /* the asps array */
+	  unlink(datafile);
+	  unlink(resultsfile);
+	  free(resultsfile);
+	  free(datafile);
+	  vmax= (v>vmax)? v : vmax;
+	}
+      
+      
+      
+      
+      buf1=strtok(Buf," ");
+      if (buf1) strcpy(naghost,buf1);
+      else printf("can't parse the naghost\n");
+      /* INFO         printf("%s\n",naghost);*/
+      
+      buf1=strtok(NULL," ");
+      if (buf1) strcpy(routine,buf1);
+      else printf("can't parse the routine\n");
+      /* INFO         printf("%s\n",routine);*/
+      
+      /* make copy of filenames because we will reuse Buf before deleting the files*/
+      buf1=strtok(NULL," ");
+      if (buf1) resultsfile=strdup(buf1);
+      else printf("can't parse the resultsfile file\n");	
+      /* INFO         printf("%s\n",resultsfile);*/
+      
+      buf1=strtok(NULL," ");  
+      if (buf1) datafile=strdup(buf1); 
+      else printf("can't parse the datafile file\n");  
+      /* INFO         printf("%s\n",datafile);*/
+      
+      buf1=strtok(NULL," ");
+      if (buf1) nag4.per=atoi(buf1);
+      else printf("can't parse the persistence\n");
+      /* INFO         printf("%d\n",nag4.per);*/
+      
+      buf1=strtok(NULL," ");
+      if (buf1) {
+	if (!strcmp(buf1,"on")) showMessage=DO;
+	else showMessage=DONT;
+      }
+      else printf("can't parse the messages flag\n");
+      /* INFO         printf("%s\n",buf1);*/
+      
+      v=0; /* asp counter */
+      while( (buf1=strtok(NULL," ")) )
+	{
+	  ffile[v++]=strdup(buf1);
+	  /* INFO 	      	printf("%s\n",ffile[v-1]);*/
+	}
+      
+      /* INFO  	printf("number of asps seen %d\n",v);*/
+      
+      if(showMessage==DO) printf("nagman:acknowledging request for %s\n",routine);
+      
+      res=0;  /* prepare result integer to be sent to Lisp */
+      
+      if((nfp3=fopen(resultsfile,"w"))==NULL)
+	{
+	  printf("can't open output file\n");
+	  goto END;
+	}
+      
+      /* nag4.h is the XDR array of asp text */
+      nag4.h.h_len=v;
+      nag4.h.h_val=(nago *)malloc((v)*sizeof(nago));
+      
+      
+      /* get asp text in call argument */
+      for(u=0;u<v;u++)
+	{
+	  /* this should be done by mmap */
+	  if((nfp1=fopen(ffile[u],"r"))==NULL)
+	    {
+	      fprintf(stderr,"can't open asp file %s\n",ffile[u]);
+	      fclose(nfp1);
+	      goto END;
+	    }
+	  fclose(nfp1);
+	  i=size_of_file(ffile[u]);
+
+	  /* allocs memory for the file */
+	  nag4.h.h_val[u].z.z_val= (char *)malloc((i+1)*sizeof(char)); 
+	  
+	  fd=open(ffile[u],O_RDONLY);
+	  read(fd,nag4.h.h_val[u].z.z_val,i);
+	  close(fd);
+	  /* make null-term. string */
+	  nag4.h.h_val[u].z.z_val[i]='\0'; 
+	  /* set the length */
+	  nag4.h.h_val[u].z.z_len=strlen(nag4.h.h_val[u].z.z_val); 
+	}
+      
+      
+      nag4.nm.z.z_val=strdup(routine);
+      nag4.nm.z.z_len=strlen(routine);
+      
+      /* get XDR data in call argument */
+      /* should be done by mmap */
+      if((nfp2=fopen(datafile,"r"))==NULL)
+	{
+	  fprintf(stderr,"can't open data file\n");
+	  fclose(nfp2);
+	  goto END;
+	}
+      
+      fclose(nfp2);
+      i=size_of_file(datafile);
+      nag4.y.z.z_val=(char *)malloc(i*sizeof(char));
+      
+      fd=open(datafile,O_RDONLY);
+      read(fd,nag4.y.z.z_val,i);
+      close(fd);
+      nag4.y.z.z_len=i;
+      
+      
+      /*
+       * Create client "handle" used for calling MESSAGEPROG on
+       * the server designated on the command line.  We tell
+       * the RPC package to use the "tcp" protocol when
+       * contacting the server.
+       */
+      
+      /* update naghost by lookup */
+      
+      if ((junk = inet_addr(naghost))!=-1)
+	{
+	  addrnum=(struct in_addr *)junk;
+	  if((alias2=gethostbyaddr((char *)&addrnum,
+				   sizeof(addrnum),
+				   AF_INET))!=NULL)
+	    strcpy(naghost,alias2->h_name);
+	  else
+	    if((alias1=gethostbyname(naghost))!=NULL)
+	      strcpy(naghost,alias1->h_name);
+	}
+      else
+	if((alias1=gethostbyname(naghost))!=NULL)
+	  strcpy(naghost,alias1->h_name);
+      
+      
+      
+      
+      cl = clnt_create(naghost, NAGPROG, NAGVERS, "tcp");
+      if (cl == NULL)
+	{
+	  /*
+	   * Couldn't establish connection with server.
+	   * Print error message and die.
+	   */
+	  clnt_pcreateerror(naghost);
+	  goto END;
+	}
+      else
+	if (showMessage==DO)
+	  printf("nagman:connection successful to %s\n",naghost);
+      
+      /*
+       * this number here sets the "timeout" for the rpc call. after this number
+       * of seconds, the call will quit if no response is received
+       *
+       */
+      
+      tv.tv_sec=1000000;
+      tv.tv_usec=0;
+      clnt_control(cl,CLSET_TIMEOUT,(char *)&tv);
+      
+      
+      result = callnag_1(&nag4, cl);
+      
+      for(phost=hlist;phost!=NULL;phost=phost->next)
+	{
+	  /*
+	   * hlist is the "hostlist" of sites that have been contacted by nagman.
+	   * here we check if this call is contacting a new site, and if so add it
+	   * to the hostlist
+	   *
+	   */
+	  
+	  if(!strcmp(phost->name,naghost))
+	    goto SKIP;
+	}
+      
+      if(hnum==0) {
+	hlist=(struct hostnode *)malloc(sizeof(struct hostnode));
+	hlist->name=strdup(naghost);
+	hlist->next=NULL;
+      }
+      
+      else {
+	phost=(struct hostnode *)malloc(sizeof(struct hostnode));
+	phost->name=strdup(naghost);
+	phost->next=hlist;
+	hlist=phost;
+      }
+      hnum++;
+      
+      
+    SKIP:
+      if (result == NULL)
+	{
+	  /*
+	   * An error occurred while calling the server.
+	   * Print error message and die.
+	   */
+	  if (showMessage==DO)
+	    printf("nagman:no results (error) from %s\n",naghost);
+	  clnt_perror(cl,naghost);
+	  clnt_destroy(cl);
+	  goto END;
+	}
+      
+      /*
+       * (*result).p is the part of the result with the XDRed results in it 
+       * (numbers). (*result).q is the part with (text) error messages that 
+       * have come from the NAG library. If there is neither an XDR result,
+       * nor a text error message from the library, then something is wrong
+       * so we just print out the "no result or error returned" message.
+       *
+       */
+      
+      else if ((*result).p.z.z_len==0)
+	{
+	  if((*result).q.z.z_len==0)
+	    {
+	      if (showMessage==DO)
+		printf("nagman:empty result (error) from %s\n",naghost);
+	      clnt_destroy(cl);
+	      goto END;
+	    }
+	  else
+	    {
+	      if (showMessage==DO)
+		printf("nagman:receiving results from %s\n\n",naghost);
+	      for(j=0;j<(*result).q.z.z_len;j++)
+		printf("%c",(*result).q.z.z_val[j]);
+	      clnt_destroy(cl);
+	      goto END;
+	    }
+	}
+      else
+	if (showMessage==DO)
+	  printf("nagman:receiving results from %s\n\n",naghost);
+      
+      if (showMessage==DO)
+	fwrite(result->q.z.z_val,sizeof(char),result->q.z.z_len,stdout);
+      
+      /*INFO		printf("\nRESULTS of length %d\n",(*result).p.z.z_len);*/
+      
+      fwrite(result->p.z.z_val,sizeof(char),result->p.z.z_len, nfp3);
+      res=1;
+      clnt_destroy(cl);
+      
+      /*
+       * in case of any type of error, a goto END in the above code causes
+       * nagman to skip here and return to AXIOM
+       *
+       */
+      
+      
+    END:
+      fclose(nfp3);
+      /*
+       * if everything has gone alright, send_int returns the integer res=1. If
+       * not it returns res=0. This is detected by the boot code which acts 
+       * accordingly.
+       */
+      send_int(sock1,res);
+      free(Buf);
+    }
+  
+  
+}
+
+@
+\subsection{catchSignals}
+catchSignals sets up signal handling. If nagman gets a sigterm it does not
+die but goes back to rpcloop
+<<nag.catchSignals>>=
+static void 
+catchSignals(void)
+{
+  bsdSignal(SIGTERM,term,RestartSystemCalls);
+  bsdSignal(SIGSEGV,term,RestartSystemCalls);
+}
+
+@
+\subsection{main nagman}
+<<nag.main>>=
+void 
+main(int argc,char **argv)
+{
+  char this[256],*hname,*dname,*spadnum;
+  int stat;
+ 
+  catchSignals();
+  stat=gethostname(this,256);
+  if (stat!=0) perror("gethostname");
+  hname=strdup(this);
+
+  stat=getdomainname(this,256);
+  if (stat!=0) perror("getdomainname");
+  dname=strdup(this);
+  spadnum=getenv("SPADNUM");
+  if (spadnum==0) {
+    fprintf(stderr,"nagman error: SPADNUM is not in the environment\n");
+    exit(0);
+  }
+
+  /* some machines return a full name from hostname 
+     need to check hname has a . in it */
+
+  if  (strchr(hname,'.'))
+    /* '.' found */
+    sprintf(this,"%s_%i",hname,atoi(spadnum));
+  else
+    /* substring not found */
+    sprintf(this,"%s.%s_%i",hname,dname,atoi(spadnum));
+
+  /* this must contain the Internet address of the current host */
+  nag4.id.z.z_val=strdup(this);
+  nag4.id.z.z_len=strlen(nag4.id.z.z_val);
+  hnum=0;
+  vmax=0;
+  /*
+   * this line sets up a socket for communication with the lisp
+   */
+
+  sock1 = connect_to_local_server(SpadServer, DebugWindow, 120 /*seconds*/);
+  if (!sock1) exit(0);
+
+  rpcloop();
+}
+
+@
+\subsection{nagman}
+<<nagman>>=
+#define _NAGMAN_C
+<<nag.includes>>
+<<nag.variables>>
+<<nag.term>>
+<<nag.sizeoffile>>
+<<nag.rpcloop>>
+<<nag.catchSignals>>
+<<nag.main>>
+@
+
+\chapter{The {\tt hypertex} program}
+<<the hypertex command line>>=
+char *HypertexProgram = "$AXIOM/bin/hypertex -s";
+@
+\chapter{The {\tt clef} program}
+<<the clef command line>>=
+char *ClefProgram = "$AXIOM/bin/clef -f $AXIOM/lib/command.list -e ";
+@
+\chapter{The {\tt session} program}
+<<the session manager command line>>=
+char *SessionManagerProgram = "$AXIOM/lib/session";
+@
+\section{session}
+\subsection{includes}
+<<ses.includes>>=
+#include <stdlib.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#ifdef SGIplatform
+#include <bstring.h>
+#endif
+#include "com.h"
+#include "bsdsignal.h"
+#include "sockio-c.h1"
+#include "bsdsignal.h1"
+#include "session.h1"
+
+@
+\subsection{variables}
+<<ses.variables>>=
+#define BufSize		4096	/* size of communication buffer */
+
+typedef struct sock_list {      /* linked list of Sock */
+  Sock Socket;
+  struct sock_list *next;
+} Sock_List;
+
+Sock *spad_io = (Sock *) 0;	   /* to_server socket for SessionIO */
+Sock *spad_server = (Sock *) 0;    /* to_server socket for SpadServer    */
+Sock *menu_client = (Sock *) 0;	   /* to_client socket for MenuServerName  */
+Sock *active_session = (Sock *) 0; /* pointer to currently active session */
+
+Sock_List *plSock = (Sock_List *) 0;
+
+char big_bad_buf[BufSize];	/* big I/O buffer */
+int num_active_clients = 0;	/* number of InterpWindows attached */
+int reading_output = 0;
+fd_set session_socket_mask;
+
+@
+\subsection{usr1\_handler}
+<<ses.usr1handler>>=
+static void 
+usr1_handler(int sig)
+{
+  return;
+}
+
+@
+\subsection{usr2\_handler}
+SIGUSR2 is generated by spadclients.
+We interpret it as an interrupt for the Lisp.
+<<ses.usr2handler>>=
+static void 
+usr2_handler(int sig)
+{
+  send_signal(spad_server, SIGINT);
+  return;
+}
+
+@
+\subsection{term\_handler}
+<<ses.termhandler>>=
+static void 
+term_handler(int sig)
+{
+  exit(1);
+}
+
+@
+\subsection{pr}
+<<ses.pr>>=
+static void
+pr()
+{
+  Sock_List *pSock;
+  
+  fprintf(stderr,"The socket list:\n");
+  for(pSock=plSock;pSock!=(Sock_List *)0;pSock=pSock->next){
+    fprintf(stderr,"(%d,%d,%d)\t",
+      pSock->Socket.pid, 2<<(pSock->Socket.socket), pSock->Socket.frame);
+  }
+  fprintf(stderr,"\n");
+}
+
+@
+\subsection{close\_client}
+<<ses.closeclient>>=
+static void
+close_client(int frame)
+{
+  Sock_List *pSock,*locSock;
+  int socket_fd;
+  
+  /* we will check for frame equality,
+     kill with send_signal,
+     notify HyperTex so that it updates its list (if it's a spadbuf),
+     repair the list,
+     unset the active_session,
+     update num_active_clients
+     */
+  
+  
+  /* first check head */
+#ifdef DEBUG
+fprintf(stderr,"close_client(%d)\n",frame);
+#endif
+  
+  if ( (plSock) && (plSock->Socket.frame == frame) ){
+    socket_fd = plSock->Socket.socket;
+    send_signal((Sock *)plSock, SIGTERM);
+    if ( menu_client != (Sock *) 0){
+      send_int(menu_client,CloseClient);
+      send_int(menu_client,(*plSock).Socket.pid);
+    } 
+#ifdef DEBUG
+fprintf(stderr,"trying to clear %u\n",socket_fd);
+#endif
+    FD_CLR(socket_fd,&session_socket_mask);
+    locSock = plSock;
+    if ((*plSock).next == (Sock_List *) 0) 
+      {plSock = (Sock_List *) 0;}
+    else
+      {plSock = plSock->next;}
+    active_session = (Sock *) 0;
+    num_active_clients--;
+    free(locSock);
+  }
+  
+  /* now check the rest */
+  
+  else {
+    for (pSock=plSock; pSock->next != (Sock_List *) 0 ; pSock=pSock->next)
+      if (pSock->next->Socket.frame == frame){
+	socket_fd = pSock->next->Socket.socket;
+	send_signal((Sock *)pSock->next, SIGTERM);
+	if ( menu_client != (Sock *) 0){
+	  send_int(menu_client,CloseClient);
+	  send_int(menu_client,(*plSock).Socket.pid);
+	}
+#ifdef DEBUG
+fprintf(stderr,"trying to clear %u\n",socket_fd);
+#endif
+	FD_CLR(socket_fd,&session_socket_mask);
+	locSock = pSock->next;
+	if (  pSock->next->next == (Sock_List *) 0  )
+	  { pSock->next= (Sock_List *) 0;}
+	else
+	  { pSock->next = pSock->next->next;}
+	num_active_clients--;
+	active_session = (Sock *) 0;
+	free(locSock);
+	break;
+      }
+  }
+#ifdef DEBUG
+pr();
+#endif
+}
+
+@
+\subsection{read\_SpadServer\_command}
+<<ses.readSpadServercommand>>=
+static void 
+read_SpadServer_command(void)
+{
+  int cmd, frame, num;
+  cmd  = get_int(spad_server);
+  switch (cmd) {
+  case EndOfOutput:
+    if (menu_client != (Sock *) 0) send_signal(menu_client, SIGUSR2); 
+    if (reading_output != 0) reading_output = 0;
+    break;
+  case QueryClients:
+    /*  don't count MenuServer */
+    num =  num_active_clients ;
+    send_int(spad_server, num);
+    break;
+  case CloseClient:
+    frame = get_int(spad_server);
+    if (frame != -1) close_client(frame); 
+    break;
+  case SendXEventToHyperTeX:
+    break;
+  default:
+    fprintf(stderr, "session : unknown command from SpadServer %d\n", cmd);
+    break;
+  }
+}
+
+@
+\subsection{test\_sock\_for\_process}
+<<ses.testsockforprocess>>=
+static int
+test_sock_for_process(Sock *sock)
+{
+  if (sock == (Sock *)0 ) return -1;
+  return kill(sock->pid, 0);
+}
+
+@
+\subsection{read\_menu\_client\_command}
+<<ses.readmenuclientcommand>>=
+static void
+read_menu_client_command(void)
+{
+  int cmd,frame, i,socket_fd;
+  Sock_List *pSock;
+  
+  /* save it for possible clearing */
+  socket_fd =  menu_client->socket;
+
+  if (test_sock_for_process(menu_client) == -1) {
+    FD_CLR(socket_fd,&session_socket_mask);
+    menu_client = (Sock *) 0; 
+    reading_output = 0;
+    return;
+  }
+  cmd = get_int(menu_client);
+  switch(cmd) {
+  case -1:		/* socket closed */
+    FD_CLR(socket_fd,&session_socket_mask);
+    menu_client = (Sock *) 0;
+    reading_output = 0;
+    break;
+  case SwitchFrames:
+#ifdef DEBUG
+fprintf(stderr,"menu:SwitchFrames\n");
+#endif
+    frame = get_int(menu_client);
+    send_int(spad_server, SwitchFrames);
+    send_int(spad_server, frame);
+    for(i=0,pSock=plSock; pSock != (Sock_List *) 0 ; i++,pSock=pSock->next)
+      if ((pSock->Socket.frame == frame)) {
+	active_session = (Sock *)pSock;
+	reading_output = 1;
+	break;
+      }
+    if (i == num_active_clients) {
+      /* fprintf(stderr, "Couldn't find socket for frame %d\n", frame); */
+    }
+    break;
+  case QuerySpad:
+#ifdef DEBUG
+fprintf(stderr,"menu:QuerySpad\n");
+#endif
+    send_int(menu_client, reading_output);
+    break;
+  default:
+    fprintf(stderr, "session : unknown command from MenuServer: %d\n", cmd);
+    menu_client = (Sock *) 0;
+    break;
+  }
+}
+
+@
+\subsection{read\_from\_spad\_io}
+<<ses.readfromspadio>>=
+static void
+read_from_spad_io(void)
+{
+  int ret_code;
+  ret_code = sread(spad_io, big_bad_buf, BufSize, "session: stdout socket");
+  if (ret_code == -1) return;
+  if(active_session != (Sock *) 0) {
+    ret_code = swrite(active_session, big_bad_buf, ret_code,
+		      NULL);
+  }
+}
+
+@
+\subsection{kill\_spad}
+<<ses.killspad>>=
+static void
+kill_spad(void)
+{
+  int i;
+  Sock_List *pSock;
+  
+  send_signal(spad_server, SIGTERM);
+  for  (pSock=plSock,i=0;
+	(i<num_active_clients) && (pSock != (Sock_List *) 0); 
+	i++,pSock=pSock->next) {
+    if ((pSock->Socket).socket != 0)
+      send_signal((Sock *)pSock, SIGTERM);
+  }
+  if (menu_client != (Sock *) 0) send_signal(menu_client, SIGTERM);
+  exit(0);
+}
+
+@
+\subsection{accept\_session\_connection}
+<<ses.acceptsessionconnection>>=
+static int
+accept_session_connection(Sock *server_sock)
+{
+  int sock_fd, ret_code;
+  Sock_List *pls;
+  
+  /* Could be three things : KillSpad MenuServer InterpWindow  */
+  
+  pls = (Sock_List *) malloc(sizeof (Sock_List));
+  sock_fd = accept(server_sock->socket, 0, 0);
+  if (sock_fd == -1) {
+    perror("session : accepting connection");
+    return -1;
+  }
+  (pls->Socket).socket = sock_fd;
+    get_socket_type((Sock *)pls);
+    
+    switch((pls->Socket).purpose) {
+    case KillSpad:
+      kill_spad();
+      return KillSpad;
+      free(pls);
+    case MenuServer:
+#ifdef DEBUG
+      fprintf(stderr,"session: accepted MenuServer , fd = %d\n",sock_fd);
+#endif
+      menu_client = &(pls->Socket);
+      FD_SET(menu_client->socket, &session_socket_mask);
+      return MenuServer;
+    case InterpWindow:
+#ifdef DEBUG
+      fprintf(stderr,"session: accepted InterpWindow , fd = %d\n",sock_fd);
+#endif
+      
+      /* new Sock is put at the head of the list */
+      if (plSock == (Sock_List *)0 ) {
+	plSock = pls;
+	plSock->next = (Sock_List *)0 ;
+      }
+      else{
+	pls->next = plSock;
+	plSock = pls;
+      }
+      
+      /* we need to maintain session_socket_mask here 
+         since we roll our own accept */
+      
+      FD_SET(plSock->Socket.socket, &session_socket_mask);
+      send_int(spad_server, CreateFrame);
+      {
+          int command = get_int(spad_server);
+          /* XXX hack -- the whole protocol looks broken, we just
+          try to detect losage */
+          if (command != CreateFrameAnswer) {
+              fprintf(stderr, "session: non-fatal, got out of sync "
+                               "with Spad server\n  (lost race)\n");
+          /*    exit(1); */
+          }
+      }
+      plSock->Socket.frame = get_int(spad_server);
+      active_session = (Sock *)plSock;
+      get_string_buf(spad_server, big_bad_buf, BufSize);
+      ret_code = swrite((Sock *)plSock, big_bad_buf, strlen(big_bad_buf)+1,
+			"session: writing to InterpWindow");
+      if (ret_code == -1) 
+	return -1;
+      num_active_clients++;
+#ifdef DEBUG
+pr();
+#endif
+      return plSock->Socket.purpose;
+    }
+    return (-1);
+}
+
+@
+\subsection{read\_from\_session}
+<<ses.readfromsession>>=
+static void
+read_from_session(Sock *sock)
+{
+  int ret_code;
+  if (sock != active_session) {
+    send_int(spad_server, SwitchFrames);
+    send_int(spad_server, sock->frame);
+  }
+  active_session = sock;
+  ret_code = sread(sock, big_bad_buf, BufSize, 
+		   "session: reading InterpWindow");
+  if (ret_code == -1) {
+    active_session = (Sock *) 0;
+    reading_output = 0;
+    return;
+  }
+  ret_code = swrite(spad_io, big_bad_buf, ret_code,
+		    "session: writing SessionIO");
+  if (ret_code == -1) {
+    active_session = (Sock *)0 ;
+    reading_output = 0;
+    return;
+  }
+  reading_output = 1;
+}
+
+@
+\subsection{manage\_sessions}
+<<ses.managesessions>>=
+static void
+manage_sessions(void)
+{
+  int ret_code;
+  fd_set rd, wr, ex;
+  Sock_List  *pSock;
+  
+  reading_output = 0;
+  while (1) {
+    FD_ZERO(&rd);
+    FD_ZERO(&wr);
+    FD_ZERO(&ex);
+
+    /* Allow server socket and all connections if not waiting for output
+       socket_mask is maintained by libspad.a  */
+#ifdef DEBUG
+fprintf(stderr,"session_socket_mask=%u ",*((long *)session_socket_mask.fds_bits));
+#endif
+    rd = session_socket_mask;
+    if (!reading_output) {
+      rd = session_socket_mask;
+    }
+
+    /* Allow the active_session if set */
+    if (active_session) FD_SET(active_session->socket, &rd);
+#ifdef DEBUG
+fprintf(stderr,"[rd=%u ",*((long *)rd.fds_bits));
+#endif
+
+    ret_code = sselect(FD_SETSIZE, &rd, &wr, &ex, NULL);
+    if (ret_code == -1) {
+	break;
+    }
+#ifdef DEBUG
+fprintf(stderr,"rd=%u]\n",*((long *)rd.fds_bits));
+#endif
+    
+    if ((menu_client != (Sock *) 0)  && FD_ISSET(menu_client->socket, &rd)) {
+      /* MenuServer wants to talk */
+      read_menu_client_command(); }
+    
+    
+    if (FD_ISSET(spad_io->socket, &rd)) {
+      /* Lisp has output */
+      read_from_spad_io(); }
+    
+    
+    if (FD_ISSET(server[1].socket, &rd)) {
+      /* Someone wants to connect to our server socket */
+      accept_session_connection(server+1); }
+    
+    
+    for(pSock=plSock; pSock != (Sock_List *) 0 ; pSock=pSock->next) {
+      if ((active_session == (Sock *)pSock || !reading_output) &&
+	  (pSock->Socket).socket>0 && FD_ISSET(pSock->Socket.socket, &rd)) {
+	/* An InterpWindow */
+	read_from_session((Sock *)pSock); }
+    }
+    
+    
+    if (FD_ISSET(spad_server->socket, &rd)) {
+      /* The Lisp socket */
+      read_SpadServer_command(); }
+  }
+}
+
+@
+\subsection{main sessionmanager}
+<<ses.main>>=
+int
+main(void)
+{
+
+#ifdef DEBUG2
+  /* delay for attaching with debugger before interesting things happen */
+  sleep(30);
+#endif
+
+ /* spad_server connects to Lisp server socket         
+    read_SpadServer_command handles requests */
+  spad_server = connect_to_local_server(SpadServer, SessionManager, Forever);
+  if (spad_server == (Sock *) 0) {
+    fprintf(stderr, "session: Cannot connect to AXIOM server!\n");
+    exit(0);
+  }
+  else {
+#ifdef DEBUG
+    fprintf(stderr, "session: connected SpadServer , fd = %d\n",
+	    spad_server->socket);
+#endif  
+    FD_SET(spad_server->socket, &session_socket_mask);
+  }
+
+
+  /* spad_io connects to SessionIOName server socket
+    this is Lisp std IO read_from_spad_io handles requests */
+  spad_io = connect_to_local_server(SessionIOName, SessionIO, Forever);
+  if (spad_io == (Sock *) 0) {
+    fprintf(stderr, "session: Cannot connect to AXIOM IO!\n");
+    exit(0);
+  }
+  else {
+#ifdef DEBUG
+    fprintf(stderr,"session: connected SessionIOName , fd = %d\n",
+	    spad_io->socket);
+#endif  
+    FD_SET(spad_io->socket, &session_socket_mask);
+  }
+  bsdSignal(SIGUSR2, usr2_handler,DontRestartSystemCalls);
+  bsdSignal(SIGUSR1, usr1_handler,RestartSystemCalls);
+  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
+  bsdSignal(SIGTERM, term_handler,RestartSystemCalls);
+
+  /* open_server opens the server socket so that we can accept connections
+    we expect connections from spadbuf/spadclient(purpose:InterpWindow) 
+    and hypertex (MenuServer) */
+
+  if (open_server(SessionServer) == -2) {
+    fprintf(stderr, "session: Cannot make server socket!\n");
+    exit(-1);
+  }
+  else {
+#ifdef DEBUG
+    fprintf(stderr, "session: opened SessionServer , fd = %d\n",
+	    server[1].socket);
+#endif  
+    FD_SET(server[1].socket,&session_socket_mask);
+  }
+  manage_sessions();
+  return(0);
+}
+
+@
+\subsection{session}
+<<session>>=
+/* #define DEBUG */
+#define _SESSION_C
+
+<<ses.includes>>
+<<ses.variables>>
+<<ses.usr1handler>>
+<<ses.usr2handler>>
+<<ses.termhandler>>
+<<ses.pr>>
+<<ses.closeclient>>
+<<ses.readSpadServercommand>>
+<<ses.testsockforprocess>>
+<<ses.readmenuclientcommand>>
+<<ses.readfromspadio>>
+<<ses.killspad>>
+<<ses.acceptsessionconnection>>
+<<ses.readfromsession>>
+<<ses.managesessions>>
+<<ses.main>>
+
+@
+\chapter{The {\tt spadclient} program}
+<<the spadclient command line>>=
+char *SpadClientProgram = "$AXIOM/lib/spadclient";
+@
+\section{spadclient}
+<<spadclient>>=
+#define _SPADCLIENT_C
+
+#include <stdio.h>
+#include <signal.h>
+#include "com.h"
+#include "bsdsignal.h"
+
+#include "bsdsignal.h1"
+#include "sockio-c.h1"
+#include "spadclient.h1"
+
+Sock *sock;
+
+static void 
+inter_handler(int sig)
+{
+  send_signal(sock, SIGUSR2);
+  fflush(stderr);
+}
+
+
+int 
+main(void)
+{
+  sock = connect_to_local_server(SessionServer, InterpWindow, Forever);
+  bsdSignal(SIGINT, inter_handler,RestartSystemCalls); 
+  remote_stdio(sock);
+  return(0);
+}
+
+@
+\chapter{The {\tt sman} program}
+\section{sman.h}
+The spad\_proc structure holds information about the process id
+of a child process, what to do when it dies, and the shell command
+line necessary to restart the process. There is a linked list of
+these structures which maintains the process list for axiom.
+<<sman.h>>=
+/* Process control definitions.  Used by fork_you and spawn_of_hell */
+
+/* When a process dies it kills off everything else */
+#define Die 1
+/* When a process dies, do nothing */
+#define NadaDelShitsky  2
+/* When a process dies start it up again */
+#define DoItAgain       3
+
+typedef struct spad_proc {
+  int	proc_id;	/* process id of child */
+  int	death_action;	/* one of the above constants */
+  char	*command;	/* sh command line to restart the process */
+  struct spad_proc *next;
+} SpadProcess;
+
+@
+\section{sman}
+\subsection{includes}
+<<sman.includes>>=
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#if defined(SUN4OS5platform) || defined(HP10platform)
+#include <sys/stropts.h>
+#endif
+
+#include "com.h"
+#include "bsdsignal.h"
+#include "sman.h"
+
+#include "bsdsignal.h1"
+#include "sockio-c.h1"
+#include "openpty.h1"
+#include "sman.h1"
+
+@
+\subsection{variables}
+<<sman.variables>>=
+char *ws_path;                  /* location of the AXIOM executable */
+int start_clef;			/* start clef under spad */
+int start_graphics;		/* start the viewman */
+int start_nagman;               /* start the nagman */
+int start_ht;			/* start hypertex */
+int start_spadclient;		/* Start the client spad buffer */
+int start_local_spadclient;	/* Start the client spad buffer */
+int use_X;			/* Use the X windows environment */
+int server_num;			/* AXIOM server number */
+@
+We add a debug flag so we can print information about what [[sman]]
+is trying to do. This change is pervasive as it touches nearly every
+routine.
+<<sman.variables>>=
+int tpd=0;                      /* to-print-debug information */
+
+/************************************************/
+/* definitions of programs which sman can start */
+/************************************************/
+
+<<the viewman command line>>
+<<the nagman command line>>
+<<the hypertex command line>>
+<<the clef command line>>
+<<the session manager command line>>
+<<the spadclient command line>>
+char *PasteFile = NULL;
+char *MakeRecordFile = NULL;
+char *VerifyRecordFile = NULL;
+
+SpadProcess *spad_process_list = NULL;
+/***************************/
+/* sman defaults file name */
+/***************************/
+
+#define SpadDefaultFile "spadprof.input"
+
+char ClefCommandLine[256];
+
+#define BufSize      4096 	/* size of communication buffer */
+char big_bad_buf[BufSize];      /* big I/O buffer */
+
+Sock *session_io = NULL;        /* socket connecting to session manager */
+
+/***********************************************************/
+/* Some characters used and externally defined in edible.h */
+/***********************************************************/
+
+unsigned char  _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2;
+
+/*************************************/
+/* Stuff for opening pseudo-terminal */
+/*************************************/
+
+int ptsNum, ptcNum;
+char ptsPath[20], ptcPath[20];
+
+char **new_envp;                /* new environment for AXIOM */
+int child_pid;                  /* child's process id */
+struct termios oldbuf;           /* the original settings */
+struct termios childbuf;         /* terminal structure for user i/o */
+
+int nagman_signal=0;
+int death_signal = 0;
+
+@
+\subsection{process\_arguments}
+<<sman.processarguments>>=
+static void
+process_arguments(int argc,char ** argv)
+{
+  int arg;
+  if (tpd == 1) fprintf(stderr,"sman:process_arguments entered\n");
+  for (arg = 1; arg < argc; arg++) {
+    if      (strcmp(argv[arg], "-debug")      == 0)
+      tpd = 1;
+    else if (strcmp(argv[arg], "-noclef")      == 0)
+      start_clef = 0;
+    else if (strcmp(argv[arg], "-clef")        == 0)
+      start_clef = 1;
+    else if (strcmp(argv[arg], "-gr")          == 0)
+      start_graphics = 1;
+    else if (strcmp(argv[arg], "-nogr")        == 0)
+      start_graphics = 0;
+    else if (strcmp(argv[arg], "-nag")          == 0)
+      start_nagman = 1;
+    else if (strcmp(argv[arg], "-nonag")        == 0)
+      start_nagman = 0;
+    else if (strcmp(argv[arg], "-ht")          == 0)
+      start_ht = 1;
+    else if (strcmp(argv[arg], "-noht")        == 0)
+      start_ht = 0;
+    else if (strcmp(argv[arg], "-iw")          == 0)
+      start_spadclient = 1;
+    else if (strcmp(argv[arg], "-ihere")       == 0)
+      start_local_spadclient = 1;
+    else if (strcmp(argv[arg], "-noihere")     == 0)
+      start_local_spadclient = 0;
+    else if (strcmp(argv[arg], "-noiw")        == 0)
+      start_spadclient = 0;
+    else if (strcmp(argv[arg], "-ws")          == 0)
+      ws_path = argv[++arg];
+    else if (strcmp(argv[arg], "-comp")        == 0)
+      ws_path = "$AXIOM/etc/images/comp";
+    else if (strcmp(argv[arg], "-nox")         == 0)
+      {
+	use_X = 0;
+	start_local_spadclient = 1;
+	start_spadclient = 0;
+	start_ht = 0;
+	start_graphics = 0;
+      }
+    else if (strcmp(argv[arg], "-grprog")      == 0)
+      GraphicsProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-nagprog")      == 0)
+      NagManagerProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-htprog")      == 0)
+      HypertexProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-clefprog")    == 0) {
+      strcpy(ClefCommandLine,argv[++arg]);
+    ClefProgram = 
+        strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e ");
+    }
+    else if (strcmp(argv[arg], "-sessionprog") == 0)
+      SessionManagerProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-clientprog")  == 0)
+      SpadClientProgram = argv[++arg];
+    else if (strcmp(argv[arg], "-rm")  == 0)
+      MakeRecordFile = argv[++arg];
+    else if (strcmp(argv[arg], "-rv")  == 0)
+      VerifyRecordFile = argv[++arg];
+    else if (strcmp(argv[arg], "-paste")  == 0)
+      PasteFile = argv[++arg];
+    else {
+      fprintf(stderr, "Usage: sman <-clef|-noclef> <-gr|-nogr> <-ht|-noht>");
+      fprintf(stderr, " <-iw|-noiw> <-nag|-nonag> <-nox> <-comp>");
+      fprintf(stderr, " <-ws spad_workspace> <-grprog path> <-htprog path>");
+      fprintf(stderr, " <-clefprog path> <-sessionprog path> <-nagprog path>");
+      fprintf(stderr, " <-clientprog path>\n");
+      exit(-1);
+    }
+  }
+  if (tpd == 1)
+  { fprintf(stderr,"  sman ");
+    if (start_clef == 0)
+      fprintf(stderr,"-noclef ");
+    else
+      fprintf(stderr,"-clef ");
+    if (start_graphics == 0)
+      fprintf(stderr,"-nogr ");
+    else
+      fprintf(stderr,"-gr ");
+    if (start_nagman == 0)
+      fprintf(stderr,"-nonag ");
+    else
+      fprintf(stderr,"-nag ");
+    if (start_ht == 0)
+      fprintf(stderr,"-noht ");
+    else
+      fprintf(stderr,"-ht ");
+    if (start_spadclient == 0)
+      fprintf(stderr,"-noiw ");
+    else
+      fprintf(stderr,"-iw ");
+    if (start_local_spadclient == 0)
+      fprintf(stderr,"-noihere ");
+    else
+      fprintf(stderr,"-ihere ");
+    if (start_local_spadclient == 0)
+      fprintf(stderr,"-noihere ");
+    else
+      fprintf(stderr,"-ihere ");
+    if (use_X == 0)
+      fprintf(stderr,"-nox ");
+    fprintf(stderr,"-ws ");
+    fprintf(stderr,"'%s' ",ws_path);
+    fprintf(stderr,"-grprog ");
+    fprintf(stderr,"'%s' ",GraphicsProgram);
+    fprintf(stderr,"-nagprog ");
+    fprintf(stderr,"'%s' ",NagManagerProgram);
+    fprintf(stderr,"-htprog ");
+    fprintf(stderr,"'%s' ",HypertexProgram);
+    fprintf(stderr,"-clefprog ");
+    fprintf(stderr,"'%s' ",ClefCommandLine);
+    fprintf(stderr,"-sessionprog ");
+    fprintf(stderr,"'%s' ",SessionManagerProgram);
+    fprintf(stderr,"-clientprog ");
+    fprintf(stderr,"'%s' ",SpadClientProgram);
+    fprintf(stderr,"-rm ");
+    fprintf(stderr,"'%s' ",MakeRecordFile);
+    fprintf(stderr,"-rv ");
+    fprintf(stderr,"'%s' ",VerifyRecordFile);
+    fprintf(stderr,"-paste ");
+    fprintf(stderr,"'%s' ",PasteFile);
+    fprintf(stderr,"\n");
+  }
+  if (tpd == 1) fprintf(stderr,"sman:process_arguments exit\n");
+}
+
+@
+\subsection{should\_I\_clef}
+<<sman.shouldIclef>>=
+static int 
+should_I_clef(void)
+{
+  return(1);
+}
+
+@
+\subsection{in\_X}
+<<sman.inX>>=
+static int 
+in_X(void)
+{
+  if (getenv("DISPLAY")) return 1;
+  return 0;
+}
+
+@
+\subsection{set\_up\_defaults}
+These are the default values for sman. A '1' value means that
+sman will try to start the given process, a '0' value means not
+starting the process.
+
+We do not have replacement code for the [[nagman]] process nor
+do we have a copy of the [[nag fortran library]] to test the process.
+Until this changes we set [[start_nagman = 0]] in order to disable
+starting this process by default.
+<<sman.setupdefaults>>=
+static  void
+set_up_defaults(void)
+{
+  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults entered\n");
+  start_clef = should_I_clef();
+  start_graphics = 1;
+  start_nagman = 0;
+  start_ht = 1;
+  start_spadclient = 0;
+  start_local_spadclient = 1;
+  use_X = isatty(0) && in_X();
+  ws_path = "$AXIOM/bin/AXIOMsys";
+  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults exit\n");
+}
+
+@
+\subsection{process\_options}
+<<sman.processoptions>>=
+static void
+process_options(int argc, char **argv)
+{
+  if (tpd == 1) fprintf(stderr,"sman:process_options entered\n");
+  set_up_defaults();
+  process_arguments(argc, argv);
+  if (tpd == 1) fprintf(stderr,"sman:process_options exit\n");
+}
+
+@
+\subsection{death\_handler}
+<<sman.deathhandler>>=
+static void
+death_handler(int sig)
+{
+  death_signal = 1;
+}
+
+@
+\subsection{nagman\_handler}
+<<sman.nagmanhandler>>=
+static void 
+nagman_handler(int sig)
+{
+  nagman_signal=1;
+}
+
+@
+\subsection{sman\_catch\_signals}
+<<sman.smancatchsignals>>=
+static void
+sman_catch_signals(void)
+{
+  
+  /* Set up the signal handlers for sman */
+  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
+  bsdSignal(SIGTERM, death_handler,RestartSystemCalls);
+  bsdSignal(SIGQUIT, death_handler,RestartSystemCalls);
+  bsdSignal(SIGHUP,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGILL,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGTRAP, death_handler,RestartSystemCalls);
+  bsdSignal(SIGIOT,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGBUS,  death_handler,RestartSystemCalls);
+  bsdSignal(SIGSEGV, death_handler,RestartSystemCalls);
+  /* don't restart wait call on SIGUSR1  */
+  bsdSignal(SIGUSR1, nagman_handler,DontRestartSystemCalls); 
+  /* ONLY nagman should send this.
+     If an error (such as C-c) interrupts a NAGLINK call, nagman
+     gets a signal to clean up. We need to start another nagman 
+     almost immediately to process the next NAGLINK request.
+     Since nagman takes a while to clean up, we treat it specially.
+     nagman should send a signal (USR1) to sman.
+     sman should respond by spawning a new nagman.
+     
+     so nagman is NOT a DoItAgain but a NadaDelShitsky.
+     
+     The USR1 mechanism does not work for HPUX 9 - use DoItAgain 
+     */
+
+}
+
+@
+\subsection{fix\_env}
+insert SPADSERVER and SPADNUM variables into the environemnt
+<<sman.fixenv>>=
+static void
+fix_env(char **envp, int spadnum)
+{
+  int len, i;
+  char *sn;
+  for(len = 0; envp[len] != NULL; len++);
+  new_envp = (char **) malloc((len + 3) * sizeof(char *));
+  new_envp[0] = "SPADSERVER=TRUE";
+  sn = (char *) malloc(20 * sizeof(char));
+  sprintf(sn, "SPADNUM=%d", spadnum);
+  new_envp[1] = sn;
+  for(i=0; i<=len; i++)
+    new_envp[i+2] = envp[i];
+}
+
+@
+\subsection{init\_term\_io}
+<<sman.inittermio>>=
+static void
+init_term_io(void)
+{
+  if(!isatty(0)) return;
+  if( tcgetattr(0, &oldbuf) == -1) {
+    perror("getting termios");
+    return ; 			/*  exit(-1); */
+  }
+  if( tcgetattr(0, &childbuf) == -1) {
+    perror("getting termios");
+    return ; 			/*   exit(-1); */
+  }
+  _INTR = oldbuf.c_cc[VINTR];
+  _QUIT = oldbuf.c_cc[VQUIT];
+  _ERASE = oldbuf.c_cc[VERASE];
+  _KILL = oldbuf.c_cc[VKILL];
+  _EOF = oldbuf.c_cc[VEOF];
+  _EOL = oldbuf.c_cc[VEOL];
+}
+
+@
+\subsection{strPrefix}
+<<sman.strPrefix>>=
+static char *
+strPrefix(char *prefix,char * s)
+{
+  while (*prefix != '\0' && *prefix == *s) {
+    prefix++;
+    s++;
+  }
+  if (*prefix == '\0') return s;
+  return NULL;
+}
+
+@
+\subsection{check\_spad\_proc}
+<<sman.checkspadproc>>=
+static void
+check_spad_proc(char *file, char *prefix)
+{
+  char *num;
+  int pid;
+  if ((num = strPrefix(prefix, file))) {
+    pid = atoi(num);
+    if (pid > 2) {
+      kill(pid, 0);
+      if (kill(pid, 0) == -1 && errno == ESRCH) {
+	unlink(file);
+      }
+    }
+  }
+}
+
+@
+\subsection{clean\_up\_old\_sockets}
+<<sman.cleanupoldsockets>>=
+static void
+clean_up_old_sockets(void)
+{
+  char com[512], tmp_file[128];
+  FILE *file;
+  int len;
+  sprintf(tmp_file, "/tmp/socks.%d", server_num);
+  sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s",
+	  tmp_file, tmp_file);
+  system(com);
+  file = fopen(tmp_file, "r");
+  if (file == NULL) {
+    fprintf(stderr, "Can't open socket listing file\n");
+    return;
+  }
+  while(fgets(com, 512, file) != NULL) {
+    len = strlen(com);
+    if (len) com[len-1] = '\0';
+    else break;
+    check_spad_proc(com, "/tmp/.d");
+    check_spad_proc(com, "/tmp/.s");
+    check_spad_proc(com, "/tmp/.i");
+    check_spad_proc(com, "/tmp/.h");
+  }
+  fclose(file);
+  unlink(tmp_file);
+}
+
+@
+\subsection{fork\_you}
+<<sman.forkyou>>=
+static SpadProcess *
+fork_you(int death_action)
+{
+  /* fork a new process, giving it a default death action */
+  /* return NULL in child, SpadProcess in parent          */
+  int child_pid = fork();
+  SpadProcess *proc;
+  if (!child_pid) return NULL;
+  proc = (SpadProcess *) malloc(sizeof(SpadProcess));
+  proc->proc_id = child_pid;
+  proc->death_action = death_action;
+  proc->command = NULL;
+  proc->next = spad_process_list;
+  spad_process_list = proc;
+  return proc;
+}
+
+@
+\subsection{exec\_command\_env}
+Note that the next-to-last argument of {\tt execle} must be an
+explicit NULL pointer. The previous naked 0 value was not correct.
+<<sman.execcommandenv>>=
+static void
+exec_command_env(char *command,char ** env)
+{
+  char new_command[512];
+  sprintf(new_command, "exec %s", command);
+  execle("/bin/sh","/bin/sh", "-c", new_command, (char *)0, env);
+}
+
+@
+\subsection{spawn\_of\_hell}
+<<sman.spawnofhell>>=
+static SpadProcess *
+spawn_of_hell(char *command, int death_action)
+{
+  SpadProcess *proc = fork_you(death_action);
+  if (proc != NULL) {
+    proc->command = command;
+    return proc;
+  }
+  exec_command_env(command, new_envp);
+  return NULL;
+}
+
+@
+\subsection{start\_the\_spadclient}
+run a AXIOM client in the main process
+<<sman.startthespadclient>>=
+static void
+start_the_spadclient(void)
+{
+  char command[256];
+  if (start_clef)
+#ifdef RIOSplatform
+    sprintf(command, 
+	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
+	    ClefProgram, SpadClientProgram);
+#else
+  sprintf(command, 
+	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
+	  ClefProgram, SpadClientProgram);
+#endif
+  else
+#ifdef RIOSplatform
+    sprintf(command, 
+	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
+	    SpadClientProgram);
+#else
+  sprintf(command, 
+	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
+	  SpadClientProgram);
+#endif
+  if (tpd == 1) 
+    fprintf(stderr,"sman:start_the_spadclient: %s\n",command);
+  spawn_of_hell(command, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_local\_spadclient}
+<<sman.startthelocalspadclient>>=
+static void
+start_the_local_spadclient(void)
+{
+  char command[256];
+  if (start_clef)
+    sprintf(command, "%s  %s", ClefProgram, SpadClientProgram);
+  else
+    sprintf(command, "%s", SpadClientProgram);
+  if (tpd == 1) 
+    fprintf(stderr,"sman:start_the_local_spadclient: %s\n",command);
+  spawn_of_hell(command, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_nagman}
+<<sman.startthenagman>>=
+static void
+start_the_nagman(void)
+{
+#if defined(HP9platform)
+  spawn_of_hell(NagManagerProgram,DoItAgain);
+#else
+  spawn_of_hell(NagManagerProgram,NadaDelShitsky );
+#endif
+}
+
+@
+\subsection{start\_the\_session\_manager}
+<<sman.startthesessionmanager>>=
+static void
+start_the_session_manager(void)
+{
+  spawn_of_hell(SessionManagerProgram, Die);
+}
+
+@
+\subsection{start\_the\_hypertex}
+<<sman.startthehypertex>>=
+static void
+start_the_hypertex(void)
+{
+  char prog[512];
+
+  if (PasteFile){
+    sprintf(prog, "%s -k -ip %s", HypertexProgram, PasteFile);
+    spawn_of_hell(prog, NadaDelShitsky);
+  }
+  else if (MakeRecordFile){
+    sprintf(prog, "%s -k -rm %s", HypertexProgram,MakeRecordFile );
+    spawn_of_hell(prog, NadaDelShitsky);
+  }
+  else if (VerifyRecordFile){
+    sprintf(prog, "%s -k -rv %s", HypertexProgram, VerifyRecordFile);
+    spawn_of_hell(prog, NadaDelShitsky);
+  }
+  else	spawn_of_hell(HypertexProgram, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_graphics}
+<<sman.startthegraphics>>=
+static void
+start_the_graphics(void)
+{
+  spawn_of_hell(GraphicsProgram, DoItAgain);
+}
+
+@
+\subsection{fork\_Axiom}
+<<sman.forkAxiom>>=
+/* Start the AXIOM session in a separate process, */
+/* using a pseudo-terminal to catch all input and output */
+static void 
+fork_Axiom(void)
+{
+  char augmented_ws_path[256];  /* will append directory path */
+  char *tmp_pointer;
+  SpadProcess *proc;
+
+  proc =  fork_you(Die);
+  child_pid = (proc == NULL ? 0 : proc->proc_id);
+  switch(child_pid) {
+  case -1 :
+    fprintf(stderr, "Can't create a new process \n");
+    exit(0);
+  case 0:
+    /* Dissasociate from my parents group so all my child processes */
+    /* look at my terminal as the controlling terminal for the      */
+    /* group                                                        */
+
+    if(setsid() < 0) {
+      perror("Dissassociating from parents group");
+      exit(-1);
+    }
+
+    close(ptsNum);
+    /* Now reopen the server side, so that pg, su, etc. work properly */
+
+    if ((ptsNum =  open(ptsPath, O_RDWR)) < 0 ) {
+      perror("fork_Axiom: Failed to reopen server");
+      exit(-1);
+    }
+#if defined(SUN4OS5platform) || defined(HP10platform)
+    ioctl(ptsNum,I_PUSH,"ptem");
+    ioctl(ptsNum,I_PUSH,"ldterm");
+#endif
+
+    /* since I am the child, I can close ptc, and dup pts for all its */
+    /* standard descriptors                                           */
+
+    if( (dup2(ptsNum, 0) == -1) ||
+        (dup2(ptsNum, 1) == -1) ||
+        (dup2(ptsNum, 2) == -1)  ) {
+      perror("trying to dupe the child");
+      exit(-1);
+    }
+    close(ptcNum);
+    close(ptsNum);
+
+
+    /* I also have to turn off echoing, since I am echoing all the */
+    /* input myself                  */
+
+    childbuf.c_lflag &= ~ECHO;
+    if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) {
+      perror("setting the term buffer");
+      exit(-1); 
+    }
+    strcpy(augmented_ws_path,ws_path);          /* write the name    */
+    strcat(augmented_ws_path," ");              /* space             */
+    strcat(augmented_ws_path,ws_path);          /* name again        */
+    tmp_pointer = (char *)
+      strrchr(augmented_ws_path,'/');      /*pointer to last /  */
+    *(++tmp_pointer) = '\0';
+    exec_command_env(augmented_ws_path, new_envp);
+
+    /*    fprintf(stderr, "Cannot execute the %s system.\n", ws_path); */
+
+    exit(0);
+  }
+}
+
+@
+\subsection{start\_the\_Axiom}
+<<sman.starttheAxiom>>=
+static void
+start_the_Axiom(char **envp)
+{
+  server_num = make_server_number();
+  clean_up_old_sockets();
+  if (server_num == -1) {
+    fprintf(stderr, "could not get an AXIOM server number\n");
+    exit(-1);
+  }
+  if (ptyopen(&ptcNum, &ptsNum, ptcPath, ptsPath) == -1) {
+    perror("start_the_Axiom: ptyopen failed");
+    exit(-1);
+  }
+  fix_env(envp, server_num);
+  fork_Axiom();
+  close(ptsNum);
+}
+
+@
+\subsection{clean\_up\_sockets}
+<<sman.cleanupsockets>>=
+static void
+clean_up_sockets(void)
+{
+  char name[256];
+  sprintf(name, "%s%d", SpadServer, server_num);
+  unlink(name);
+  sprintf(name, "%s%d", SessionServer, server_num);
+  unlink(name);
+  sprintf(name, "%s%d", SessionIOName, server_num);
+  unlink(name);
+  sprintf(name, "%s%d", MenuServerName, server_num);
+  unlink(name);
+}
+
+@
+\subsection{read\_from\_spad\_io}
+<<sman.readfromspadio>>=
+static void
+read_from_spad_io(int ptcNum)
+{
+  int ret_code = 0, i=0;
+  static int mes_len =0; 
+  ret_code = read(ptcNum, big_bad_buf, BufSize);
+  if (ret_code == -1) {
+    clean_up_sockets();
+    exit(-1);
+  }
+  if (session_io == NULL) {
+    if (ret_code < mes_len)
+      mes_len -= ret_code;
+    else {
+      if (mes_len > 0) {
+	i = mes_len;
+	mes_len = 0;
+      }
+      else
+	i = 0;
+      ret_code = write(1, big_bad_buf+i, ret_code-i);
+    }
+  }
+  else
+    ret_code = swrite(session_io, big_bad_buf, ret_code,
+		      "writing to session man");
+  if (ret_code == -1) {
+    perror("writing output to session manager");
+    clean_up_sockets();
+    exit(-1);
+  }
+}
+
+@
+\subsection{read\_from\_manager}
+<<sman.readfrommanager>>=
+static void
+read_from_manager(int ptcNum)
+{
+  int ret_code;
+  ret_code = sread(session_io, big_bad_buf, BufSize, "reading session io");
+  if (ret_code == -1) {
+    return;
+  }
+  ret_code = write(ptcNum, big_bad_buf, ret_code);
+  if (ret_code == -1) {
+    return;
+  }
+}
+
+@
+\subsection{manage\_spad\_io}
+<<sman.managespadio>>=
+static void
+manage_spad_io(int ptcNum)
+{
+  int ret_code, i, p;
+  fd_set rd;
+  while (1) {
+    rd = socket_mask;
+    FD_SET(ptcNum, &rd);
+    if (session_io != NULL)
+      FD_SET(session_io->socket, &rd);
+    ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
+    if (ret_code == -1) {
+      perror("Session manager select");
+      clean_up_sockets();
+      exit(-1);
+    }
+    if (FD_ISSET(ptcNum, &rd)) {
+      read_from_spad_io(ptcNum);
+    }
+    for(i=0; i<2; i++) {
+      if (server[i].socket > 0 && FD_ISSET(server[i].socket, &rd)) {
+	p = accept_connection(server+i);
+	switch(p) {
+	case SessionIO:
+	  session_io = purpose_table[SessionIO];
+	  /*  printf("connected session manager\n\r");*/
+	  printf("\n");
+	  break;
+	default:
+	  printf("sman: Unkown connection request type: %d\n", p);
+	  break;
+	}
+      }
+    }
+    if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) {
+      read_from_manager(ptcNum);
+    }
+  }
+}
+
+@
+\subsection{init\_spad\_process\_list}
+<<sman.initspadprocesslist>>=
+static void
+init_spad_process_list(void)
+{
+  spad_process_list = NULL;
+}
+
+@
+\subsection{print\_spad\_process\_list}
+<<sman.printspadprocesslist>>=
+#if 0
+static void
+print_spad_process_list()
+{
+  SpadProcess *proc;
+  for(proc = spad_process_list; proc != NULL; proc = proc->next)
+    fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id,
+	    proc->death_action);
+}
+#endif
+
+@
+\subsection{find\_child}
+<<sman.findchild>>=
+static SpadProcess *
+find_child(int proc_id)
+{
+  SpadProcess *proc;
+  for(proc = spad_process_list; proc != NULL; proc = proc->next)
+    if (proc->proc_id == proc_id) return proc;
+  return NULL;
+}
+
+@
+\subsection{kill\_all\_children}
+<<sman.killallchildren>>=
+static void
+kill_all_children(void)
+{
+  char name[256];
+  SpadProcess *proc;
+  
+  
+  for(proc = spad_process_list; proc != NULL; proc = proc->next) {
+    kill(proc->proc_id, SIGTERM);
+  }
+  sprintf(name, "/tmp/hyper%d.input",server_num);
+  unlink(name);
+
+}
+
+@
+\subsection{clean\_up\_terminal}
+<<sman.cleanupterminal>>=
+static void
+clean_up_terminal(void)
+{
+  tcsetattr(0, TCSAFLUSH, &oldbuf);
+}
+
+@
+\subsection{monitor\_children}
+<<sman.monitorchildren>>=
+static void
+monitor_children(void)
+{
+  int dead_baby, stat;
+  SpadProcess *proc;
+  while (1) {
+    stat = 0;
+    dead_baby = wait(&stat);
+    /* Check the value of dead_baby, since wait may have returned
+       a pid but subsequently we have received a signal.  Yeuch! */
+    if (dead_baby == -1 && death_signal) {
+      kill_all_children();
+      clean_up_sockets();
+      clean_up_terminal();
+      sleep(2);
+      exit(0);
+    }
+    /* Check the value of dead_baby, since wait may have returned
+       a pid but subsequently we have received a signal.  Yeuch! */
+    if(dead_baby == -1 && nagman_signal) {
+      nagman_signal=0;
+      spawn_of_hell(NagManagerProgram,NadaDelShitsky);
+      continue;
+    }
+
+    if (dead_baby == -1) {
+      fprintf(stderr, "sman: wait returned -1\n");
+      continue;
+    }
+    proc = find_child(dead_baby);
+    if (proc == NULL) {
+      /*      fprintf(stderr, "sman: %d is not known to be a child process\n",
+	      dead_baby);
+	      */
+      continue;
+    }
+    switch(proc->death_action) {
+    case Die:
+      kill_all_children();
+      clean_up_sockets();
+      clean_up_terminal();
+      sleep(2);
+      exit(0);
+    case NadaDelShitsky:
+      break;
+    case DoItAgain:
+      spawn_of_hell(proc->command, DoItAgain);
+      break;
+    }
+  }
+}
+
+@
+\subsection{main sman}
+The main procedure should return an [[int]]. We change the return value
+here and in [[src/include/sman.h1]].
+<<sman.result>>=
+  return(0);
+@
+<<sman.main>>=
+int
+main(int argc, char *argv[],char *envp[])
+{
+  if (tpd == 1) fprintf(stderr,"sman:main entered\n");
+  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
+  process_options(argc, argv);
+
+  init_term_io();
+  init_spad_process_list();
+  start_the_Axiom(envp);
+  if (open_server(SessionIOName) == -2) {
+    fprintf(stderr, "Fatal error opening I/O socket\n");
+    clean_up_sockets();
+    exit(-1);
+  }
+  start_the_session_manager();
+  if (start_spadclient)       start_the_spadclient();
+  if (start_local_spadclient) start_the_local_spadclient();
+  if (start_nagman)           start_the_nagman();
+  if (start_ht)               start_the_hypertex();
+  if (start_graphics)         start_the_graphics();
+  sleep(1);
+
+  if (fork_you(Die) != NULL) {
+    sman_catch_signals();
+    monitor_children();
+    exit(0);
+  }
+  manage_spad_io(ptcNum);
+  if (tpd == 1) fprintf(stderr,"sman:main exit\n");
+<<sman.result>>
+}
+
+@
+\subsection{sman}
+<<sman>>=
+#define _SMAN_C
+
+<<sman.includes>>
+<<sman.variables>>
+<<sman.processarguments>>
+<<sman.shouldIclef>>
+<<sman.inX>>
+<<sman.setupdefaults>>
+<<sman.processoptions>>
+<<sman.deathhandler>>
+<<sman.nagmanhandler>>
+<<sman.smancatchsignals>>
+<<sman.fixenv>>
+<<sman.inittermio>>
+<<sman.strPrefix>>
+<<sman.checkspadproc>>
+<<sman.cleanupoldsockets>>
+<<sman.forkyou>>
+<<sman.execcommandenv>>
+<<sman.spawnofhell>>
+<<sman.startthespadclient>>
+<<sman.startthelocalspadclient>>
+<<sman.startthenagman>>
+<<sman.startthesessionmanager>>
+<<sman.startthehypertex>>
+<<sman.startthegraphics>>
+<<sman.forkAxiom>>
+<<sman.starttheAxiom>>
+<<sman.cleanupsockets>>
+<<sman.readfromspadio>>
+<<sman.readfrommanager>>
+<<sman.managespadio>>
+<<sman.initspadprocesslist>>
+<<sman.printspadprocesslist>>
+<<sman.findchild>>
+<<sman.killallchildren>>
+<<sman.cleanupterminal>>
+<<sman.monitorchildren>>
+<<sman.main>>
+
+@
+\chapter{The Command Completion List}
+<<command.list>>=
+-
+/
+/\
+^
+^=
+~
+~=
+*
+**
+\/
+#
++
+<
+<=
+=
+>
+>=
+0
+1
+abelianGroup
+abs
+absolutelyIrreducible?
+accuracyIF
+acos
+acosh
+acoshIfCan
+acosIfCan
+acot
+acoth
+acothIfCan
+acotIfCan
+acsc
+acsch
+acschIfCan
+acscIfCan
+aCubic
+adaptive
+adaptive?
+adaptive3D?
+addBadValue
+addChild!
+addData!
+addField!
+addiag
+addMatch
+addMatchRestricted
+addmod
+addPoint
+addPoint2
+addPointLast
+adjoint
+airyAi
+airyBi
+Aleph
+algDsolve
+algebraic?
+algebraicCoefficients?
+algebraicDecompose
+algebraicOf
+algebraicSort
+algebraicVariables
+algint
+algintegrate
+algSplitSimple
+aLinear
+allRootsOf
+alphabetic
+alphabetic?
+alphanumeric
+alphanumeric?
+alternating
+alternatingGroup
+alternative?
+An
+AND
+And
+and
+anfactor
+antiAssociative?
+antiCommutative?
+antiCommutator
+anticoord
+antisymmetric?
+antisymmetricTensors
+any
+any?
+append
+appendPoint
+apply
+applyQuote
+applyRules
+approximants
+approximate
+approxNthRoot
+approxSqrt
+aQuadratic
+aQuartic
+areEquivalent?
+arg1
+arg2
+argscript
+argument
+argumentList!
+argumentListOf
+arity
+aromberg
+arrayStack
+asec
+asech
+asechIfCan
+asecIfCan
+asimpson
+asin
+asinh
+asinhIfCan
+asinIfCan
+aspFilename
+assert
+assign
+assoc
+associatedEquations
+associatedSystem
+associates?
+associative?
+associator
+associatorDependence
+atan
+atanh
+atanhIfCan
+atanIfCan
+atom?
+atoms
+atrapezoidal
+att2Result
+augment
+autoReduced?
+axes
+axesColorDefault
+B1solve
+back
+backOldPos
+badNum
+badValues
+bag
+balancedBinaryTree
+balancedFactorisation
+bandedHessian
+bandedJacobian
+base
+baseRDE
+baseRDEsys
+BasicMethod
+basicSet
+basis
+basisOfCenter
+basisOfCentroid
+basisOfCommutingElements
+basisOfLeftAnnihilator
+basisOfLeftNucleus
+basisOfLeftNucloid
+basisOfMiddleNucleus
+basisOfNucleus
+basisOfRightAnnihilator
+basisOfRightNucleus
+basisOfRightNucloid
+bat
+bat1
+beauzamyBound
+belong?
+bernoulli
+bernoulliB
+besselI
+besselJ
+besselK
+besselY
+Beta
+bezoutDiscriminant
+bezoutMatrix
+bezoutResultant
+bfEntry
+bfKeys
+binary
+binaryFunction
+binarySearchTree
+binaryTournament
+binaryTree
+binomial
+binomThmExpt
+bipolar
+bipolarCylindrical
+biRank
+birth
+bit?
+bitCoef
+bitLength
+bits
+bitTruth
+bivariate?
+bivariatePolynomials
+bivariateSLPEBR
+blankSeparate
+block
+blue
+bombieriNorm
+bool
+bool?
+bottom!
+boundOfCauchy
+box
+brace
+bracket
+branchIfCan
+branchPoint?
+branchPointAtInfinity?
+bright
+brillhartIrreducible?
+brillhartTrials
+bringDown
+bsolve
+btwFact
+bubbleSort!
+build
+BumInSepFFE
+bumprow
+bumptab
+bumptab1
+BY
+c02aff
+c02agf
+c05adf
+c05nbf
+c05pbf
+c06eaf
+c06ebf
+c06ecf
+c06ekf
+c06fpf
+c06fqf
+c06frf
+c06fuf
+c06gbf
+c06gcf
+c06gqf
+c06gsf
+cache
+cAcos
+cAcosh
+cAcot
+cAcoth
+cAcsc
+cAcsch
+calcRanges
+call
+cap
+car
+cardinality
+cartesian
+cAsec
+cAsech
+cAsin
+cAsinh
+cAtan
+cAtanh
+cCos
+cCosh
+cCot
+cCoth
+cCsc
+cCsch
+cdr
+ceiling
+center
+central?
+certainlySubVariety?
+cExp
+cfirst
+chainSubResultants
+changeBase
+changeMeasure
+changeName
+changeNameToObjf
+changeThreshhold
+changeVar
+changeWeightLevel
+char
+character?
+characteristic
+characteristicPolynomial
+characteristicSerie
+characteristicSet
+charClass
+charpol
+charthRoot
+chebyshevT
+chebyshevU
+check
+checkCxResult
+checkForZero
+checkMxCDF
+checkMxDF
+checkPrecision
+checkResult
+checkRur
+child
+child?
+children
+chineseRemainder
+chiSquare
+chiSquare1
+choosemon
+chvar
+Ci
+className
+clearCache
+clearDenominator
+clearFortranOutputStack
+clearTable!
+clearTheFTable
+clearTheIFTable
+clearTheSymbolTable
+clikeUniv
+clip
+clipBoolean
+clipParametric
+clipPointsDefault
+clipSurface
+clipWithRanges
+cLog
+close
+close!
+closeComponent
+closed?
+closedCurve
+closedCurve?
+cn
+code
+coef
+coefChoose
+coefficient
+coefficients
+coerce
+coerceImages
+coerceListOfPairs
+coerceP
+coercePreimagesImages
+coHeight
+coleman
+collect
+collectQuasiMonic
+collectUnder
+collectUpper
+color
+colorDef
+colorFunction
+column
+combineFeatureCompatibility
+commaSeparate
+comment
+common
+commonDenominator
+commutative?
+commutativeEquality
+commutator
+comp
+compactFraction
+companionBlocks
+comparison
+compBound
+compdegd
+compile
+compiledFunction
+complement
+complementaryBasis
+complete
+completeEchelonBasis
+completeEval
+completeHensel
+completeHermite
+completeSmith
+complex
+complex?
+complexEigenvalues
+complexEigenvectors
+complexElementary
+complexExpand
+complexForm
+complexIntegrate
+complexLimit
+complexNormalize
+complexNumeric
+complexNumericIfCan
+complexRoots
+complexSolve
+complexZeros
+component
+components
+compose
+composite
+composites
+computeBasis
+computeCycleEntry
+computeCycleLength
+computeInt
+computePowers
+concat
+concat!
+cond
+condition
+conditionP
+conditions
+conditionsForIdempotents
+conical
+conjHerm
+conjug
+conjugate
+conjugates
+connect
+connect?
+cons
+consnewpol
+const
+constant
+constant?
+constantCoefficientRicDE
+constantIfCan
+constantKernel
+constantLeft
+constantOperator
+constantOpIfCan
+constantRight
+constantToUnaryFunction
+constDsolve
+construct
+contains?
+content
+continue
+continuedFraction
+contract
+contractSolve
+controlPanel
+convergents
+convert
+coord
+coordinate
+coordinates
+copies
+copy
+copy!
+copyInto!
+corrPoly
+cos
+cos2sec
+cosh
+cosh2sech
+coshIfCan
+cosIfCan
+cosSinInfo
+cot
+cot2tan
+cot2trig
+coth
+coth2tanh
+coth2trigh
+cothIfCan
+cotIfCan
+count
+countable?
+countRealRoots
+countRealRootsMultiple
+cPower
+cRationalPower
+create
+create3Space
+createGenericMatrix
+createIrreduciblePoly
+createLowComplexityNormalBasis
+createLowComplexityTable
+createMultiplicationMatrix
+createMultiplicationTable
+createNormalElement
+createNormalPoly
+createNormalPrimitivePoly
+createPrimitiveElement
+createPrimitiveNormalPoly
+createPrimitivePoly
+createRandomElement
+createThreeSpace
+createZechTable
+credPol
+crest
+critB
+critBonD
+critM
+critMonD1
+critMTonD1
+critpOrder
+critT
+cross
+crushedSet
+csc
+csc2sin
+csch
+csch2sinh
+cschIfCan
+cscIfCan
+cSec
+cSech
+cSin
+cSinh
+csubst
+cTan
+cTanh
+cubic
+cup
+currentSubProgram
+curry
+curryLeft
+curryRight
+curve
+curve?
+curveColor
+curveColorPalette
+cycle
+cycleElt
+cycleEntry
+cycleLength
+cyclePartition
+cycleRagits
+cycles
+cycleSplit!
+cycleTail
+cyclic
+cyclic?
+cyclicCopy
+cyclicEntries
+cyclicEqual?
+cyclicGroup
+cyclicParents
+cyclicSubmodule
+cyclotomic
+cyclotomicDecomposition
+cyclotomicFactorization
+cylindrical
+D
+d01ajf
+d01akf
+d01alf
+d01amf
+d01anf
+d01apf
+d01aqf
+d01asf
+d01bbf
+d01fcf
+d01gaf
+d01gbf
+d02bbf
+d02bhf
+d02cjf
+d02ejf
+d02gaf
+d02gbf
+d02kef
+d02raf
+d03edf
+d03eef
+d03faf
+dAndcExp
+dark
+datalist
+ddFact
+debug
+debug3D
+dec
+decimal
+declare
+declare!
+decompose
+decomposeFunc
+decrease
+decreasePrecision
+deepCopy
+deepestInitial
+deepestTail
+deepExpand
+defineProperty
+definingEquations
+definingInequation
+definingPolynomial
+degree
+degreePartition
+degreeSubResultant
+degreeSubResultantEuclidean
+delay
+delete
+delete!
+deleteProperty!
+deleteRoutine!
+delta
+denom
+denominator
+denominators
+denomLODE
+denomRicDE
+depth
+dequeue
+dequeue!
+deref
+deriv
+derivationCoordinates
+derivative
+destruct
+determinant
+df2ef
+df2fi
+df2mf
+df2st
+dflist
+dfRange
+diag
+diagonal
+diagonal?
+diagonalMatrix
+diagonalProduct
+diagonals
+dictionary
+diff
+difference
+differentialVariables
+differentiate
+digamma
+digit
+digit?
+digits
+dihedral
+dihedralGroup
+dilog
+dim
+dimension
+dimensionOfIrreducibleRepresentation
+dimensions
+dimensionsOf
+diophantineSystem
+dioSolve
+direction
+directory
+directProduct
+directSum
+discreteLog
+discriminant
+discriminantEuclidean
+display
+dispose!
+distance
+distdfact
+distFact
+distribute
+div
+divergence
+divide
+divideExponents
+divideIfCan
+divideIfCan!
+divisor
+divisorCascade
+divisors
+dmp2rfi
+dmpToHdmp
+dmpToP
+dn
+dom
+domainOf
+dominantTerm
+dot
+double
+double?
+doubleComplex?
+doubleDisc
+doubleRank
+doubleResultant
+doublyTransitive?
+draw
+drawComplex
+drawComplexVectorField
+drawCurves
+drawStyle
+drawToScale
+droot
+duplicates
+duplicates?
+e
+e01baf
+e01bef
+e01bff
+e01bgf
+e01bhf
+e01daf
+e01saf
+e01sbf
+e01sef
+e01sff
+e02adf
+e02aef
+e02agf
+e02ahf
+e02ajf
+e02akf
+e02baf
+e02bbf
+e02bcf
+e02bdf
+e02bef
+e02daf
+e02dcf
+e02ddf
+e02def
+e02dff
+e02gaf
+e02zaf
+e04dgf
+e04fdf
+e04gcf
+e04jaf
+e04mbf
+e04naf
+e04ucf
+e04ycf
+edf2df
+edf2ef
+edf2efi
+edf2fi
+ef2edf
+Ei
+eigenMatrix
+eigenvalues
+eigenvector
+eigenvectors
+eisensteinIrreducible?
+elColumn2!
+elem?
+element?
+elementary
+elements
+elliptic
+elliptic?
+ellipticCylindrical
+elRow1!
+elRow2!
+elt
+empty
+empty?
+endOfFile?
+endSubProgram
+enqueue!
+enterInCache
+enterPointData
+entries
+entry
+entry?
+enumerate
+epilogue
+EQ
+eq
+eq?
+equality
+equation
+erf
+error
+errorInfo
+errorKind
+escape
+euclideanGroebner
+euclideanNormalForm
+euclideanSize
+euler
+eulerE
+eulerPhi
+eval
+evaluate
+evaluateInverse
+even?
+evenInfiniteProduct
+evenlambert
+every?
+exactQuotient
+exactQuotient!
+exists?
+exp
+exp1
+expand
+expandLog
+expandPower
+expandTrigProducts
+expenseOfEvaluation
+expenseOfEvaluationIF
+expextendedint
+expIfCan
+expint
+expintegrate
+expintfldpoly
+explicitEntries?
+explicitlyEmpty?
+explicitlyFinite?
+explimitedint
+explogs2trigs
+exponent
+exponential
+exponential1
+exponentialOrder
+exponents
+expPot
+expr
+expressIdealMember
+exprHasAlgebraicWeight
+exprHasLogarithmicWeights
+exprHasWeightCosWXorSinWX
+exprToGenUPS
+exprToUPS
+exprToXXP
+expt
+exptMod
+exQuo
+exquo
+extend
+extendedEuclidean
+extendedint
+extendedIntegrate
+extendedResultant
+extendedSubResultantGcd
+extendIfCan
+extension
+extensionDegree
+exteriorDifferential
+external?
+externalList
+extract!
+extractBottom!
+extractClosed
+extractIfCan
+extractIndex
+extractPoint
+extractProperty
+extractSplittingLeaf
+extractTop!
+eyeDistance
+F
+f01brf
+f01bsf
+f01maf
+f01mcf
+f01qcf
+f01qdf
+f01qef
+f01rcf
+f01rdf
+f01ref
+f02aaf
+f02abf
+f02adf
+f02aef
+f02aff
+f02agf
+f02ajf
+f02akf
+f02awf
+f02axf
+f02bbf
+f02bjf
+f02fjf
+f02wef
+f02xef
+f04adf
+f04arf
+f04asf
+f04atf
+f04axf
+f04faf
+f04jgf
+f04maf
+f04mbf
+f04mcf
+f04qaf
+f07adf
+f07aef
+f07fdf
+f07fef
+f2df
+F2FG
+f2st
+factor
+factor1
+factorAndSplit
+factorByRecursion
+factorFraction
+factorGroebnerBasis
+factorial
+factorials
+factorList
+factorOfDegree
+factorPolynomial
+factors
+factorset
+factorSFBRlcUnit
+factorsOfCyclicGroupSize
+factorsOfDegree
+factorSquareFree
+factorSquareFreeByRecursion
+factorSquareFreePolynomial
+failed
+failed?
+false
+ffactor
+FG2F
+fglmIfCan
+fi2df
+fibonacci
+field
+fields
+figureUnits
+filename
+fill!
+fillPascalTriangle
+filterUntil
+filterWhile
+find
+findCycle
+finite?
+finiteBasis
+finiteBound
+fintegrate
+first
+firstDenom
+firstNumer
+firstSubsetGray
+firstUncouplingMatrix
+fixedDivisor
+fixedPoint
+fixedPointExquo
+fixedPoints
+fixPredicate
+flagFactor
+flatten
+flexible?
+flexibleArray
+float
+float?
+floatlist
+floatlist?
+floor
+fmecg
+forLoop
+FormatArabic
+FormatRoman
+formula
+fortran
+fortranCarriageReturn
+fortranCharacter
+fortranCompilerName
+fortranComplex
+fortranDouble
+fortranDoubleComplex
+fortranInteger
+fortranLinkerArgs
+fortranLiteral
+fortranLiteralLine
+fortranLogical
+fortranReal
+fortranTypeOf
+fprindINFO
+fracPart
+fractionFreeGauss!
+fractionPart
+fractRadix
+fractRagits
+freeOf?
+Frobenius
+frobenius
+front
+froot
+frst
+fTable
+fullDisplay
+fullPartialFraction
+function
+functionIsContinuousAtEndPoints
+functionIsFracPolynomial?
+functionIsOscillatory
+Gamma
+gbasis
+gcd
+gcdcofact
+gcdcofactprim
+gcdPolynomial
+gcdprim
+gcdPrimitive
+gderiv
+GE
+generalInfiniteProduct
+generalizedContinuumHypothesisAssumed
+generalizedContinuumHypothesisAssumed?
+generalizedEigenvector
+generalizedEigenvectors
+generalizedInverse
+generalLambert
+generalPosition
+generalSqFr
+generalTwoFactor
+generate
+generateIrredPoly
+generator
+generators
+generic
+generic?
+genericLeftDiscriminant
+genericLeftMinimalPolynomial
+genericLeftNorm
+genericLeftTrace
+genericLeftTraceForm
+genericPosition
+genericRightDiscriminant
+genericRightMinimalPolynomial
+genericRightNorm
+genericRightTrace
+genericRightTraceForm
+genus
+geometric
+getBadValues
+getButtonValue
+getCode
+getCurve
+getDatabase
+getExplanations
+getGoodPrime
+getGraph
+gethi
+getlo
+getMatch
+getMeasure
+getMultiplicationMatrix
+getMultiplicationTable
+getOrder
+getPickedPoints
+getRef
+getStream
+getVariableOrder
+getZechTable
+GF2FG
+goodnessOfFit
+goodPoint
+GospersMethod
+goto
+gradient
+graeffe
+gramschmidt
+graphCurves
+graphImage
+graphs
+graphState
+graphStates
+green
+groebgen
+groebner
+groebner?
+groebnerFactorize
+groebnerIdeal
+groebSolve
+ground
+ground?
+GT
+halfExtendedResultant1
+halfExtendedResultant2
+halfExtendedSubResultantGcd1
+halfExtendedSubResultantGcd2
+harmonic
+has?
+hash
+hasHi
+hasoln
+hasPredicate?
+hasSolution?
+hasTopPredicate?
+Hausdorff
+hclf
+hconcat
+hcrf
+hdmpToDmp
+hdmpToP
+head
+headReduce
+headReduced?
+headRemainder
+heap
+heapSort
+height
+henselFact
+HenselLift
+hermite
+hermiteH
+HermiteIntegrate
+hessian
+hex
+hexDigit
+hexDigit?
+hi
+high
+highCommonTerms
+hitherPlane
+hMonic
+HMS
+homogeneous?
+horizConcat
+hspace
+htrigs
+hue
+hyperelliptic
+hypergeometric0F1
+iCompose
+id
+ideal
+idealiser
+idealiserMatrix
+idealSimplify
+identification
+identity
+identityMatrix
+identitySquareMatrix
+iExquo
+iflist2Result
+iFTable
+ignore?
+iiabs
+iiacos
+iiacosh
+iiacot
+iiacoth
+iiacsc
+iiacsch
+iiasec
+iiasech
+iiasin
+iiasinh
+iiatan
+iiatanh
+iibinom
+iicos
+iicosh
+iicot
+iicoth
+iicsc
+iicsch
+iidprod
+iidsum
+iiexp
+iifact
+iiGamma
+iilog
+iiperm
+iipow
+iisec
+iisech
+iisin
+iisinh
+iisqrt2
+iisqrt3
+iitan
+iitanh
+imag
+imagE
+imagI
+imagi
+imaginary
+imagJ
+imagj
+imagK
+imagk
+implies
+in?
+inc
+incr
+increase
+increasePrecision
+increment
+incrementBy
+incrementKthElement
+index
+index?
+indices
+indiceSubResultant
+indiceSubResultantEuclidean
+indicialEquation
+indicialEquationAtInfinity
+indicialEquations
+inf
+infieldint
+infieldIntegrate
+infinite?
+infiniteProduct
+infinity
+infinityNorm
+infix
+infix?
+infLex?
+infRittWu?
+inGroundField?
+inHallBasis?
+init
+initial
+initializeGroupForWordProblem
+initiallyReduce
+initiallyReduced?
+initials
+initTable!
+innerEigenvectors
+innerint
+innerSolve
+innerSolve1
+input
+inR?
+inRadical?
+inrootof
+insert
+insert!
+insertBottom!
+insertionSort!
+insertMatch
+insertRoot!
+insertTop!
+inspect
+int
+int?
+intChoose
+intcompBasis
+integer
+integer?
+integerBound
+integerIfCan
+integers
+integral
+integral?
+integralAtInfinity?
+integralBasis
+integralBasisAtInfinity
+integralCoordinates
+integralDerivationMatrix
+integralLastSubResultant
+integralMatrix
+integralMatrixAtInfinity
+integralRepresents
+integrate
+intensity
+intermediateResultsIF
+internal?
+internalAugment
+internalDecompose
+internalInfRittWu?
+internalIntegrate
+internalIntegrate0
+internalLastSubResultant
+internalSubPolSet?
+internalSubQuasiComponent?
+internalZeroSetSplit
+interpolate
+interpret
+interpretString
+interReduce
+intersect
+interval
+intlist
+intlist?
+intPatternMatch
+inv
+inverse
+inverseColeman
+inverseIntegralMatrix
+inverseIntegralMatrixAtInfinity
+inverseLaplace
+invertible?
+invertibleElseSplit?
+invertibleSet
+invertIfCan
+invmod
+invmultisect
+invWrite
+iomode
+ipow
+iprint
+iroot
+irreducible?
+irreducibleFactor
+irreducibleFactors
+irreducibleRepresentation
+Is
+is?
+isAbsolutelyIrreducible?
+isExpt
+isList
+isMult
+isobaric?
+isOp
+isPlus
+isPower
+isQuotient
+isTimes
+iter
+iteratedInitials
+jacobi
+jacobian
+jacobiIdentity?
+janko2
+jordanAdmissible?
+jordanAlgebra?
+karatsuba
+karatsubaDivide
+karatsubaOnce
+kernel
+kernels
+key
+key?
+keys
+kmax
+knownInfBasis
+kovacic
+kroneckerDelta
+KrullNumber
+ksec
+label
+lagrange
+LagrangeInterpolation
+laguerre
+laguerreL
+lambda
+lambert
+laplace
+laplacian
+largest
+last
+lastSubResultant
+lastSubResultantElseSplit
+lastSubResultantEuclidean
+latex
+laurent
+laurentIfCan
+laurentRep
+Lazard
+Lazard2
+LazardQuotient
+LazardQuotient2
+lazy?
+lazyEvaluate
+lazyGintegrate
+lazyIntegrate
+lazyIrreducibleFactors
+lazyPquo
+lazyPrem
+lazyPremWithDefault
+lazyPseudoDivide
+lazyPseudoQuotient
+lazyPseudoRemainder
+lazyResidueClass
+lazyVariations
+lcm
+ldf2lst
+ldf2vmf
+LE
+leader
+leadingBasisTerm
+leadingCoefficient
+leadingCoefficientRicDE
+leadingExponent
+leadingIdeal
+leadingIndex
+leadingMonomial
+leadingSupport
+leadingTerm
+leaf?
+leastAffineMultiple
+leastMonomial
+leastPower
+leaves
+left
+leftAlternative?
+leftCharacteristicPolynomial
+leftDiscriminant
+leftDivide
+leftExactQuotient
+leftExtendedGcd
+leftFactor
+leftFactorIfCan
+leftGcd
+leftLcm
+leftMinimalPolynomial
+leftMult
+leftNorm
+leftOne
+leftPower
+leftQuotient
+leftRank
+leftRankPolynomial
+leftRecip
+leftRegularRepresentation
+leftRemainder
+leftScalarTimes!
+leftTrace
+leftTraceMatrix
+leftTrim
+leftUnit
+leftUnits
+leftZero
+legendre
+legendreP
+lend!
+length
+lepol
+less?
+level
+leviCivitaSymbol
+lex
+lexGroebner
+lexico
+lexTriangular
+lfextendedint
+lfextlimint
+lfinfieldint
+lfintegrate
+lflimitedint
+lfunc
+lhs
+li
+library
+lieAdmissible?
+lieAlgebra?
+LiePoly
+LiePolyIfCan
+lift
+lifting
+lifting1
+light
+lighting
+limit
+limitedint
+limitedIntegrate
+limitPlus
+linear
+linear?
+linearAssociatedExp
+linearAssociatedLog
+linearAssociatedOrder
+linearDependence
+linearDependenceOverZ
+linearlyDependent?
+linearlyDependentOverZ?
+linearMatrix
+linearPart
+linearPolynomials
+linears
+lineColorDefault
+linGenPos
+linkToFortran
+linSolve
+lintgcd
+list
+list?
+listBranches
+listConjugateBases
+listexp
+listLoops
+listOfLists
+listOfMonoms
+ListOfTerms
+listRepresentation
+lists
+listYoungTableaus
+lllip
+lllp
+llprop
+lo
+localAbs
+localIntegralBasis
+localReal?
+localUnquote
+LODO2FUN
+log
+log10
+log2
+logGamma
+logical?
+logIfCan
+logpart
+lookup
+loopPoints
+low
+lowerCase
+lowerCase!
+lowerCase?
+lowerPolynomial
+LowTriBddDenomInv
+lp
+lprop
+lquo
+lSpaceBasis
+lstart!
+LT
+lyndon
+lyndon?
+LyndonBasis
+LyndonCoordinates
+lyndonIfCan
+LyndonWordsList
+LyndonWordsList1
+magnitude
+mainCharacterization
+mainCoefficients
+mainContent
+mainDefiningPolynomial
+mainForm
+mainKernel
+mainMonomial
+mainMonomials
+mainPrimitivePart
+mainSquareFreePart
+mainValue
+mainVariable
+mainVariable?
+mainVariables
+make
+makeCos
+makeCrit
+makeEq
+makeFloatFunction
+makeFR
+makeGraphImage
+makeMulti
+makeObject
+makeop
+makeprod
+makeRecord
+makeResult
+makeSceneGraph
+makeSeries
+makeSin
+makeSketch
+makeSUP
+makeTerm
+makeUnit
+makeVariable
+makeViewport2D
+makeViewport3D
+makeYoungTableau
+makingStats?
+mantissa
+map
+map!
+mapBivariate
+mapCoef
+mapdiv
+mapDown!
+mapExpon
+mapExponents
+mapGen
+mapMatrixIfCan
+mapmult
+mapSolve
+mapUnivariate
+mapUnivariateIfCan
+mapUp!
+mask
+mat
+match
+match?
+mathieu11
+mathieu12
+mathieu22
+mathieu23
+mathieu24
+matrix
+matrixConcat3D
+matrixDimensions
+matrixGcd
+max
+maxColIndex
+maxdeg
+maximumExponent
+maxIndex
+maxint
+maxPoints
+maxPoints3D
+maxrank
+maxrow
+maxRowIndex
+mdeg
+measure
+measure2Result
+meatAxe
+medialSet
+member?
+members
+merge
+merge!
+mergeDifference
+mergeFactors
+mesh
+mesh?
+meshFun2Var
+meshPar1Var
+meshPar2Var
+message
+messagePrint
+middle
+midpoint
+midpoints
+mightHaveRoots
+min
+minColIndex
+mindeg
+mindegTerm
+minGbasis
+minimalPolynomial
+minimize
+minimumDegree
+minimumExponent
+minIndex
+minordet
+minPoints
+minPoints3D
+minPol
+minPoly
+minrank
+minRowIndex
+minset
+minus!
+minusInfinity
+mirror
+mix
+mkAnswer
+mkcomm
+mkIntegral
+mkPrim
+modifyPoint
+modifyPointData
+modTree
+modularFactor
+modularGcd
+modularGcdPrimitive
+module
+moduleSum
+moduloP
+modulus
+moebius
+moebiusMu
+monic?
+monicCompleteDecompose
+monicDecomposeIfCan
+monicDivide
+monicLeftDivide
+monicModulo
+monicRightDivide
+monicRightFactorIfCan
+monom
+monomial
+monomial?
+monomialIntegrate
+monomialIntPoly
+monomials
+monomRDE
+monomRDEsys
+more?
+moreAlgebraic?
+morphism
+move
+movedPoints
+mpsode
+mr
+mulmod
+multiEuclidean
+multiEuclideanTree
+multinomial
+multiple
+multiple?
+multiplyCoefficients
+multiplyExponents
+multisect
+multiset
+multivariate
+multMonom
+musserTrials
+mvar
+myDegree
+nagCosInt
+nagDAiryAi
+nagDAiryBi
+nagDFT
+nagEigenvalues
+nagEigenvectors
+nagEllipticIntegralRC
+nagEllipticIntegralRD
+nagEllipticIntegralRF
+nagEllipticIntegralRJ
+nagErf
+nagErfC
+nagExpInt
+nagFresnelC
+nagFresnelS
+nagHankelH1
+nagHankelH2
+nagHermitianDFT
+nagHermitianInverseDFT
+nagIncompleteGammaP
+nagIncompleteGammaQ
+nagInverseDFT
+nagKelvinBei
+nagKelvinBer
+nagKelvinKei
+nagKelvinKer
+nagMin
+nagPolygonIntegrate
+nagScaledDAiryAi
+nagScaledDAiryBi
+nagScaledHankelH1
+nagScaledHankelH2
+nagSinInt
+name
+nand
+nary?
+ncols
+negative?
+neglist
+new
+newLine
+newReduc
+newSubProgram
+newTypeLists
+next
+nextColeman
+nextIrreduciblePoly
+nextItem
+nextLatticePermutation
+nextNormalPoly
+nextNormalPrimitivePoly
+nextPartition
+nextPrime
+nextPrimitiveNormalPoly
+nextPrimitivePoly
+nextsousResultant2
+nextSublist
+nextsubResultant2
+nextSubsetGray
+nil
+nilFactor
+nlde
+node
+node?
+nodeOf?
+nodes
+noKaratsuba
+noLinearFactor?
+noncommutativeJordanAlgebra?
+nonLinearPart
+nonQsign
+nonSingularModel
+nor
+norm
+normal
+normal?
+normal01
+normalDenom
+normalDeriv
+normalElement
+normalForm
+normalise
+normalize
+normalizeAtInfinity
+normalized?
+normalizedAssociate
+normalizedDivide
+normalizeIfCan
+normDeriv2
+normFactors
+normInvertible?
+NOT
+Not
+not
+notelem
+npcoef
+nrows
+nsqfree
+nthCoef
+nthExpon
+nthExponent
+nthFactor
+nthFlag
+nthFractionalTerm
+nthr
+nthRoot
+nthRootIfCan
+Nul
+null
+null?
+nullary
+nullary?
+nullity
+nullSpace
+number?
+numberOfChildren
+numberOfComponents
+numberOfComposites
+numberOfComputedEntries
+numberOfCycles
+numberOfDivisors
+numberOfFactors
+numberOfFractionalTerms
+numberOfHues
+numberOfImproperPartitions
+numberOfIrreduciblePoly
+numberOfMonomials
+numberOfNormalPoly
+numberOfOperations
+numberOfPrimitivePoly
+numberOfVariables
+numer
+numerator
+numerators
+numeric
+numericalIntegration
+numericalOptimization
+numericIfCan
+numFunEvals
+numFunEvals3D
+obj
+objectOf
+objects
+oblateSpheroidal
+ocf2ocdf
+octon
+odd?
+oddInfiniteProduct
+oddintegers
+oddlambert
+ode
+ode1
+ode2
+ODESolve
+OMbindTCP
+OMclose
+OMcloseConn
+OMconnectTCP
+OMconnInDevice
+OMconnOutDevice
+OMencodingBinary
+OMencodingSGML
+OMencodingUnknown
+OMencodingXML
+omError
+OMgetApp
+OMgetAtp
+OMgetAttr
+OMgetBind
+OMgetBVar
+OMgetEndApp
+OMgetEndAtp
+OMgetEndAttr
+OMgetEndBind
+OMgetEndBVar
+OMgetEndError
+OMgetEndObject
+OMgetError
+OMgetFloat
+OMgetInteger
+OMgetObject
+OMgetString
+OMgetSymbol
+OMgetType
+OMgetVariable
+OMlistCDs
+OMlistSymbols
+OMmakeConn
+OMopenFile
+OMopenString
+OMParseError?
+OMputApp
+OMputAtp
+OMputAttr
+OMputBind
+OMputBVar
+OMputEndApp
+OMputEndAtp
+OMputEndAttr
+OMputEndBind
+OMputEndBVar
+OMputEndError
+OMputEndObject
+OMputError
+OMputFloat
+OMputInteger
+OMputObject
+OMputString
+OMputSymbol
+OMputVariable
+OMread
+OMReadError?
+OMreadFile
+OMreadStr
+OMreceive
+OMsend
+OMserve
+OMsetEncoding
+OMsupportsCD?
+OMsupportsSymbol?
+OMunhandledSymbol
+OMUnknownCD?
+OMUnknownSymbol?
+OMwrite
+one?
+oneDimensionalArray
+op
+open
+open?
+operation
+operator
+operators
+opeval
+optAttributes
+optimize
+option
+option?
+optional
+optional?
+options
+optpair
+OR
+Or
+or
+orbit
+orbits
+ord
+order
+orthonormalBasis
+outerProduct
+outlineRender
+output
+outputArgs
+outputAsFortran
+outputAsScript
+outputAsTex
+outputFixed
+outputFloating
+outputForm
+outputGeneral
+outputList
+outputMeasure
+outputSpacing
+over
+overbar
+overlabel
+overlap
+overset?
+pack!
+packageCall
+packHS
+pade
+padecf
+padicallyExpand
+padicFraction
+pair?
+palgextint
+palgextint0
+palginfieldint
+palgint
+palgint0
+palgintegrate
+palglimint
+palglimint0
+palgLODE
+palgLODE0
+palgRDE
+palgRDE0
+parabolic
+parabolicCylindrical
+paraboloidal
+parametersOf
+parametric?
+ParCond
+ParCondList
+paren
+parent
+partialDenominators
+partialFraction
+partialNumerators
+partialQuotients
+particularSolution
+partition
+partitions
+parts
+pascalTriangle
+pastel
+pattern
+patternMatch
+patternMatchTimes
+patternVariable
+pdct
+PDESolve
+pdf2df
+pdf2ef
+perfectNthPower?
+perfectNthRoot
+perfectSqrt
+perfectSquare?
+permanent
+permutation
+permutationGroup
+permutationRepresentation
+permutations
+perspective
+phiCoord
+pHS
+physicalLength
+physicalLength!
+pi
+pile
+plenaryPower
+pleskenSplit
+plot
+plotPolar
+plus
+plus!
+plusInfinity
+pmComplexintegrate
+pmintegrate
+po
+point
+point?
+pointColor
+pointColorDefault
+pointColorPalette
+pointData
+pointlist
+pointlist?
+pointLists
+pointPlot
+points
+pointSizeDefault
+poisson
+pol
+polar
+polarCoordinates
+polCase
+pole?
+PollardSmallFactor
+polygamma
+polygon
+polygon?
+polynomial
+polynomialZeros
+polyPart
+polyRDE
+polyred
+polyRicDE
+pomopo!
+pop!
+popFortranOutputStack
+position
+position!
+positive?
+positiveRemainder
+positiveSolve
+possiblyInfinite?
+possiblyNewVariety?
+postfix
+pow
+power
+power!
+powerAssociative?
+powern
+powers
+powerSum
+powmod
+pquo
+pr2dmp
+precision
+predicate
+predicates
+prefix
+prefix?
+prefixRagits
+prem
+prepareDecompose
+prepareSubResAlgo
+preprocess
+presub
+presuper
+previous
+prevPrime
+primaryDecomp
+prime
+prime?
+primeFactor
+primeFrobenius
+primes
+primextendedint
+primextintfrac
+primintegrate
+primintfldpoly
+primitive?
+primitiveElement
+primitiveMonomials
+primitivePart
+primitivePart!
+primlimintfrac
+primlimitedint
+primPartElseUnitCanonical
+primPartElseUnitCanonical!
+prinb
+principal?
+principalIdeal
+prindINFO
+prinpolINFO
+prinshINFO
+print
+printCode
+printHeader
+printInfo
+printInfo!
+printingInfo?
+printStatement
+printStats!
+printTypes
+probablyZeroDim?
+problemPoints
+processTemplate
+prod
+product
+prolateSpheroidal
+prologue
+properties
+property
+pseudoDivide
+pseudoQuotient
+pseudoRemainder
+psolve
+ptFunc
+pToDmp
+pToHdmp
+ptree
+puiseux
+pureLex
+purelyAlgebraic?
+purelyAlgebraicLeadingMonomial?
+purelyTranscendental?
+push!
+pushdown
+pushdterm
+pushFortranOutputStack
+pushucoef
+pushuconst
+pushup
+put!
+putColorInfo
+putGraph
+qelt
+qfactor
+qinterval
+qPot
+qqq
+qroot
+qsetelt!
+quadratic
+quadratic?
+quadraticForm
+quadraticNorm
+quartic
+quasiAlgebraicSet
+quasiComponent
+quasiMonic?
+quasiMonicPolynomials
+quasiRegular
+quasiRegular?
+quatern
+queue
+quickSort
+quickWrite
+quo
+quoByVar
+quote
+quoted?
+quotedOperators
+quotient
+quotientByP
+radical
+radicalEigenvalues
+radicalEigenvector
+radicalEigenvectors
+radicalOfLeftTraceForm
+radicalRoots
+radicalSimplify
+radicalSolve
+radix
+radPoly
+raisePolynomial
+ramified?
+ramifiedAtInfinity?
+ran
+randnum
+random
+randomLC
+randomR
+range
+rangeIsFinite
+rangePascalTriangle
+ranges
+rank
+rarrow
+ratDenom
+ratDsolve
+rational
+rational?
+rationalApproximation
+rationalFunction
+rationalIfCan
+rationalPoint?
+rationalPoints
+rationalPower
+ratpart
+ratPoly
+ravel
+rCoord
+rdHack1
+rdregime
+read
+read!
+readable?
+readIfCan!
+readLine!
+readLineIfCan!
+real
+real?
+realEigenvalues
+realEigenvectors
+realElementary
+realRoots
+realSolve
+realZeros
+recip
+reciprocalPolynomial
+recolor
+recoverAfterFail
+rectangularMatrix
+recur
+red
+redmat
+redPo
+redPol
+redpps
+reduce
+reduceBasisAtInfinity
+reduceByQuasiMonic
+reduced?
+reducedContinuedFraction
+reducedDiscriminant
+reducedForm
+reducedQPowers
+reducedSystem
+reduceLODE
+ReduceOrder
+reduction
+reductum
+ref
+refine
+regime
+region
+regularRepresentation
+reindex
+relationsIdeal
+relativeApprox
+relerror
+rem
+remainder
+RemainderList
+remove
+remove!
+removeConstantTerm
+removeCoshSq
+removeCosSq
+removeDuplicates
+removeDuplicates!
+removeIrreducibleRedundantFactors
+removeRedundantFactors
+removeRedundantFactorsInContents
+removeRedundantFactorsInPols
+removeRoughlyRedundantFactorsInContents
+removeRoughlyRedundantFactorsInPol
+removeRoughlyRedundantFactorsInPols
+removeSinhSq
+removeSinSq
+removeSquaresIfCan
+removeSuperfluousCases
+removeSuperfluousQuasiComponents
+removeZero
+removeZeroes
+rename
+rename!
+render
+renderToFile!
+reopen!
+reorder
+repeating
+repeating?
+repeatUntilLoop
+replace
+replaceKthElement
+representationType
+represents
+repSq
+reseed
+reset
+reset!
+resetAttributeButtons
+resetBadValues
+resetNew
+resetVariableOrder
+reshape
+resize
+rest
+restorePrecision
+result
+resultant
+resultantEuclidean
+resultantEuclideannaif
+resultantnaif
+resultantReduit
+resultantReduitEuclidean
+retract
+retractable?
+retractIfCan
+returns
+returnType!
+returnTypeOf
+reverse
+reverse!
+reverseLex
+revert
+rewriteIdealWithHeadRemainder
+rewriteIdealWithQuasiMonicGenerators
+rewriteIdealWithRemainder
+rewriteSetByReducingWithParticularGenerators
+rewriteSetWithReduction
+RF2UTS
+rhs
+ricDsolve
+ridHack1
+right
+rightAlternative?
+rightCharacteristicPolynomial
+rightDiscriminant
+rightDivide
+rightExactQuotient
+rightExtendedGcd
+rightFactorCandidate
+rightFactorIfCan
+rightGcd
+rightLcm
+rightMinimalPolynomial
+rightMult
+rightNorm
+rightOne
+rightPower
+rightQuotient
+rightRank
+rightRankPolynomial
+rightRecip
+rightRegularRepresentation
+rightRemainder
+rightScalarTimes!
+rightTrace
+rightTraceMatrix
+rightTrim
+rightUnit
+rightUnits
+rightZero
+rischDE
+rischDEsys
+rischNormalize
+RittWuCompare
+rk4
+rk4a
+rk4f
+rk4qc
+roman
+romberg
+rombergo
+root
+root?
+rootBound
+rootKerSimp
+rootNormalize
+rootOf
+rootOfIrreduciblePoly
+rootPoly
+rootPower
+rootProduct
+rootRadius
+rootSimp
+rootsOf
+rootSplit
+rotate
+rotate!
+rotatex
+rotatey
+rotatez
+roughBase?
+roughBasicSet
+roughEqualIdeals?
+roughSubIdeal?
+roughUnitIdeal?
+round
+routines
+row
+rowEch
+rowEchelon
+rowEchelonLocal
+rowEchLocal
+rquo
+rroot
+rspace
+rst
+rubiksGroup
+rule
+rules
+ruleset
+rur
+s01eaf
+s13aaf
+s13acf
+s13adf
+s14aaf
+s14abf
+s14baf
+s15adf
+s15aef
+s17acf
+s17adf
+s17aef
+s17aff
+s17agf
+s17ahf
+s17ajf
+s17akf
+s17dcf
+s17def
+s17dgf
+s17dhf
+s17dlf
+s18acf
+s18adf
+s18aef
+s18aff
+s18dcf
+s18def
+s19aaf
+s19abf
+s19acf
+s19adf
+s20acf
+s20adf
+s21baf
+s21bbf
+s21bcf
+s21bdf
+safeCeiling
+safeFloor
+safetyMargin
+sample
+satisfy?
+saturate
+save
+say
+sayLength
+scalarMatrix
+scalarTypeOf
+scale
+scaleRoots
+scan
+ScanArabic
+ScanFloatIgnoreSpaces
+ScanFloatIgnoreSpacesIfCan
+scanOneDimSubspaces
+ScanRoman
+schema
+schwerpunkt
+screenResolution
+screenResolution3D
+script
+scripted?
+scripts
+sdf2lst
+se2rfi
+search
+sec
+sec2cos
+sech
+sech2cosh
+sechIfCan
+secIfCan
+second
+seed
+SEGMENT
+segment
+select
+select!
+selectAndPolynomials
+selectFiniteRoutines
+selectfirst
+selectIntegrationRoutines
+selectMultiDimensionalRoutines
+selectNonFiniteRoutines
+selectODEIVPRoutines
+selectOptimizationRoutines
+selectOrPolynomials
+selectPDERoutines
+selectPolynomials
+selectsecond
+selectSumOfSquaresRoutines
+semicolonSeparate
+semiDegreeSubResultantEuclidean
+semiDiscriminantEuclidean
+semiIndiceSubResultantEuclidean
+semiLastSubResultantEuclidean
+semiResultantEuclidean1
+semiResultantEuclidean2
+semiResultantEuclideannaif
+semiResultantReduitEuclidean
+semiSubResultantGcdEuclidean1
+semiSubResultantGcdEuclidean2
+separant
+separate
+separateDegrees
+separateFactors
+sequences
+series
+seriesSolve
+seriesToOutputForm
+set
+setAdaptive
+setAdaptive3D
+setAttributeButtonStep
+setButtonValue
+setchildren!
+setClipValue
+setClosed
+setColumn!
+setCondition!
+setDifference
+setelt
+setelt!
+setEmpty!
+setEpilogue!
+setErrorBound
+setFieldInfo
+setfirst!
+setFormula!
+setImagSteps
+setIntersection
+setLabelValue
+setlast!
+setleaves!
+setleft!
+setLegalFortranSourceExtensions
+setMaxPoints
+setMaxPoints3D
+setMinPoints
+setMinPoints3D
+setnext!
+setOfMinN
+setOrder
+setPoly
+setPosition
+setPredicates
+setprevious!
+setPrologue!
+setProperties
+setProperty
+setRealSteps
+setref
+setrest!
+setright!
+setRow!
+setScreenResolution
+setScreenResolution3D
+setStatus
+setStatus!
+setsubMatrix!
+setTex!
+setTopPredicate
+setUnion
+setValue!
+setvalue!
+setVariableOrder
+SFunction
+sh
+shade
+shallowCopy
+shallowExpand
+shanksDiscLogAlgorithm
+shellSort
+shift
+shiftLeft
+shiftRight
+shiftRoots
+show
+showAll?
+showAllElements
+showArrayValues
+showAttributes
+showClipRegion
+showFortranOutputStack
+showIntensityFunctions
+showRegion
+showScalarValues
+showTheFTable
+showTheIFTable
+showTheRoutinesTable
+showTheSymbolTable
+showTypeInOutput
+shrinkable
+shuffle
+shufflein
+Si
+sign
+signAround
+simpleBounds?
+simplify
+simplifyExp
+simplifyLog
+simplifyPower
+simpson
+simpsono
+sin
+sin?
+sin2csc
+sincos
+singleFactorBound
+singRicDE
+singular?
+singularAtInfinity?
+singularitiesOf
+sinh
+sinh2csch
+sinhcosh
+sinhIfCan
+sinIfCan
+size
+size?
+sizeLess?
+sizeMultiplication
+sizePascalTriangle
+skewSFunction
+slash
+slex
+smith
+sn
+sncndn
+socf2socdf
+solid
+solid?
+solve
+solve1
+solveid
+solveInField
+solveLinear
+solveLinearlyOverQ
+solveLinearPolynomialEquation
+solveLinearPolynomialEquationByFractions
+solveLinearPolynomialEquationByRecursion
+solveRetract
+someBasis
+sort
+sort!
+sortConstraints
+sorted?
+space
+sparsityIF
+specialTrigs
+spherical
+split
+split!
+splitConstant
+splitDenominator
+splitLinear
+splitNodeOf!
+splitSquarefree
+sPol
+sqfree
+sqfrFactor
+sqrt
+square?
+squareFree
+squareFreeFactors
+squareFreeLexTriangular
+squareFreePart
+squareFreePolynomial
+squareFreePrim
+squareMatrix
+squareTop
+stack
+standardBasisOfCyclicSubmodule
+start!
+startPolynomial
+startStats!
+startTable!
+startTableGcd!
+startTableInvSet!
+status
+stFunc1
+stFunc2
+stFuncN
+stiffnessAndStabilityFactor
+stiffnessAndStabilityOfODEIF
+stirling1
+stirling2
+stop
+stop!
+stopMusserTrials
+stopTable!
+stopTableGcd!
+stopTableInvSet!
+stoseIntegralLastSubResultant
+stoseInternalLastSubResultant
+stoseInvertible?
+stoseInvertible?reg
+stoseInvertibleSet
+stoseInvertibleSetreg
+stoseInvertibleSetsqfreg
+stoseInvertible?sqfreg
+stoseLastSubResultant
+stosePrepareSubResAlgo
+stoseSquareFreePart
+string
+string?
+stripCommentsAndBlanks
+strongGenerators
+stronglyReduce
+stronglyReduced?
+structuralConstants
+sts2stst
+SturmHabicht
+SturmHabichtCoefficients
+SturmHabichtMultiple
+SturmHabichtSequence
+sturmSequence
+sturmVariationsOf
+style
+sub
+subCase?
+subHeight
+subMatrix
+submod
+subNode?
+subNodeOf?
+subPolSet?
+subQuasiComponent?
+subResultantChain
+subResultantGcd
+subResultantGcdEuclidean
+subResultantsChain
+subresultantSequence
+subresultantVector
+subscript
+subscriptedVariables
+subSet
+subset?
+subspace
+subst
+substitute
+substring?
+subtractIfCan
+subTriSet?
+suchThat
+suffix?
+sum
+summation
+sumOfDivisors
+sumOfKthPowerDivisors
+sumOfSquares
+sumSquares
+sup
+supDimElseRittWu?
+super
+superHeight
+superscript
+supersub
+supRittWu?
+surface
+swap
+swap!
+swapColumns!
+swapRows!
+sylvesterMatrix
+sylvesterSequence
+symbol
+symbol?
+symbolIfCan
+symbolTable
+symbolTableOf
+symFunc
+symmetric?
+symmetricDifference
+symmetricGroup
+symmetricPower
+symmetricProduct
+symmetricRemainder
+symmetricSquare
+symmetricTensors
+systemCommand
+systemSizeIF
+t
+tab
+tab1
+table
+tableau
+tableForDiscreteLogarithm
+tablePow
+tail
+tan
+tan2cot
+tan2trig
+tanAn
+tanh
+tanh2coth
+tanh2trigh
+tanhIfCan
+tanIfCan
+tanintegrate
+tanNa
+tanQ
+tanSum
+taylor
+taylorIfCan
+taylorQuoByVar
+taylorRep
+tensorProduct
+terms
+test
+testDim
+testModulus
+tex
+thetaCoord
+third
+timer
+times
+times!
+title
+top
+top!
+topFortranOutputStack
+topPredicate
+toroidal
+torsion?
+torsionIfCan
+toScale
+toseInvertible?
+toseInvertibleSet
+toseLastSubResultant
+toseSquareFreePart
+totalDegree
+totalDifferential
+totalfract
+totalGroebner
+totalLex
+totolex
+tower
+trace
+trace2PowMod
+traceMatrix
+tracePowMod
+trailingCoefficient
+tRange
+transcendenceDegree
+transcendent?
+transcendentalDecompose
+transform
+translate
+transpose
+trapezoidal
+trapezoidalo
+traverse
+tree
+triangSolve
+triangular?
+triangularSystems
+triangulate
+trigs
+trigs2explogs
+trim
+trivialIdeal?
+true
+trueEqual
+trunc
+truncate
+tryFunctionalDecomposition
+tryFunctionalDecomposition?
+tube
+tubePlot
+tubePoints
+tubePointsDefault
+tubeRadius
+tubeRadiusDefault
+tValues
+twist
+twoFactor
+typeList
+typeLists
+unary?
+unaryFunction
+uncouplingMatrices
+unexpand
+uniform
+uniform01
+union
+uniqueID
+unit
+unit?
+unitCanonical
+unitNormal
+unitNormalize
+units
+unitsColorDefault
+unitVector
+univariate
+univariate?
+univariatePolynomial
+univariatePolynomials
+univariatePolynomialsGcds
+univariateSolve
+univcase
+universe
+unmakeSUP
+unparse
+unprotectedRemoveRedundantFactors
+unrankImproperPartitions0
+unrankImproperPartitions1
+unravel
+untab
+UnVectorise
+unvectorise
+UP2ifCan
+UP2UTS
+updatD
+update
+upDateBranches
+updateStatus!
+updatF
+upperCase
+upperCase!
+upperCase?
+UpTriBddDenomInv
+useEisensteinCriterion
+useEisensteinCriterion?
+useNagFunctions
+userOrdered?
+useSingleFactorBound
+useSingleFactorBound?
+usingTable?
+UTS2UP
+validExponential
+value
+var1Steps
+var1StepsDefault
+var2Steps
+var2StepsDefault
+variable
+variables
+variationOfParameters
+vark
+varList
+varselect
+vconcat
+vector
+Vectorise
+vectorise
+vedf2vef
+vertConcat
+viewDefaults
+viewDeltaXDefault
+viewDeltaYDefault
+viewPhiDefault
+viewpoint
+viewport2D
+viewport3D
+viewPosDefault
+viewSizeDefault
+viewThetaDefault
+viewWriteAvailable
+viewWriteDefault
+viewZoomDefault
+virtualDegree
+void
+vput!
+vspace
+vstart!
+walkTree
+weakBiRank
+weierstrass
+weight
+weighted
+weights
+whatInfinity
+whileLoop
+wholePart
+wholeRadix
+wholeRagits
+width
+withPredicates
+wordInGenerators
+wordInStrongGenerators
+wordsForStrongGenerators
+wreath
+writable?
+write
+write!
+writeLine!
+wronskianMatrix
+wrregime
+xCoord
+xn
+xor
+xRange
+Y
+yCoord
+yCoordinates
+yellow
+youngGroup
+yRange
+zag
+zCoord
+zero
+zero?
+zeroDim?
+zeroDimensional?
+zeroDimPrimary?
+zeroDimPrime?
+zeroMatrix
+zeroOf
+zeroSetSplit
+zeroSetSplitIntoTriangularSystems
+zerosOf
+zeroSquareMatrix
+zeroVector
+zoom
+zRange
+AbelianGroup
+AbelianMonoid
+AbelianMonoidRing
+AbelianSemiGroup
+Aggregate
+Algebra
+AlgebraicallyClosedField
+AlgebraicallyClosedFunctionSpace
+ArcHyperbolicFunctionCategory
+ArcTrigonometricFunctionCategory
+AssociationListAggregate
+AttributeRegistry
+BagAggregate
+BasicType
+BiModule
+BinaryRecursiveAggregate
+BinaryTreeCategory
+BitAggregate
+CachableSet
+CancellationAbelianMonoid
+CharacteristicNonZero
+CharacteristicZero
+CoercibleTo
+Collection
+CombinatorialFunctionCategory
+CombinatorialOpsCategory
+CommutativeRing
+ComplexCategory
+ConvertibleTo
+DequeueAggregate
+Dictionary
+DictionaryOperations
+DifferentialExtension
+DifferentialPolynomialCategory
+DifferentialRing
+DifferentialVariableCategory
+DirectProductCategory
+DivisionRing
+DoublyLinkedAggregate
+ElementaryFunctionCategory
+Eltable
+EltableAggregate
+EntireRing
+EuclideanDomain
+Evalable
+ExpressionSpace
+ExtensibleLinearAggregate
+ExtensionField
+Field
+FieldOfPrimeCharacteristic
+FileCategory
+FileNameCategory
+Finite
+FiniteAbelianMonoidRing
+FiniteAlgebraicExtensionField
+FiniteDivisorCategory
+FiniteFieldCategory
+FiniteLinearAggregate
+FiniteRankAlgebra
+FiniteRankNonAssociativeAlgebra
+FiniteSetAggregate
+FloatingPointSystem
+FortranFunctionCategory
+FortranMachineTypeCategory
+FortranMatrixCategory
+FortranMatrixFunctionCategory
+FortranProgramCategory
+FortranVectorCategory
+FortranVectorFunctionCategory
+FramedAlgebra
+FramedNonAssociativeAlgebra
+FreeAbelianMonoidCategory
+FreeLieAlgebra
+FreeModuleCat
+FullyEvalableOver
+FullyLinearlyExplicitRingOver
+FullyPatternMatchable
+FullyRetractableTo
+FunctionFieldCategory
+FunctionSpace
+GcdDomain
+GradedAlgebra
+GradedModule
+Group
+HomogeneousAggregate
+HyperbolicFunctionCategory
+IndexedAggregate
+IndexedDirectProductCategory
+InnerEvalable
+IntegerNumberSystem
+IntegralDomain
+IntervalCategory
+IVLeafNodeCategory
+IVNodeCategory
+KeyedDictionary
+LazyStreamAggregate
+LeftAlgebra
+LeftModule
+LieAlgebra
+LinearAggregate
+LinearlyExplicitRingOver
+LinearOrdinaryDifferentialOperatorCategory
+LiouvillianFunctionCategory
+ListAggregate
+Logic
+MatrixCategory
+Module
+Monad
+MonadWithUnit
+MonogenicAlgebra
+MonogenicLinearOperator
+Monoid
+MultiDictionary
+MultisetAggregate
+MultivariateTaylorSeriesCategory
+NonAssociativeAlgebra
+NonAssociativeRing
+NonAssociativeRng
+NormalizedTriangularSetCategory
+NumericalIntegrationCategory
+NumericalOptimizationCategory
+OctonionCategory
+OneDimensionalArrayAggregate
+OpenMath
+OrderedAbelianGroup
+OrderedAbelianMonoid
+OrderedAbelianMonoidSup
+OrderedAbelianSemiGroup
+OrderedCancellationAbelianMonoid
+OrderedFinite
+OrderedIntegralDomain
+OrderedMonoid
+OrderedMultisetAggregate
+OrderedRing
+OrderedSet
+OrdinaryDifferentialEquationsSolverCategory
+PAdicIntegerCategory
+PartialDifferentialEquationsSolverCategory
+PartialDifferentialRing
+PartialTranscendentalFunctions
+Patternable
+PatternMatchable
+PermutationCategory
+PlottablePlaneCurveCategory
+PlottableSpaceCurveCategory
+PointCategory
+PolynomialCategory
+PolynomialFactorizationExplicit
+PolynomialSetCategory
+PowerSeriesCategory
+PrimitiveFunctionCategory
+PrincipalIdealDomain
+PriorityQueueAggregate
+QuaternionCategory
+QueueAggregate
+QuotientFieldCategory
+RadicalCategory
+RealClosedField
+RealConstant
+RealNumberSystem
+RealRootCharacterizationCategory
+RectangularMatrixCategory
+RecursiveAggregate
+RecursivePolynomialCategory
+RegularTriangularSetCategory
+RetractableTo
+RightModule
+Ring
+Rng
+SegmentCategory
+SegmentExpansionCategory
+SemiGroup
+SetAggregate
+SetCategory
+SExpressionCategory
+SpecialFunctionCategory
+SquareFreeNormalizedTriangularSetCategory
+SquareFreeRegularTriangularSetCategory
+SquareMatrixCategory
+StackAggregate
+StepThrough
+StreamAggregate
+StringAggregate
+StringCategory
+TableAggregate
+ThreeSpaceCategory
+TranscendentalFunctionCategory
+TriangularSetCategory
+TrigonometricFunctionCategory
+TwoDimensionalArrayCategory
+Type
+UnaryRecursiveAggregate
+UniqueFactorizationDomain
+UnivariateLaurentSeriesCategory
+UnivariateLaurentSeriesConstructorCategory
+UnivariatePolynomialCategory
+UnivariatePowerSeriesCategory
+UnivariatePuiseuxSeriesCategory
+UnivariatePuiseuxSeriesConstructorCategory
+UnivariateSkewPolynomialCategory
+UnivariateTaylorSeriesCategory
+VectorCategory
+VectorSpace
+XAlgebra
+XFreeAlgebra
+XPolynomialsCat
+AlgebraGivenByStructuralConstants
+AlgebraicFunctionField
+AlgebraicNumber
+AnonymousFunction
+AntiSymm
+Any
+ArrayStack
+Asp1
+Asp10
+Asp12
+Asp19
+Asp20
+Asp24
+Asp27
+Asp28
+Asp29
+Asp30
+Asp31
+Asp33
+Asp34
+Asp35
+Asp4
+Asp41
+Asp42
+Asp49
+Asp50
+Asp55
+Asp6
+Asp7
+Asp73
+Asp74
+Asp77
+Asp78
+Asp8
+Asp80
+Asp9
+AssociatedJordanAlgebra
+AssociatedLieAlgebra
+AssociationList
+AttributeButtons
+Automorphism
+BalancedBinaryTree
+BalancedPAdicInteger
+BalancedPAdicRational
+BasicFunctions
+BasicOperator
+BinaryExpansion
+BinaryFile
+BinarySearchTree
+BinaryTournament
+BinaryTree
+Bits
+Boolean
+CardinalNumber
+CartesianTensor
+Character
+CharacterClass
+CliffordAlgebra
+Color
+Commutator
+Complex
+ContinuedFraction
+d01ajfAnnaType
+d01akfAnnaType
+d01alfAnnaType
+d01amfAnnaType
+d01anfAnnaType
+d01apfAnnaType
+d01aqfAnnaType
+d01asfAnnaType
+d01fcfAnnaType
+d01gbfAnnaType
+d01TransformFunctionType
+d02bbfAnnaType
+d02bhfAnnaType
+d02cjfAnnaType
+d02ejfAnnaType
+d03eefAnnaType
+d03fafAnnaType
+Database
+DataList
+DecimalExpansion
+DenavitHartenbergMatrix
+Dequeue
+DeRhamComplex
+DifferentialSparseMultivariatePolynomial
+DirectProduct
+DirectProductMatrixModule
+DirectProductModule
+DistributedMultivariatePolynomial
+DoubleFloat
+DrawOption
+e04dgfAnnaType
+e04fdfAnnaType
+e04gcfAnnaType
+e04jafAnnaType
+e04mbfAnnaType
+e04nafAnnaType
+e04ucfAnnaType
+ElementaryFunctionsUnivariateLaurentSeries
+ElementaryFunctionsUnivariatePuiseuxSeries
+Enumeration
+EqTable
+Equation
+EuclideanModularRing
+Exit
+ExponentialExpansion
+ExponentialOfUnivariatePuiseuxSeries
+Expression
+ExtAlgBasis
+Factored
+File
+FileName
+FiniteDivisor
+FiniteField
+FiniteFieldCyclicGroup
+FiniteFieldCyclicGroupExtension
+FiniteFieldCyclicGroupExtensionByPolynomial
+FiniteFieldExtension
+FiniteFieldExtensionByPolynomial
+FiniteFieldNormalBasis
+FiniteFieldNormalBasisExtension
+FiniteFieldNormalBasisExtensionByPolynomial
+FlexibleArray
+Float
+FormalFraction
+FortranCode
+FortranExpression
+FortranProgram
+FortranScalarType
+FortranTemplate
+FortranType
+FourierComponent
+FourierSeries
+Fraction
+FractionalIdeal
+FramedModule
+FreeAbelianGroup
+FreeAbelianMonoid
+FreeGroup
+FreeModule
+FreeModule1
+FreeMonoid
+FreeNilpotentLie
+FullPartialFractionExpansion
+FunctionCalled
+GeneralDistributedMultivariatePolynomial
+GeneralModulePolynomial
+GeneralPolynomialSet
+GeneralSparseTable
+GeneralTriangularSet
+GeneralUnivariatePowerSeries
+GenericNonAssociativeAlgebra
+GraphImage
+HashTable
+Heap
+HexadecimalExpansion
+HomogeneousDirectProduct
+HomogeneousDistributedMultivariatePolynomial
+HyperellipticFiniteDivisor
+IndexCard
+IndexedBits
+IndexedDirectProductAbelianGroup
+IndexedDirectProductAbelianMonoid
+IndexedDirectProductObject
+IndexedDirectProductOrderedAbelianMonoid
+IndexedDirectProductOrderedAbelianMonoidSup
+IndexedExponents
+IndexedFlexibleArray
+IndexedList
+IndexedMatrix
+IndexedOneDimensionalArray
+IndexedString
+IndexedTwoDimensionalArray
+IndexedVector
+InfiniteTuple
+InnerAlgebraicNumber
+InnerFiniteField
+InnerFreeAbelianMonoid
+InnerIndexedTwoDimensionalArray
+InnerPAdicInteger
+InnerPrimeField
+InnerSparseUnivariatePowerSeries
+InnerTable
+InnerTaylorSeries
+InputForm
+Integer
+IntegerMod
+IntegrationFunctionsTable
+IntegrationResult
+Interval
+InventorDataSink
+InventorRenderPackage
+InventorViewPort
+IVBaseColor
+IVBasicNode
+IVCoordinate3
+IVCoordinate4
+IVFaceSet
+IVField
+IVGroup
+IVIndexedLineSet
+IVNodeConnection
+IVNodeObject
+IVPointSet
+IVQuadMesh
+IVSeparator
+IVSimpleInnerNode
+IVUtilities
+IVValue
+Kernel
+KeyedAccessFile
+LaurentPolynomial
+Library
+LieExponentials
+LiePolynomial
+LieSquareMatrix
+LinearOrdinaryDifferentialOperator
+LinearOrdinaryDifferentialOperator1
+LinearOrdinaryDifferentialOperator2
+List
+ListMonoidOps
+ListMultiDictionary
+LocalAlgebra
+Localize
+LyndonWord
+MachineComplex
+MachineFloat
+MachineInteger
+Magma
+MakeCachableSet
+Mapping
+Matrix
+ModMonic
+ModularField
+ModularRing
+ModuleMonomial
+ModuleOperator
+MoebiusTransform
+MonoidRing
+Multiset
+MultivariatePolynomial
+NagDiscreteFourierTransformInterfacePackage
+NagEigenInterfacePackage
+NagOptimisationInterfacePackage
+NagQuadratureInterfacePackage
+NagResultChecks
+NagSpecialFunctionsInterfacePackage
+NewSparseMultivariatePolynomial
+NewSparseUnivariatePolynomial
+None
+NonNegativeInteger
+NumericalIntegrationProblem
+NumericalODEProblem
+NumericalOptimizationProblem
+NumericalPDEProblem
+Octonion
+ODEIntensityFunctionsTable
+OneDimensionalArray
+OnePointCompletion
+OpenMathConnection
+OpenMathDevice
+OpenMathEncoding
+OpenMathError
+OpenMathErrorKind
+Operator
+OppositeMonogenicLinearOperator
+OrderedCompletion
+OrderedDirectProduct
+OrderedFreeMonoid
+OrderedVariableList
+OrderlyDifferentialPolynomial
+OrderlyDifferentialVariable
+OrdinaryDifferentialRing
+OrdinaryWeightedPolynomials
+OrdSetInts
+OutputForm
+PackedHermitianSequence
+PAdicInteger
+PAdicRational
+PAdicRationalConstructor
+Palette
+ParametricPlaneCurve
+ParametricSpaceCurve
+ParametricSurface
+PartialFraction
+Partition
+Pattern
+PatternMatchListResult
+PatternMatchResult
+PendantTree
+Permutation
+PermutationGroup
+Pi
+PlaneAlgebraicCurvePlot
+Plot
+Plot3D
+PoincareBirkhoffWittLyndonBasis
+Point
+Polynomial
+PolynomialIdeals
+PolynomialRing
+PositiveInteger
+PrimeField
+PrimitiveArray
+Product
+QuadraticForm
+QuasiAlgebraicSet
+Quaternion
+QueryEquation
+Queue
+RadicalFunctionField
+RadixExpansion
+RealClosure
+Record
+RectangularMatrix
+Reference
+RegularChain
+RegularTriangularSet
+RenderTools
+ResidueRing
+Result
+RewriteRule
+RightOpenIntervalRootCharacterization
+RomanNumeral
+RoutinesTable
+RuleCalled
+Ruleset
+ScriptFormulaFormat
+Segment
+SegmentBinding
+SequentialDifferentialPolynomial
+SequentialDifferentialVariable
+Set
+SetOfMIntegersInOneToN
+SExpression
+SExpressionOf
+SimpleAlgebraicExtension
+SimpleFortranProgram
+SingleInteger
+SingletonAsOrderedSet
+SparseMultivariatePolynomial
+SparseMultivariateTaylorSeries
+SparseTable
+SparseUnivariateLaurentSeries
+SparseUnivariatePolynomial
+SparseUnivariatePuiseuxSeries
+SparseUnivariateSkewPolynomial
+SparseUnivariateTaylorSeries
+SplitHomogeneousDirectProduct
+SplittingNode
+SplittingTree
+SquareFreeRegularTriangularSet
+SquareMatrix
+Stack
+Stream
+String
+StringTable
+SubSpace
+SubSpaceComponentProperty
+SuchThat
+Switch
+Symbol
+SymbolTable
+SymmetricPolynomial
+Table
+Tableau
+TaylorSeries
+TexFormat
+TextFile
+TheSymbolTable
+ThreeDimensionalMatrix
+ThreeDimensionalViewport
+ThreeSpace
+Timer
+Tree
+TubePlot
+Tuple
+TwoDimensionalArray
+TwoDimensionalViewport
+Union
+UnivariateLaurentSeries
+UnivariateLaurentSeriesConstructor
+UnivariatePolynomial
+UnivariatePuiseuxSeries
+UnivariatePuiseuxSeriesConstructor
+UnivariatePuiseuxSeriesWithExponentialSingularity
+UnivariateSkewPolynomial
+UnivariateTaylorSeries
+UniversalSegment
+Variable
+Vector
+Void
+WeightedPolynomials
+WuWenTsunTriangularSet
+XDistributedPolynomial
+XPBWPolynomial
+XPolynomial
+XPolynomialRing
+XRecursivePolynomial
+AlgebraicFunction
+AlgebraicHermiteIntegration
+AlgebraicIntegrate
+AlgebraicIntegration
+AlgebraicManipulations
+AlgebraicMultFact
+AlgebraPackage
+AlgFactor
+AnnaNumericalIntegrationPackage
+AnnaNumericalOptimizationPackage
+AnnaOrdinaryDifferentialEquationPackage
+AnnaPartialDifferentialEquationPackage
+AnyFunctions1
+ApplyRules
+ApplyUnivariateSkewPolynomial
+AssociatedEquations
+AttachPredicates
+BalancedFactorisation
+BasicOperatorFunctions1
+BezoutMatrix
+BoundIntegerRoots
+BrillhartTests
+CartesianTensorFunctions2
+ChangeOfVariable
+CharacteristicPolynomialInMonogenicalAlgebra
+CharacteristicPolynomialPackage
+ChineseRemainderToolsForIntegralBases
+CoerceVectorMatrixPackage
+CombinatorialFunction
+CommonDenominator
+CommonOperators
+CommuteUnivariatePolynomialCategory
+ComplexFactorization
+ComplexFunctions2
+ComplexIntegerSolveLinearPolynomialEquation
+ComplexPattern
+ComplexPatternMatch
+ComplexRootFindingPackage
+ComplexRootPackage
+ComplexTrigonometricManipulations
+ConstantLODE
+CoordinateSystems
+CRApackage
+CycleIndicators
+CyclicStreamTools
+CyclotomicPolynomialPackage
+d01AgentsPackage
+d01WeightsPackage
+d02AgentsPackage
+d03AgentsPackage
+DefiniteIntegrationTools
+DegreeReductionPackage
+DiophantineSolutionPackage
+DirectProductFunctions2
+DiscreteLogarithmPackage
+DisplayPackage
+DistinctDegreeFactorize
+DoubleFloatSpecialFunctions
+DoubleResultantPackage
+DrawComplex
+DrawNumericHack
+DrawOptionFunctions0
+DrawOptionFunctions1
+e04AgentsPackage
+EigenPackage
+ElementaryFunction
+ElementaryFunctionDefiniteIntegration
+ElementaryFunctionLODESolver
+ElementaryFunctionODESolver
+ElementaryFunctionSign
+ElementaryFunctionStructurePackage
+ElementaryIntegration
+ElementaryRischDE
+ElementaryRischDESystem
+EllipticFunctionsUnivariateTaylorSeries
+EquationFunctions2
+ErrorFunctions
+EuclideanGroebnerBasisPackage
+EvaluateCycleIndicators
+ExpertSystemContinuityPackage
+ExpertSystemContinuityPackage1
+ExpertSystemToolsPackage
+ExpertSystemToolsPackage1
+ExpertSystemToolsPackage2
+ExpressionFunctions2
+ExpressionSpaceFunctions1
+ExpressionSpaceFunctions2
+ExpressionSpaceODESolver
+ExpressionToOpenMath
+ExpressionToUnivariatePowerSeries
+ExpressionTubePlot
+FactoredFunctions
+FactoredFunctions2
+FactoredFunctionUtilities
+FactoringUtilities
+FGLMIfCanPackage
+FindOrderFinite
+FiniteDivisorFunctions2
+FiniteFieldFunctions
+FiniteFieldHomomorphisms
+FiniteFieldPolynomialPackage
+FiniteFieldPolynomialPackage2
+FiniteFieldSolveLinearPolynomialEquation
+FiniteLinearAggregateFunctions2
+FiniteLinearAggregateSort
+FiniteSetAggregateFunctions2
+FloatingComplexPackage
+FloatingRealPackage
+FortranCodePackage1
+FortranOutputStackPackage
+FortranPackage
+FractionalIdealFunctions2
+FractionFunctions2
+FramedNonAssociativeAlgebraFunctions2
+FunctionalSpecialFunction
+FunctionFieldCategoryFunctions2
+FunctionFieldIntegralBasis
+FunctionSpaceAssertions
+FunctionSpaceAttachPredicates
+FunctionSpaceComplexIntegration
+FunctionSpaceFunctions2
+FunctionSpaceIntegration
+FunctionSpacePrimitiveElement
+FunctionSpaceReduce
+FunctionSpaceSum
+FunctionSpaceToExponentialExpansion
+FunctionSpaceToUnivariatePowerSeries
+FunctionSpaceUnivariatePolynomialFactor
+GaloisGroupFactorizationUtilities
+GaloisGroupFactorizer
+GaloisGroupPolynomialUtilities
+GaloisGroupUtilities
+GaussianFactorizationPackage
+GeneralHenselPackage
+GeneralizedMultivariateFactorize
+GeneralPolynomialGcdPackage
+GenerateUnivariatePowerSeries
+GenExEuclid
+GenUFactorize
+GenusZeroIntegration
+GosperSummationMethod
+GraphicsDefaults
+GrayCode
+GroebnerFactorizationPackage
+GroebnerInternalPackage
+GroebnerPackage
+GroebnerSolve
+HallBasis
+HeuGcd
+IdealDecompositionPackage
+IncrementingMaps
+InfiniteProductCharacteristicZero
+InfiniteProductFiniteField
+InfiniteProductPrimeField
+InfiniteTupleFunctions2
+InfiniteTupleFunctions3
+Infinity
+InnerAlgFactor
+InnerCommonDenominator
+InnerMatrixLinearAlgebraFunctions
+InnerMatrixQuotientFieldFunctions
+InnerModularGcd
+InnerMultFact
+InnerNormalBasisFieldFunctions
+InnerNumericEigenPackage
+InnerNumericFloatSolvePackage
+InnerPolySign
+InnerPolySum
+InnerTrigonometricManipulations
+InputFormFunctions1
+IntegerBits
+IntegerCombinatoricFunctions
+IntegerFactorizationPackage
+IntegerLinearDependence
+IntegerNumberTheoryFunctions
+IntegerPrimesPackage
+IntegerRetractions
+IntegerRoots
+IntegerSolveLinearPolynomialEquation
+IntegralBasisPolynomialTools
+IntegralBasisTools
+IntegrationResultFunctions2
+IntegrationResultRFToFunction
+IntegrationResultToFunction
+IntegrationTools
+InternalPrintPackage
+InternalRationalUnivariateRepresentationPackage
+InverseLaplaceTransform
+IrredPolyOverFiniteField
+IrrRepSymNatPackage
+KernelFunctions2
+Kovacic
+LaplaceTransform
+LazardSetSolvingPackage
+LeadingCoefDetermination
+LexTriangularPackage
+LinearDependence
+LinearOrdinaryDifferentialOperatorFactorizer
+LinearOrdinaryDifferentialOperatorsOps
+LinearPolynomialEquationByFractions
+LinearSystemMatrixPackage
+LinearSystemMatrixPackage1
+LinearSystemPolynomialPackage
+LinGroebnerPackage
+LiouvillianFunction
+ListFunctions2
+ListFunctions3
+ListToMap
+MakeBinaryCompiledFunction
+MakeFloatCompiledFunction
+MakeFunction
+MakeRecord
+MakeUnaryCompiledFunction
+MappingPackage1
+MappingPackage2
+MappingPackage3
+MappingPackageInternalHacks1
+MappingPackageInternalHacks2
+MappingPackageInternalHacks3
+MatrixCategoryFunctions2
+MatrixCommonDenominator
+MatrixLinearAlgebraFunctions
+MergeThing
+MeshCreationRoutinesForThreeDimensions
+ModularDistinctDegreeFactorizer
+ModularHermitianRowReduction
+MonoidRingFunctions2
+MonomialExtensionTools
+MoreSystemCommands
+MPolyCatFunctions2
+MPolyCatFunctions3
+MPolyCatPolyFactorizer
+MPolyCatRationalFunctionFactorizer
+MRationalFactorize
+MultFiniteFactorize
+MultipleMap
+MultiVariableCalculusFunctions
+MultivariateFactorize
+MultivariateLifting
+MultivariateSquareFree
+NagEigenPackage
+NagFittingPackage
+NagIntegrationPackage
+NagInterpolationPackage
+NagLapack
+NagLinearEquationSolvingPackage
+NAGLinkSupportPackage
+NagMatrixOperationsPackage
+NagOptimisationPackage
+NagOrdinaryDifferentialEquationsPackage
+NagPartialDifferentialEquationsPackage
+NagPolynomialRootsPackage
+NagRootFindingPackage
+NagSeriesSummationPackage
+NagSpecialFunctionsPackage
+NewSparseUnivariatePolynomialFunctions2
+NonCommutativeOperatorDivision
+NoneFunctions1
+NonLinearFirstOrderODESolver
+NonLinearSolvePackage
+NormalizationPackage
+NormInMonogenicAlgebra
+NormRetractPackage
+NPCoef
+NumberFieldIntegralBasis
+NumberFormats
+NumberTheoreticPolynomialFunctions
+Numeric
+NumericalOrdinaryDifferentialEquations
+NumericalQuadrature
+NumericComplexEigenPackage
+NumericContinuedFraction
+NumericRealEigenPackage
+NumericTubePlot
+OctonionCategoryFunctions2
+ODEIntegration
+ODETools
+OneDimensionalArrayFunctions2
+OnePointCompletionFunctions2
+OpenMathPackage
+OpenMathServerPackage
+OperationsQuery
+OrderedCompletionFunctions2
+OrderingFunctions
+OrthogonalPolynomialFunctions
+OutputPackage
+PadeApproximantPackage
+PadeApproximants
+PAdicWildFunctionFieldIntegralBasis
+ParadoxicalCombinatorsForStreams
+ParametricLinearEquations
+ParametricPlaneCurveFunctions2
+ParametricSpaceCurveFunctions2
+ParametricSurfaceFunctions2
+PartialFractionPackage
+PartitionsAndPermutations
+PatternFunctions1
+PatternFunctions2
+PatternMatch
+PatternMatchAssertions
+PatternMatchFunctionSpace
+PatternMatchIntegerNumberSystem
+PatternMatchIntegration
+PatternMatchKernel
+PatternMatchListAggregate
+PatternMatchPolynomialCategory
+PatternMatchPushDown
+PatternMatchQuotientFieldCategory
+PatternMatchResultFunctions2
+PatternMatchSymbol
+PatternMatchTools
+Permanent
+PermutationGroupExamples
+PiCoercions
+PlotFunctions1
+PlotTools
+PointFunctions2
+PointPackage
+PointsOfFiniteOrder
+PointsOfFiniteOrderRational
+PointsOfFiniteOrderTools
+PolToPol
+PolyGroebner
+PolynomialAN2Expression
+PolynomialCategoryLifting
+PolynomialCategoryQuotientFunctions
+PolynomialComposition
+PolynomialDecomposition
+PolynomialFactorizationByRecursion
+PolynomialFactorizationByRecursionUnivariate
+PolynomialFunctions2
+PolynomialGcdPackage
+PolynomialInterpolation
+PolynomialInterpolationAlgorithms
+PolynomialNumberTheoryFunctions
+PolynomialRoots
+PolynomialSetUtilitiesPackage
+PolynomialSolveByFormulas
+PolynomialSquareFree
+PolynomialToUnivariatePolynomial
+PowerSeriesLimitPackage
+PrecomputedAssociatedEquations
+PrimitiveArrayFunctions2
+PrimitiveElement
+PrimitiveRatDE
+PrimitiveRatRicDE
+PrintPackage
+PseudoLinearNormalForm
+PseudoRemainderSequence
+PureAlgebraicIntegration
+PureAlgebraicLODE
+PushVariables
+QuasiAlgebraicSet2
+QuasiComponentPackage
+QuaternionCategoryFunctions2
+QuotientFieldCategoryFunctions2
+RadicalEigenPackage
+RadicalSolvePackage
+RadixUtilities
+RandomDistributions
+RandomFloatDistributions
+RandomIntegerDistributions
+RandomNumberSource
+RationalFactorize
+RationalFunction
+RationalFunctionDefiniteIntegration
+RationalFunctionFactor
+RationalFunctionFactorizer
+RationalFunctionIntegration
+RationalFunctionLimitPackage
+RationalFunctionSign
+RationalFunctionSum
+RationalIntegration
+RationalLODE
+RationalRetractions
+RationalRicDE
+RationalUnivariateRepresentationPackage
+RealPolynomialUtilitiesPackage
+RealSolvePackage
+RealZeroPackage
+RealZeroPackageQ
+RectangularMatrixCategoryFunctions2
+ReducedDivisor
+ReduceLODE
+ReductionOfOrder
+RegularSetDecompositionPackage
+RegularTriangularSetGcdPackage
+RepeatedDoubling
+RepeatedSquaring
+RepresentationPackage1
+RepresentationPackage2
+ResolveLatticeCompletion
+RetractSolvePackage
+SAERationalFunctionAlgFactor
+ScriptFormulaFormat1
+SegmentBindingFunctions2
+SegmentFunctions2
+SimpleAlgebraicExtensionAlgFactor
+SimplifyAlgebraicNumberConvertPackage
+SmithNormalForm
+SortedCache
+SortPackage
+SparseUnivariatePolynomialFunctions2
+SpecialOutputPackage
+SquareFreeQuasiComponentPackage
+SquareFreeRegularSetDecompositionPackage
+SquareFreeRegularTriangularSetGcdPackage
+StorageEfficientMatrixOperations
+StreamFunctions1
+StreamFunctions2
+StreamFunctions3
+StreamInfiniteProduct
+StreamTaylorSeriesOperations
+StreamTranscendentalFunctions
+StreamTranscendentalFunctionsNonCommutative
+StructuralConstantsPackage
+SturmHabichtPackage
+SubResultantPackage
+SupFractionFactorizer
+SymmetricFunctions
+SymmetricGroupCombinatoricFunctions
+SystemODESolver
+SystemSolvePackage
+TableauxBumpers
+TabulatedComputationPackage
+TangentExpansions
+TemplateUtilities
+TexFormat1
+ToolsForSign
+TopLevelDrawFunctions
+TopLevelDrawFunctionsForAlgebraicCurves
+TopLevelDrawFunctionsForCompiledFunctions
+TopLevelDrawFunctionsForPoints
+TopLevelThreeSpace
+TranscendentalHermiteIntegration
+TranscendentalIntegration
+TranscendentalManipulations
+TranscendentalRischDE
+TranscendentalRischDESystem
+TransSolvePackage
+TransSolvePackageService
+TriangularMatrixOperations
+TrigonometricManipulations
+TubePlotTools
+TwoDimensionalPlotClipping
+TwoFactorize
+UnivariateFactorize
+UnivariateLaurentSeriesFunctions2
+UnivariatePolynomialCategoryFunctions2
+UnivariatePolynomialCommonDenominator
+UnivariatePolynomialDecompositionPackage
+UnivariatePolynomialDivisionPackage
+UnivariatePolynomialFunctions2
+UnivariatePolynomialMultiplicationPackage
+UnivariatePolynomialSquareFree
+UnivariatePuiseuxSeriesFunctions2
+UnivariateSkewPolynomialCategoryOps
+UnivariateTaylorSeriesFunctions2
+UnivariateTaylorSeriesODESolver
+UniversalSegmentFunctions2
+UserDefinedPartialOrdering
+UserDefinedVariableOrdering
+UTSodetools
+VectorFunctions2
+ViewDefaultsPackage
+ViewportPackage
+WeierstrassPreparation
+WildFunctionFieldIntegralBasis
+XExponentialPackage
+ZeroDimensionalSolvePackage
+@
+\begin{thebibliography}{99}
+\bibitem{1} Jenks, R.J. and Sutor, R.S. 
+``Axiom -- The Scientific Computation System''
+Springer-Verlag New York (1992)
+ISBN 0-387-97855-0
+\bibitem{2} Knuth, Donald E., ``Literate Programming''
+Center for the Study of Language and Information
+ISBN 0-937073-81-4
+Stanford CA (1992) 
+\bibitem{3} Page, William, ``The Axiom Wiki Website''\\
+{\bf http://wiki.axiom-developer.org}
+\bibitem{4} Watt, Stephen, ``Aldor'',\\
+{\bf http://www.aldor.org}
+\bibitem{5} Lamport, Leslie, ``Latex -- A Document Preparation System'',
+Addison-Wesley, New York ISBN 0-201-52983-1
+\bibitem{6} Ramsey, Norman ``Noweb -- A Simple, Extensible Tool for
+Literate Programming''\\
+{\bf http://www.eecs.harvard.edu/ $\tilde{}$nr/noweb}
+\end{thebibliography}
+\printindex
+\end{document}
diff --git a/src/sman/nagman.c.pamphlet b/src/sman/nagman.c.pamphlet
deleted file mode 100644
index 8864c74..0000000
--- a/src/sman/nagman.c.pamphlet
+++ /dev/null
@@ -1,604 +0,0 @@
-\documentclass{article}
-\usepackage{axiom}
-\begin{document}
-\title{\$SPAD/src/sman nagman.c}
-\author{The Axiom Team}
-\maketitle
-\begin{abstract}
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-\section{nag.x}
-<<nag.x>>=
-
-/*
- * msg.x: Remote message printing protocol
- */
-const MAXASP = 10;
-
-/*
- * the nago structure is essentially a variable length string
- */
-
-struct nago {
-  opaque z <>;
-  };
-struct nagerr {
-nago p;
-nago q;
-};
-
-struct host{
-nago h <>;
-};
-
-struct nagst {
-
-/* Okay, if you understand this bit you know the essentials of how the link
- * works. h <> is an array of nago, which is an array of fortran source 
- * code, the length of the array being the no. of asps (0 for most routines).
- * y is the actual (XDR) input data for the routine. nm is the name of the
- * routine. id is a tag identifying the host/axiom session. Finally per is a
- * number telling whether or not to erase old fortran files on the remote
- * machine (persistence - the number per distinct fortran files will be 
- * stored, any more than this and earlier ones will be deleted.
- */
-
-  nago h <>;
-  nago y;
-  nago nm;
-  nago id;
-  int per;
-  };
-program NAGPROG {
-   version NAGVERS {
-       nagerr CALLNAG(nagst) = 1;
-       nago NAGMON(int)=2;
-       void AXEND(nago)=3;
-   } = 1;
-/*
- * the following number is very important. It tells the 
- * portmapper what number to register the nag daemon under.
- * There are rules about which number to pick - check SUN
- * technical info for more details
- */
-} = 100088;
-
-
-@
-\section{nagman}
-\subsection{includes}
-<<includes>>=
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h> 
-#include <string.h>
-#include <errno.h>
-#include <termios.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <rpc/rpc.h>     /* always needed */ 
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include "nag.h"  /* generated by rpcgen */
-#include "com.h"
-#include "bsdsignal.h"
-#include "sockio-c.h1"
-#include "bsdsignal.h1"
-#include "nagman.h1"
-
-@
-\subsection{variables}
-<<variables>>=
-#ifdef ALPHAplatform
-extern int getdomainname( char *, int );
-#endif
-#ifdef SUN4OS5platform
-extern int getdomainname( char *, int );
-extern int gethostname( char *, int );
-#endif
-
-nagerr * callnag_1(nagst *,CLIENT *);
-nago * nagmon_1(int *,CLIENT *);
-void * axend_1(nago *,CLIENT *);
-
-#define DO 1
-#define DONT 0
-
-int hnum, vmax;
-char *datafile, *resultsfile;
-
-struct hostnode {
-  char * name;
-  struct hostnode *next; 
-} *hlist=NULL;
-
-nagst nag4;
-Sock *sock1;
-
-@
-\subsection{term}
-this code runs when the user quits axiom. before nagman dies, it does
-an rpc call to nagd to tell it to get rid of files etc. The rpc call in
-question is [[axend_1]]
-we also send a USR1 to sman to beget another nagman
-<<term>>=
-static void 
-term(int sig)
-{
-  CLIENT *cld;
-  void *res;
-  struct hostnode *pnode;
-
-#ifndef HP9platform /* can't figure out a way to do this on HP/UX 9 */
-  kill(atoi(getenv("SPADNUM")) , SIGUSR1);
-#endif
-
-
-  if(hnum!=0)
-    {
-      unlink(datafile);
-      unlink(resultsfile);
-    }
-
-  for(pnode=hlist;pnode!=NULL;pnode=pnode->next)
-    {
-      cld=clnt_create(pnode->name,NAGPROG, NAGVERS, "tcp");
-      if (cld == NULL)
-	goto NOHOST;
-
-      res=axend_1(&(nag4.id),cld);
-    NOHOST:
-      clnt_destroy(cld);
-    }
-  exit(0);
-}
-
-@
-\subsection{size\_of\_file}
-<<sizeoffile>>=
-static long 
-size_of_file(char *filename)
-{
-  struct stat buf_stat;
-
-  stat(filename,&buf_stat);
-  return (buf_stat.st_size);
-
-}
-
-@
-\subsection{rpcloop}
-<<rpcloop>>=
-static void 
-rpcloop(void)
-{
-  CLIENT *cl;
-  int res,j,v=0,u,showMessage;
-  long i;
-  register struct hostent *alias1, *alias2;
-  struct in_addr *addrnum;
-  u_long junk;
-  struct timeval tv;
-  nagerr *result;
-  char *Buf , *buf1;
-  char *ffile[MAXASP];
-  char routine[12], naghost[256];
-  FILE *nfp1, *nfp2, *nfp3;
-  struct hostnode *phost;
-  int fd;
-  
-  for (;;)
-    {
-      
-      if((Buf=get_string(sock1))==NULL) term(1); /* one string carries all */
-      
-      if(hnum!=0)
-	{
-	  /* call parameters */
-	  free(nag4.nm.z.z_val); /* the routine name */
-	  free(nag4.y.z.z_val);  /* the XDR data */
-	  for(i=0;i<v;i++)
-	    {
-	      unlink(ffile[i]);
-	      free(ffile[i]); /* the asp filenames */
-	      free(nag4.h.h_val[i].z.z_val); /* the asps themselves*/
-	    }
-	  free(nag4.h.h_val); /* the asps array */
-	  unlink(datafile);
-	  unlink(resultsfile);
-	  free(resultsfile);
-	  free(datafile);
-	  vmax= (v>vmax)? v : vmax;
-	}
-      
-      
-      
-      
-      buf1=strtok(Buf," ");
-      if (buf1) strcpy(naghost,buf1);
-      else printf("can't parse the naghost\n");
-      /* INFO         printf("%s\n",naghost);*/
-      
-      buf1=strtok(NULL," ");
-      if (buf1) strcpy(routine,buf1);
-      else printf("can't parse the routine\n");
-      /* INFO         printf("%s\n",routine);*/
-      
-      /* make copy of filenames because we will reuse Buf before deleting the files*/
-      buf1=strtok(NULL," ");
-      if (buf1) resultsfile=strdup(buf1);
-      else printf("can't parse the resultsfile file\n");	
-      /* INFO         printf("%s\n",resultsfile);*/
-      
-      buf1=strtok(NULL," ");  
-      if (buf1) datafile=strdup(buf1); 
-      else printf("can't parse the datafile file\n");  
-      /* INFO         printf("%s\n",datafile);*/
-      
-      buf1=strtok(NULL," ");
-      if (buf1) nag4.per=atoi(buf1);
-      else printf("can't parse the persistence\n");
-      /* INFO         printf("%d\n",nag4.per);*/
-      
-      buf1=strtok(NULL," ");
-      if (buf1) {
-	if (!strcmp(buf1,"on")) showMessage=DO;
-	else showMessage=DONT;
-      }
-      else printf("can't parse the messages flag\n");
-      /* INFO         printf("%s\n",buf1);*/
-      
-      v=0; /* asp counter */
-      while( (buf1=strtok(NULL," ")) )
-	{
-	  ffile[v++]=strdup(buf1);
-	  /* INFO 	      	printf("%s\n",ffile[v-1]);*/
-	}
-      
-      /* INFO  	printf("number of asps seen %d\n",v);*/
-      
-      if(showMessage==DO) printf("nagman:acknowledging request for %s\n",routine);
-      
-      res=0;  /* prepare result integer to be sent to Lisp */
-      
-      if((nfp3=fopen(resultsfile,"w"))==NULL)
-	{
-	  printf("can't open output file\n");
-	  goto END;
-	}
-      
-      /* nag4.h is the XDR array of asp text */
-      nag4.h.h_len=v;
-      nag4.h.h_val=(nago *)malloc((v)*sizeof(nago));
-      
-      
-      /* get asp text in call argument */
-      for(u=0;u<v;u++)
-	{
-	  /* this should be done by mmap */
-	  if((nfp1=fopen(ffile[u],"r"))==NULL)
-	    {
-	      fprintf(stderr,"can't open asp file %s\n",ffile[u]);
-	      fclose(nfp1);
-	      goto END;
-	    }
-	  fclose(nfp1);
-	  i=size_of_file(ffile[u]);
-
-	  /* allocs memory for the file */
-	  nag4.h.h_val[u].z.z_val= (char *)malloc((i+1)*sizeof(char)); 
-	  
-	  fd=open(ffile[u],O_RDONLY);
-	  read(fd,nag4.h.h_val[u].z.z_val,i);
-	  close(fd);
-	  /* make null-term. string */
-	  nag4.h.h_val[u].z.z_val[i]='\0'; 
-	  /* set the length */
-	  nag4.h.h_val[u].z.z_len=strlen(nag4.h.h_val[u].z.z_val); 
-	}
-      
-      
-      nag4.nm.z.z_val=strdup(routine);
-      nag4.nm.z.z_len=strlen(routine);
-      
-      /* get XDR data in call argument */
-      /* should be done by mmap */
-      if((nfp2=fopen(datafile,"r"))==NULL)
-	{
-	  fprintf(stderr,"can't open data file\n");
-	  fclose(nfp2);
-	  goto END;
-	}
-      
-      fclose(nfp2);
-      i=size_of_file(datafile);
-      nag4.y.z.z_val=(char *)malloc(i*sizeof(char));
-      
-      fd=open(datafile,O_RDONLY);
-      read(fd,nag4.y.z.z_val,i);
-      close(fd);
-      nag4.y.z.z_len=i;
-      
-      
-      /*
-       * Create client "handle" used for calling MESSAGEPROG on
-       * the server designated on the command line.  We tell
-       * the RPC package to use the "tcp" protocol when
-       * contacting the server.
-       */
-      
-      /* update naghost by lookup */
-      
-      if ((junk = inet_addr(naghost))!=-1)
-	{
-	  addrnum=(struct in_addr *)junk;
-	  if((alias2=gethostbyaddr((char *)&addrnum,
-				   sizeof(addrnum),
-				   AF_INET))!=NULL)
-	    strcpy(naghost,alias2->h_name);
-	  else
-	    if((alias1=gethostbyname(naghost))!=NULL)
-	      strcpy(naghost,alias1->h_name);
-	}
-      else
-	if((alias1=gethostbyname(naghost))!=NULL)
-	  strcpy(naghost,alias1->h_name);
-      
-      
-      
-      
-      cl = clnt_create(naghost, NAGPROG, NAGVERS, "tcp");
-      if (cl == NULL)
-	{
-	  /*
-	   * Couldn't establish connection with server.
-	   * Print error message and die.
-	   */
-	  clnt_pcreateerror(naghost);
-	  goto END;
-	}
-      else
-	if (showMessage==DO)
-	  printf("nagman:connection successful to %s\n",naghost);
-      
-      /*
-       * this number here sets the "timeout" for the rpc call. after this number
-       * of seconds, the call will quit if no response is received
-       *
-       */
-      
-      tv.tv_sec=1000000;
-      tv.tv_usec=0;
-      clnt_control(cl,CLSET_TIMEOUT,(char *)&tv);
-      
-      
-      result = callnag_1(&nag4, cl);
-      
-      for(phost=hlist;phost!=NULL;phost=phost->next)
-	{
-	  /*
-	   * hlist is the "hostlist" of sites that have been contacted by nagman.
-	   * here we check if this call is contacting a new site, and if so add it
-	   * to the hostlist
-	   *
-	   */
-	  
-	  if(!strcmp(phost->name,naghost))
-	    goto SKIP;
-	}
-      
-      if(hnum==0) {
-	hlist=(struct hostnode *)malloc(sizeof(struct hostnode));
-	hlist->name=strdup(naghost);
-	hlist->next=NULL;
-      }
-      
-      else {
-	phost=(struct hostnode *)malloc(sizeof(struct hostnode));
-	phost->name=strdup(naghost);
-	phost->next=hlist;
-	hlist=phost;
-      }
-      hnum++;
-      
-      
-    SKIP:
-      if (result == NULL)
-	{
-	  /*
-	   * An error occurred while calling the server.
-	   * Print error message and die.
-	   */
-	  if (showMessage==DO)
-	    printf("nagman:no results (error) from %s\n",naghost);
-	  clnt_perror(cl,naghost);
-	  clnt_destroy(cl);
-	  goto END;
-	}
-      
-      /*
-       * (*result).p is the part of the result with the XDRed results in it 
-       * (numbers). (*result).q is the part with (text) error messages that 
-       * have come from the NAG library. If there is neither an XDR result,
-       * nor a text error message from the library, then something is wrong
-       * so we just print out the "no result or error returned" message.
-       *
-       */
-      
-      else if ((*result).p.z.z_len==0)
-	{
-	  if((*result).q.z.z_len==0)
-	    {
-	      if (showMessage==DO)
-		printf("nagman:empty result (error) from %s\n",naghost);
-	      clnt_destroy(cl);
-	      goto END;
-	    }
-	  else
-	    {
-	      if (showMessage==DO)
-		printf("nagman:receiving results from %s\n\n",naghost);
-	      for(j=0;j<(*result).q.z.z_len;j++)
-		printf("%c",(*result).q.z.z_val[j]);
-	      clnt_destroy(cl);
-	      goto END;
-	    }
-	}
-      else
-	if (showMessage==DO)
-	  printf("nagman:receiving results from %s\n\n",naghost);
-      
-      if (showMessage==DO)
-	fwrite(result->q.z.z_val,sizeof(char),result->q.z.z_len,stdout);
-      
-      /*INFO		printf("\nRESULTS of length %d\n",(*result).p.z.z_len);*/
-      
-      fwrite(result->p.z.z_val,sizeof(char),result->p.z.z_len, nfp3);
-      res=1;
-      clnt_destroy(cl);
-      
-      /*
-       * in case of any type of error, a goto END in the above code causes
-       * nagman to skip here and return to AXIOM
-       *
-       */
-      
-      
-    END:
-      fclose(nfp3);
-      /*
-       * if everything has gone alright, send_int returns the integer res=1. If
-       * not it returns res=0. This is detected by the boot code which acts 
-       * accordingly.
-       */
-      send_int(sock1,res);
-      free(Buf);
-    }
-  
-  
-}
-
-@
-\subsection{catchSignals}
-catchSignals sets up signal handling. If nagman gets a sigterm it does not
-die but goes back to rpcloop
-<<catchSignals>>=
-static void 
-catchSignals(void)
-{
-  bsdSignal(SIGTERM,term,RestartSystemCalls);
-  bsdSignal(SIGSEGV,term,RestartSystemCalls);
-}
-
-@
-\subsection{main}
-<<main>>=
-void 
-main(int argc,char **argv)
-{
-  char this[256],*hname,*dname,*spadnum;
-  int stat;
- 
-  catchSignals();
-  stat=gethostname(this,256);
-  if (stat!=0) perror("gethostname");
-  hname=strdup(this);
-
-  stat=getdomainname(this,256);
-  if (stat!=0) perror("getdomainname");
-  dname=strdup(this);
-  spadnum=getenv("SPADNUM");
-  if (spadnum==0) {
-    fprintf(stderr,"nagman error: SPADNUM is not in the environment\n");
-    exit(0);
-  }
-
-  /* some machines return a full name from hostname 
-     need to check hname has a . in it */
-
-  if  (strchr(hname,'.'))
-    /* '.' found */
-    sprintf(this,"%s_%i",hname,atoi(spadnum));
-  else
-    /* substring not found */
-    sprintf(this,"%s.%s_%i",hname,dname,atoi(spadnum));
-
-  /* this must contain the Internet address of the current host */
-  nag4.id.z.z_val=strdup(this);
-  nag4.id.z.z_len=strlen(nag4.id.z.z_val);
-  hnum=0;
-  vmax=0;
-  /*
-   * this line sets up a socket for communication with the lisp
-   */
-
-  sock1 = connect_to_local_server(SpadServer, DebugWindow, 120 /*seconds*/);
-  if (!sock1) exit(0);
-
-  rpcloop();
-}
-
-@
-\subsection{nagman}
-<<nagman>>=
-#define _NAGMAN_C
-<<includes>>
-<<variables>>
-<<term>>
-<<sizeoffile>>
-<<rpcloop>>
-<<catchSignals>>
-<<main>>
-@
-\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.
-*/
-
-@
-<<*>>=
-<<license>>
-<<nagman>>
-@ 
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} nothing
-\end{thebibliography}
-\end{document}
diff --git a/src/sman/session.c.pamphlet b/src/sman/session.c.pamphlet
deleted file mode 100644
index 5f5d9c9..0000000
--- a/src/sman/session.c.pamphlet
+++ /dev/null
@@ -1,612 +0,0 @@
-\documentclass{article}
-\usepackage{axiom}
-\begin{document}
-\title{\$SPAD/src/sman session.c}
-\author{The Axiom Team}
-\maketitle
-\begin{abstract}
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-\section{session}
-\subsection{includes}
-<<includes>>=
-#include <stdlib.h>
-#include <sys/time.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#ifdef SGIplatform
-#include <bstring.h>
-#endif
-#include "com.h"
-#include "bsdsignal.h"
-#include "sockio-c.h1"
-#include "bsdsignal.h1"
-#include "session.h1"
-
-@
-\subsection{variables}
-<<variables>>=
-#define BufSize		4096	/* size of communication buffer */
-
-typedef struct sock_list {      /* linked list of Sock */
-  Sock Socket;
-  struct sock_list *next;
-} Sock_List;
-
-Sock *spad_io = (Sock *) 0;	   /* to_server socket for SessionIO */
-Sock *spad_server = (Sock *) 0;    /* to_server socket for SpadServer    */
-Sock *menu_client = (Sock *) 0;	   /* to_client socket for MenuServerName  */
-Sock *active_session = (Sock *) 0; /* pointer to currently active session */
-
-Sock_List *plSock = (Sock_List *) 0;
-
-char big_bad_buf[BufSize];	/* big I/O buffer */
-int num_active_clients = 0;	/* number of InterpWindows attached */
-int reading_output = 0;
-fd_set session_socket_mask;
-
-@
-\subsection{usr1\_handler}
-<<usr1handler>>=
-static void 
-usr1_handler(int sig)
-{
-  return;
-}
-
-@
-\subsection{usr2\_handler}
-SIGUSR2 is generated by spadclients.
-We interpret it as an interrupt for the Lisp.
-<<usr2handler>>=
-static void 
-usr2_handler(int sig)
-{
-  send_signal(spad_server, SIGINT);
-  return;
-}
-
-@
-\subsection{term\_handler}
-<<termhandler>>=
-static void 
-term_handler(int sig)
-{
-  exit(1);
-}
-
-@
-\subsection{pr}
-<<pr>>=
-static void
-pr()
-{
-  Sock_List *pSock;
-  
-  fprintf(stderr,"The socket list:\n");
-  for(pSock=plSock;pSock!=(Sock_List *)0;pSock=pSock->next){
-    fprintf(stderr,"(%d,%d,%d)\t",
-      pSock->Socket.pid, 2<<(pSock->Socket.socket), pSock->Socket.frame);
-  }
-  fprintf(stderr,"\n");
-}
-
-@
-\subsection{close\_client}
-<<closeclient>>=
-static void
-close_client(int frame)
-{
-  Sock_List *pSock,*locSock;
-  int socket_fd;
-  
-  /* we will check for frame equality,
-     kill with send_signal,
-     notify HyperTex so that it updates its list (if it's a spadbuf),
-     repair the list,
-     unset the active_session,
-     update num_active_clients
-     */
-  
-  
-  /* first check head */
-#ifdef DEBUG
-fprintf(stderr,"close_client(%d)\n",frame);
-#endif
-  
-  if ( (plSock) && (plSock->Socket.frame == frame) ){
-    socket_fd = plSock->Socket.socket;
-    send_signal((Sock *)plSock, SIGTERM);
-    if ( menu_client != (Sock *) 0){
-      send_int(menu_client,CloseClient);
-      send_int(menu_client,(*plSock).Socket.pid);
-    } 
-#ifdef DEBUG
-fprintf(stderr,"trying to clear %u\n",socket_fd);
-#endif
-    FD_CLR(socket_fd,&session_socket_mask);
-    locSock = plSock;
-    if ((*plSock).next == (Sock_List *) 0) 
-      {plSock = (Sock_List *) 0;}
-    else
-      {plSock = plSock->next;}
-    active_session = (Sock *) 0;
-    num_active_clients--;
-    free(locSock);
-  }
-  
-  /* now check the rest */
-  
-  else {
-    for (pSock=plSock; pSock->next != (Sock_List *) 0 ; pSock=pSock->next)
-      if (pSock->next->Socket.frame == frame){
-	socket_fd = pSock->next->Socket.socket;
-	send_signal((Sock *)pSock->next, SIGTERM);
-	if ( menu_client != (Sock *) 0){
-	  send_int(menu_client,CloseClient);
-	  send_int(menu_client,(*plSock).Socket.pid);
-	}
-#ifdef DEBUG
-fprintf(stderr,"trying to clear %u\n",socket_fd);
-#endif
-	FD_CLR(socket_fd,&session_socket_mask);
-	locSock = pSock->next;
-	if (  pSock->next->next == (Sock_List *) 0  )
-	  { pSock->next= (Sock_List *) 0;}
-	else
-	  { pSock->next = pSock->next->next;}
-	num_active_clients--;
-	active_session = (Sock *) 0;
-	free(locSock);
-	break;
-      }
-  }
-#ifdef DEBUG
-pr();
-#endif
-}
-
-@
-\subsection{read\_SpadServer\_command}
-<<readSpadServercommand>>=
-static void 
-read_SpadServer_command(void)
-{
-  int cmd, frame, num;
-  cmd  = get_int(spad_server);
-  switch (cmd) {
-  case EndOfOutput:
-    if (menu_client != (Sock *) 0) send_signal(menu_client, SIGUSR2); 
-    if (reading_output != 0) reading_output = 0;
-    break;
-  case QueryClients:
-    /*  don't count MenuServer */
-    num =  num_active_clients ;
-    send_int(spad_server, num);
-    break;
-  case CloseClient:
-    frame = get_int(spad_server);
-    if (frame != -1) close_client(frame); 
-    break;
-  case SendXEventToHyperTeX:
-    break;
-  default:
-    fprintf(stderr, "session : unknown command from SpadServer %d\n", cmd);
-    break;
-  }
-}
-
-@
-\subsection{test\_sock\_for\_process}
-<<testsockforprocess>>=
-static int
-test_sock_for_process(Sock *sock)
-{
-  if (sock == (Sock *)0 ) return -1;
-  return kill(sock->pid, 0);
-}
-
-@
-\subsection{read\_menu\_client\_command}
-<<readmenuclientcommand>>=
-static void
-read_menu_client_command(void)
-{
-  int cmd,frame, i,socket_fd;
-  Sock_List *pSock;
-  
-  /* save it for possible clearing */
-  socket_fd =  menu_client->socket;
-
-  if (test_sock_for_process(menu_client) == -1) {
-    FD_CLR(socket_fd,&session_socket_mask);
-    menu_client = (Sock *) 0; 
-    reading_output = 0;
-    return;
-  }
-  cmd = get_int(menu_client);
-  switch(cmd) {
-  case -1:		/* socket closed */
-    FD_CLR(socket_fd,&session_socket_mask);
-    menu_client = (Sock *) 0;
-    reading_output = 0;
-    break;
-  case SwitchFrames:
-#ifdef DEBUG
-fprintf(stderr,"menu:SwitchFrames\n");
-#endif
-    frame = get_int(menu_client);
-    send_int(spad_server, SwitchFrames);
-    send_int(spad_server, frame);
-    for(i=0,pSock=plSock; pSock != (Sock_List *) 0 ; i++,pSock=pSock->next)
-      if ((pSock->Socket.frame == frame)) {
-	active_session = (Sock *)pSock;
-	reading_output = 1;
-	break;
-      }
-    if (i == num_active_clients) {
-      /* fprintf(stderr, "Couldn't find socket for frame %d\n", frame); */
-    }
-    break;
-  case QuerySpad:
-#ifdef DEBUG
-fprintf(stderr,"menu:QuerySpad\n");
-#endif
-    send_int(menu_client, reading_output);
-    break;
-  default:
-    fprintf(stderr, "session : unknown command from MenuServer: %d\n", cmd);
-    menu_client = (Sock *) 0;
-    break;
-  }
-}
-
-@
-\subsection{read\_from\_spad\_io}
-<<readfromspadio>>=
-static void
-read_from_spad_io(void)
-{
-  int ret_code;
-  ret_code = sread(spad_io, big_bad_buf, BufSize, "session: stdout socket");
-  if (ret_code == -1) return;
-  if(active_session != (Sock *) 0) {
-    ret_code = swrite(active_session, big_bad_buf, ret_code,
-		      NULL);
-  }
-}
-
-@
-\subsection{kill\_spad}
-<<killspad>>=
-static void
-kill_spad(void)
-{
-  int i;
-  Sock_List *pSock;
-  
-  send_signal(spad_server, SIGTERM);
-  for  (pSock=plSock,i=0;
-	(i<num_active_clients) && (pSock != (Sock_List *) 0); 
-	i++,pSock=pSock->next) {
-    if ((pSock->Socket).socket != 0)
-      send_signal((Sock *)pSock, SIGTERM);
-  }
-  if (menu_client != (Sock *) 0) send_signal(menu_client, SIGTERM);
-  exit(0);
-}
-
-@
-\subsection{accept\_session\_connection}
-<<acceptsessionconnection>>=
-static int
-accept_session_connection(Sock *server_sock)
-{
-  int sock_fd, ret_code;
-  Sock_List *pls;
-  
-  /* Could be three things : KillSpad MenuServer InterpWindow  */
-  
-  pls = (Sock_List *) malloc(sizeof (Sock_List));
-  sock_fd = accept(server_sock->socket, 0, 0);
-  if (sock_fd == -1) {
-    perror("session : accepting connection");
-    return -1;
-  }
-  (pls->Socket).socket = sock_fd;
-    get_socket_type((Sock *)pls);
-    
-    switch((pls->Socket).purpose) {
-    case KillSpad:
-      kill_spad();
-      return KillSpad;
-      free(pls);
-    case MenuServer:
-#ifdef DEBUG
-      fprintf(stderr,"session: accepted MenuServer , fd = %d\n",sock_fd);
-#endif
-      menu_client = &(pls->Socket);
-      FD_SET(menu_client->socket, &session_socket_mask);
-      return MenuServer;
-    case InterpWindow:
-#ifdef DEBUG
-      fprintf(stderr,"session: accepted InterpWindow , fd = %d\n",sock_fd);
-#endif
-      
-      /* new Sock is put at the head of the list */
-      if (plSock == (Sock_List *)0 ) {
-	plSock = pls;
-	plSock->next = (Sock_List *)0 ;
-      }
-      else{
-	pls->next = plSock;
-	plSock = pls;
-      }
-      
-      /* we need to maintain session_socket_mask here 
-         since we roll our own accept */
-      
-      FD_SET(plSock->Socket.socket, &session_socket_mask);
-      send_int(spad_server, CreateFrame);
-      {
-          int command = get_int(spad_server);
-          /* XXX hack -- the whole protocol looks broken, we just
-          try to detect losage */
-          if (command != CreateFrameAnswer) {
-              fprintf(stderr, "session: non-fatal, got out of sync "
-                               "with Spad server\n  (lost race)\n");
-          /*    exit(1); */
-          }
-      }
-      plSock->Socket.frame = get_int(spad_server);
-      active_session = (Sock *)plSock;
-      get_string_buf(spad_server, big_bad_buf, BufSize);
-      ret_code = swrite((Sock *)plSock, big_bad_buf, strlen(big_bad_buf)+1,
-			"session: writing to InterpWindow");
-      if (ret_code == -1) 
-	return -1;
-      num_active_clients++;
-#ifdef DEBUG
-pr();
-#endif
-      return plSock->Socket.purpose;
-    }
-    return (-1);
-}
-
-@
-\subsection{read\_from\_session}
-<<readfromsession>>=
-static void
-read_from_session(Sock *sock)
-{
-  int ret_code;
-  if (sock != active_session) {
-    send_int(spad_server, SwitchFrames);
-    send_int(spad_server, sock->frame);
-  }
-  active_session = sock;
-  ret_code = sread(sock, big_bad_buf, BufSize, 
-		   "session: reading InterpWindow");
-  if (ret_code == -1) {
-    active_session = (Sock *) 0;
-    reading_output = 0;
-    return;
-  }
-  ret_code = swrite(spad_io, big_bad_buf, ret_code,
-		    "session: writing SessionIO");
-  if (ret_code == -1) {
-    active_session = (Sock *)0 ;
-    reading_output = 0;
-    return;
-  }
-  reading_output = 1;
-}
-
-@
-\subsection{manage\_sessions}
-<<managesessions>>=
-static void
-manage_sessions(void)
-{
-  int ret_code;
-  fd_set rd, wr, ex;
-  Sock_List  *pSock;
-  
-  reading_output = 0;
-  while (1) {
-    FD_ZERO(&rd);
-    FD_ZERO(&wr);
-    FD_ZERO(&ex);
-
-    /* Allow server socket and all connections if not waiting for output
-       socket_mask is maintained by libspad.a  */
-#ifdef DEBUG
-fprintf(stderr,"session_socket_mask=%u ",*((long *)session_socket_mask.fds_bits));
-#endif
-    rd = session_socket_mask;
-    if (!reading_output) {
-      rd = session_socket_mask;
-    }
-
-    /* Allow the active_session if set */
-    if (active_session) FD_SET(active_session->socket, &rd);
-#ifdef DEBUG
-fprintf(stderr,"[rd=%u ",*((long *)rd.fds_bits));
-#endif
-
-    ret_code = sselect(FD_SETSIZE, &rd, &wr, &ex, NULL);
-    if (ret_code == -1) {
-	break;
-    }
-#ifdef DEBUG
-fprintf(stderr,"rd=%u]\n",*((long *)rd.fds_bits));
-#endif
-    
-    if ((menu_client != (Sock *) 0)  && FD_ISSET(menu_client->socket, &rd)) {
-      /* MenuServer wants to talk */
-      read_menu_client_command(); }
-    
-    
-    if (FD_ISSET(spad_io->socket, &rd)) {
-      /* Lisp has output */
-      read_from_spad_io(); }
-    
-    
-    if (FD_ISSET(server[1].socket, &rd)) {
-      /* Someone wants to connect to our server socket */
-      accept_session_connection(server+1); }
-    
-    
-    for(pSock=plSock; pSock != (Sock_List *) 0 ; pSock=pSock->next) {
-      if ((active_session == (Sock *)pSock || !reading_output) &&
-	  (pSock->Socket).socket>0 && FD_ISSET(pSock->Socket.socket, &rd)) {
-	/* An InterpWindow */
-	read_from_session((Sock *)pSock); }
-    }
-    
-    
-    if (FD_ISSET(spad_server->socket, &rd)) {
-      /* The Lisp socket */
-      read_SpadServer_command(); }
-  }
-}
-
-@
-\subsection{main}
-<<main>>=
-int
-main(void)
-{
-
-#ifdef DEBUG2
-  /* delay for attaching with debugger before interesting things happen */
-  sleep(30);
-#endif
-
- /* spad_server connects to Lisp server socket         
-    read_SpadServer_command handles requests */
-  spad_server = connect_to_local_server(SpadServer, SessionManager, Forever);
-  if (spad_server == (Sock *) 0) {
-    fprintf(stderr, "session: Cannot connect to AXIOM server!\n");
-    exit(0);
-  }
-  else {
-#ifdef DEBUG
-    fprintf(stderr, "session: connected SpadServer , fd = %d\n",
-	    spad_server->socket);
-#endif  
-    FD_SET(spad_server->socket, &session_socket_mask);
-  }
-
-
-  /* spad_io connects to SessionIOName server socket
-    this is Lisp std IO read_from_spad_io handles requests */
-  spad_io = connect_to_local_server(SessionIOName, SessionIO, Forever);
-  if (spad_io == (Sock *) 0) {
-    fprintf(stderr, "session: Cannot connect to AXIOM IO!\n");
-    exit(0);
-  }
-  else {
-#ifdef DEBUG
-    fprintf(stderr,"session: connected SessionIOName , fd = %d\n",
-	    spad_io->socket);
-#endif  
-    FD_SET(spad_io->socket, &session_socket_mask);
-  }
-  bsdSignal(SIGUSR2, usr2_handler,DontRestartSystemCalls);
-  bsdSignal(SIGUSR1, usr1_handler,RestartSystemCalls);
-  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
-  bsdSignal(SIGTERM, term_handler,RestartSystemCalls);
-
-  /* open_server opens the server socket so that we can accept connections
-    we expect connections from spadbuf/spadclient(purpose:InterpWindow) 
-    and hypertex (MenuServer) */
-
-  if (open_server(SessionServer) == -2) {
-    fprintf(stderr, "session: Cannot make server socket!\n");
-    exit(-1);
-  }
-  else {
-#ifdef DEBUG
-    fprintf(stderr, "session: opened SessionServer , fd = %d\n",
-	    server[1].socket);
-#endif  
-    FD_SET(server[1].socket,&session_socket_mask);
-  }
-  manage_sessions();
-  return(0);
-}
-
-@
-\subsection{session}
-<<session>>=
-/* #define DEBUG */
-#define _SESSION_C
-
-<<includes>>
-<<variables>>
-<<usr1handler>>
-<<usr2handler>>
-<<termhandler>>
-<<pr>>
-<<closeclient>>
-<<readSpadServercommand>>
-<<testsockforprocess>>
-<<readmenuclientcommand>>
-<<readfromspadio>>
-<<killspad>>
-<<acceptsessionconnection>>
-<<readfromsession>>
-<<managesessions>>
-<<main>>
-
-@
-\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.
-*/
-
-@
-<<*>>=
-<<license>>
-<<session>>
-@ 
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} nothing
-\end{thebibliography}
-\end{document}
diff --git a/src/sman/sman.c.pamphlet b/src/sman/sman.c.pamphlet
deleted file mode 100644
index 7c3e3b4..0000000
--- a/src/sman/sman.c.pamphlet
+++ /dev/null
@@ -1,1113 +0,0 @@
-\documentclass{article}
-\usepackage{axiom}
-\begin{document}
-\title{\$SPAD/src/sman sman}
-\author{The Axiom Team}
-\maketitle
-\begin{abstract}
-The superman process, called sman, is normally invoked from the
-axiom shell script in order to start a tree of subprocesses.
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-\section{sman.h}
-The spad\_proc structure holds information about the process id
-of a child process, what to do when it dies, and the shell command
-line necessary to restart the process. There is a linked list of
-these structures which maintains the process list for axiom.
-<<sman.h>>=
-/* Process control definitions.  Used by fork_you and spawn_of_hell */
-
-/* When a process dies it kills off everything else */
-#define Die 1
-/* When a process dies, do nothing */
-#define NadaDelShitsky  2
-/* When a process dies start it up again */
-#define DoItAgain       3
-
-typedef struct spad_proc {
-  int	proc_id;	/* process id of child */
-  int	death_action;	/* one of the above constants */
-  char	*command;	/* sh command line to restart the process */
-  struct spad_proc *next;
-} SpadProcess;
-
-@
-\section{sman}
-\subsection{includes}
-<<includes>>=
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <pwd.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#if defined(SUN4OS5platform) || defined(HP10platform)
-#include <sys/stropts.h>
-#endif
-
-#include "com.h"
-#include "bsdsignal.h"
-#include "sman.h"
-
-#include "bsdsignal.h1"
-#include "sockio-c.h1"
-#include "openpty.h1"
-#include "sman.h1"
-
-@
-\subsection{variables}
-We add a debug flag so we can print information about what [[sman]]
-is trying to do. This change is pervasive as it touches nearly every
-routine.
-<<debugflag>>=
-int tpd=0;                      /* to-print-debug information */
-@
-This line is no longer used. We would completely elide it except that
-it would raise spurious issues about deleting credit and/or copyright
-information.
-\begin{verbatim}
-char *start_line =
-"AKCL (Austin Kyoto Common Lisp)  Version(1.568) Thu Aug 22 16:49:01 EDT 1991\
-\r\nContains Enhancements by W. Schelter\r\n";
-\end{verbatim}
-We modified the place where the command list lives. 
-The command list used to live in
-\begin{verbatim}
-$AXIOM/../../share/algebra/command.list
-\end{verbatim}
-but the open source version of the system no longer has a share
-subdirectory so we move this to the lib subdirectory.
-<<clefprogram>>=
-char	*ClefProgram            = 
-           "$AXIOM/bin/clef -f $AXIOM/lib/command.list -e ";
-@
-and we change the command line arguments
-<<clefprogram1>>=
-      ClefProgram = 
-        strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e ");
-@
-<<variables>>=
-char *ws_path;                  /* location of the AXIOM executable */
-int start_clef;			/* start clef under spad */
-int start_graphics;		/* start the viewman */
-int start_nagman;               /* start the nagman */
-int start_ht;			/* start hypertex */
-int start_spadclient;		/* Start the client spad buffer */
-int start_local_spadclient;	/* Start the client spad buffer */
-int use_X;			/* Use the X windows environment */
-int server_num;			/* AXIOM server number */
-<<debugflag>>
-
-/************************************************/
-/* definitions of programs which sman can start */
-/************************************************/
-
-char	*GraphicsProgram        = "$AXIOM/lib/viewman";
-char    *NagManagerProgram      = "$AXIOM/lib/nagman";
-char	*HypertexProgram        = "$AXIOM/bin/hypertex -s";
-<<clefprogram>>
-char	*SessionManagerProgram  = "$AXIOM/lib/session";
-char	*SpadClientProgram      = "$AXIOM/lib/spadclient";
-char	*PasteFile		= NULL;
-char	*MakeRecordFile		= NULL;
-char	*VerifyRecordFile	= NULL;
-
-SpadProcess *spad_process_list = NULL;
-/***************************/
-/* sman defaults file name */
-/***************************/
-
-#define SpadDefaultFile "spadprof.input"
-
-char ClefCommandLine[256];
-
-#define BufSize      4096 	/* size of communication buffer */
-char big_bad_buf[BufSize];      /* big I/O buffer */
-
-Sock *session_io = NULL;        /* socket connecting to session manager */
-
-/***********************************************************/
-/* Some characters used and externally defined in edible.h */
-/***********************************************************/
-
-unsigned char  _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2;
-
-/*************************************/
-/* Stuff for opening pseudo-terminal */
-/*************************************/
-
-int ptsNum, ptcNum;
-char ptsPath[20], ptcPath[20];
-
-char **new_envp;                /* new environment for AXIOM */
-int child_pid;                  /* child's process id */
-struct termios oldbuf;           /* the original settings */
-struct termios childbuf;         /* terminal structure for user i/o */
-
-
-int nagman_signal=0;
-int death_signal = 0;
-
-@
-\subsection{process\_arguments}
-<<processarguments>>=
-static void
-process_arguments(int argc,char ** argv)
-{
-  int arg;
-  if (tpd == 1) fprintf(stderr,"sman:process_arguments entered\n");
-  for (arg = 1; arg < argc; arg++) {
-    if      (strcmp(argv[arg], "-debug")      == 0)
-      tpd = 1;
-    else if (strcmp(argv[arg], "-noclef")      == 0)
-      start_clef = 0;
-    else if (strcmp(argv[arg], "-clef")        == 0)
-      start_clef = 1;
-    else if (strcmp(argv[arg], "-gr")          == 0)
-      start_graphics = 1;
-    else if (strcmp(argv[arg], "-nogr")        == 0)
-      start_graphics = 0;
-    else if (strcmp(argv[arg], "-nag")          == 0)
-      start_nagman = 1;
-    else if (strcmp(argv[arg], "-nonag")        == 0)
-      start_nagman = 0;
-    else if (strcmp(argv[arg], "-ht")          == 0)
-      start_ht = 1;
-    else if (strcmp(argv[arg], "-noht")        == 0)
-      start_ht = 0;
-    else if (strcmp(argv[arg], "-iw")          == 0)
-      start_spadclient = 1;
-    else if (strcmp(argv[arg], "-ihere")       == 0)
-      start_local_spadclient = 1;
-    else if (strcmp(argv[arg], "-noihere")     == 0)
-      start_local_spadclient = 0;
-    else if (strcmp(argv[arg], "-noiw")        == 0)
-      start_spadclient = 0;
-    else if (strcmp(argv[arg], "-ws")          == 0)
-      ws_path = argv[++arg];
-    else if (strcmp(argv[arg], "-comp")        == 0)
-      ws_path = "$AXIOM/etc/images/comp";
-    else if (strcmp(argv[arg], "-nox")         == 0)
-      {
-	use_X = 0;
-	start_local_spadclient = 1;
-	start_spadclient = 0;
-	start_ht = 0;
-	start_graphics = 0;
-      }
-    else if (strcmp(argv[arg], "-grprog")      == 0)
-      GraphicsProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-nagprog")      == 0)
-      NagManagerProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-htprog")      == 0)
-      HypertexProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-clefprog")    == 0) {
-      strcpy(ClefCommandLine,argv[++arg]);
-<<clefprogram1>>
-    }
-    else if (strcmp(argv[arg], "-sessionprog") == 0)
-      SessionManagerProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-clientprog")  == 0)
-      SpadClientProgram = argv[++arg];
-    else if (strcmp(argv[arg], "-rm")  == 0)
-      MakeRecordFile = argv[++arg];
-    else if (strcmp(argv[arg], "-rv")  == 0)
-      VerifyRecordFile = argv[++arg];
-    else if (strcmp(argv[arg], "-paste")  == 0)
-      PasteFile = argv[++arg];
-    else {
-      fprintf(stderr, "Usage: sman <-clef|-noclef> <-gr|-nogr> <-ht|-noht>");
-      fprintf(stderr, " <-iw|-noiw> <-nag|-nonag> <-nox> <-comp>");
-      fprintf(stderr, " <-ws spad_workspace> <-grprog path> <-htprog path>");
-      fprintf(stderr, " <-clefprog path> <-sessionprog path> <-nagprog path>");
-      fprintf(stderr, " <-clientprog path>\n");
-      exit(-1);
-    }
-  }
-  if (tpd == 1)
-  { fprintf(stderr,"  sman ");
-    if (start_clef == 0)
-      fprintf(stderr,"-noclef ");
-    else
-      fprintf(stderr,"-clef ");
-    if (start_graphics == 0)
-      fprintf(stderr,"-nogr ");
-    else
-      fprintf(stderr,"-gr ");
-    if (start_nagman == 0)
-      fprintf(stderr,"-nonag ");
-    else
-      fprintf(stderr,"-nag ");
-    if (start_ht == 0)
-      fprintf(stderr,"-noht ");
-    else
-      fprintf(stderr,"-ht ");
-    if (start_spadclient == 0)
-      fprintf(stderr,"-noiw ");
-    else
-      fprintf(stderr,"-iw ");
-    if (start_local_spadclient == 0)
-      fprintf(stderr,"-noihere ");
-    else
-      fprintf(stderr,"-ihere ");
-    if (start_local_spadclient == 0)
-      fprintf(stderr,"-noihere ");
-    else
-      fprintf(stderr,"-ihere ");
-    if (use_X == 0)
-      fprintf(stderr,"-nox ");
-    fprintf(stderr,"-ws ");
-    fprintf(stderr,"'%s' ",ws_path);
-    fprintf(stderr,"-grprog ");
-    fprintf(stderr,"'%s' ",GraphicsProgram);
-    fprintf(stderr,"-nagprog ");
-    fprintf(stderr,"'%s' ",NagManagerProgram);
-    fprintf(stderr,"-htprog ");
-    fprintf(stderr,"'%s' ",HypertexProgram);
-    fprintf(stderr,"-clefprog ");
-    fprintf(stderr,"'%s' ",ClefCommandLine);
-    fprintf(stderr,"-sessionprog ");
-    fprintf(stderr,"'%s' ",SessionManagerProgram);
-    fprintf(stderr,"-clientprog ");
-    fprintf(stderr,"'%s' ",SpadClientProgram);
-    fprintf(stderr,"-rm ");
-    fprintf(stderr,"'%s' ",MakeRecordFile);
-    fprintf(stderr,"-rv ");
-    fprintf(stderr,"'%s' ",VerifyRecordFile);
-    fprintf(stderr,"-paste ");
-    fprintf(stderr,"'%s' ",PasteFile);
-    fprintf(stderr,"\n");
-  }
-  if (tpd == 1) fprintf(stderr,"sman:process_arguments exit\n");
-}
-
-@
-\subsection{should\_I\_clef}
-<<shouldIclef>>=
-static int 
-should_I_clef(void)
-{
-  return(1);
-}
-
-@
-\subsection{in\_X}
-<<inX>>=
-static int 
-in_X(void)
-{
-  if (getenv("DISPLAY")) return 1;
-  return 0;
-}
-
-@
-\subsection{set\_up\_defaults}
-These are the default values for sman. A '1' value means that
-sman will try to start the given process, a '0' value means not
-starting the process.
-
-We do not have replacement code for the [[nagman]] process nor
-do we have a copy of the [[nag fortran library]] to test the process.
-Until this changes we set [[start_nagman = 0]] in order to disable
-starting this process by default.
-<<setupdefaults>>=
-static  void
-set_up_defaults(void)
-{
-  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults entered\n");
-  start_clef = should_I_clef();
-  start_graphics = 1;
-  start_nagman = 0;
-  start_ht = 1;
-  start_spadclient = 0;
-  start_local_spadclient = 1;
-  use_X = isatty(0) && in_X();
-  ws_path = "$AXIOM/bin/AXIOMsys";
-  if (tpd == 1) fprintf(stderr,"sman:set_up_defaults exit\n");
-}
-
-@
-\subsection{process\_options}
-<<processoptions>>=
-static void
-process_options(int argc, char **argv)
-{
-  if (tpd == 1) fprintf(stderr,"sman:process_options entered\n");
-  set_up_defaults();
-  process_arguments(argc, argv);
-  if (tpd == 1) fprintf(stderr,"sman:process_options exit\n");
-}
-
-@
-\subsection{death\_handler}
-<<deathhandler>>=
-static void
-death_handler(int sig)
-{
-  death_signal = 1;
-}
-
-@
-\subsection{nagman\_handler}
-<<nagmanhandler>>=
-static void 
-nagman_handler(int sig)
-{
-  nagman_signal=1;
-}
-
-@
-\subsection{sman\_catch\_signals}
-<<smancatchsignals>>=
-static void
-sman_catch_signals(void)
-{
-  
-  /* Set up the signal handlers for sman */
-  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
-  bsdSignal(SIGTERM, death_handler,RestartSystemCalls);
-  bsdSignal(SIGQUIT, death_handler,RestartSystemCalls);
-  bsdSignal(SIGHUP,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGILL,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGTRAP, death_handler,RestartSystemCalls);
-  bsdSignal(SIGIOT,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGBUS,  death_handler,RestartSystemCalls);
-  bsdSignal(SIGSEGV, death_handler,RestartSystemCalls);
-  /* don't restart wait call on SIGUSR1  */
-  bsdSignal(SIGUSR1, nagman_handler,DontRestartSystemCalls); 
-  /* ONLY nagman should send this.
-     If an error (such as C-c) interrupts a NAGLINK call, nagman
-     gets a signal to clean up. We need to start another nagman 
-     almost immediately to process the next NAGLINK request.
-     Since nagman takes a while to clean up, we treat it specially.
-     nagman should send a signal (USR1) to sman.
-     sman should respond by spawning a new nagman.
-     
-     so nagman is NOT a DoItAgain but a NadaDelShitsky.
-     
-     The USR1 mechanism does not work for HPUX 9 - use DoItAgain 
-     */
-
-}
-
-@
-\subsection{fix\_env}
-insert SPADSERVER and SPADNUM variables into the environemnt
-<<fixenv>>=
-static void
-fix_env(char **envp, int spadnum)
-{
-  int len, i;
-  char *sn;
-  for(len = 0; envp[len] != NULL; len++);
-  new_envp = (char **) malloc((len + 3) * sizeof(char *));
-  new_envp[0] = "SPADSERVER=TRUE";
-  sn = (char *) malloc(20 * sizeof(char));
-  sprintf(sn, "SPADNUM=%d", spadnum);
-  new_envp[1] = sn;
-  for(i=0; i<=len; i++)
-    new_envp[i+2] = envp[i];
-}
-
-@
-\subsection{init\_term\_io}
-<<inittermio>>=
-static void
-init_term_io(void)
-{
-  if(!isatty(0)) return;
-  if( tcgetattr(0, &oldbuf) == -1) {
-    perror("getting termios");
-    return ; 			/*  exit(-1); */
-  }
-  if( tcgetattr(0, &childbuf) == -1) {
-    perror("getting termios");
-    return ; 			/*   exit(-1); */
-  }
-  _INTR = oldbuf.c_cc[VINTR];
-  _QUIT = oldbuf.c_cc[VQUIT];
-  _ERASE = oldbuf.c_cc[VERASE];
-  _KILL = oldbuf.c_cc[VKILL];
-  _EOF = oldbuf.c_cc[VEOF];
-  _EOL = oldbuf.c_cc[VEOL];
-}
-
-@
-\subsection{strPrefix}
-<<strPrefix>>=
-static char *
-strPrefix(char *prefix,char * s)
-{
-  while (*prefix != '\0' && *prefix == *s) {
-    prefix++;
-    s++;
-  }
-  if (*prefix == '\0') return s;
-  return NULL;
-}
-
-@
-\subsection{check\_spad\_proc}
-<<checkspadproc>>=
-static void
-check_spad_proc(char *file, char *prefix)
-{
-  char *num;
-  int pid;
-  if ((num = strPrefix(prefix, file))) {
-    pid = atoi(num);
-    if (pid > 2) {
-      kill(pid, 0);
-      if (kill(pid, 0) == -1 && errno == ESRCH) {
-	unlink(file);
-      }
-    }
-  }
-}
-
-@
-\subsection{clean\_up\_old\_sockets}
-<<cleanupoldsockets>>=
-static void
-clean_up_old_sockets(void)
-{
-  char com[512], tmp_file[128];
-  FILE *file;
-  int len;
-  sprintf(tmp_file, "/tmp/socks.%d", server_num);
-  sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s",
-	  tmp_file, tmp_file);
-  system(com);
-  file = fopen(tmp_file, "r");
-  if (file == NULL) {
-    fprintf(stderr, "Can't open socket listing file\n");
-    return;
-  }
-  while(fgets(com, 512, file) != NULL) {
-    len = strlen(com);
-    if (len) com[len-1] = '\0';
-    else break;
-    check_spad_proc(com, "/tmp/.d");
-    check_spad_proc(com, "/tmp/.s");
-    check_spad_proc(com, "/tmp/.i");
-    check_spad_proc(com, "/tmp/.h");
-  }
-  fclose(file);
-  unlink(tmp_file);
-}
-
-@
-\subsection{fork\_you}
-<<forkyou>>=
-static SpadProcess *
-fork_you(int death_action)
-{
-  /* fork a new process, giving it a default death action */
-  /* return NULL in child, SpadProcess in parent          */
-  int child_pid = fork();
-  SpadProcess *proc;
-  if (!child_pid) return NULL;
-  proc = (SpadProcess *) malloc(sizeof(SpadProcess));
-  proc->proc_id = child_pid;
-  proc->death_action = death_action;
-  proc->command = NULL;
-  proc->next = spad_process_list;
-  spad_process_list = proc;
-  return proc;
-}
-
-@
-\subsection{exec\_command\_env}
-Note that the next-to-last argument of {\tt execle} must be an
-explicit NULL pointer. The previous naked 0 value was not correct.
-<<execcommandenv>>=
-static void
-exec_command_env(char *command,char ** env)
-{
-  char new_command[512];
-  sprintf(new_command, "exec %s", command);
-  execle("/bin/sh","/bin/sh", "-c", new_command, (char *)0, env);
-}
-
-@
-\subsection{spawn\_of\_hell}
-<<spawnofhell>>=
-static SpadProcess *
-spawn_of_hell(char *command, int death_action)
-{
-  SpadProcess *proc = fork_you(death_action);
-  if (proc != NULL) {
-    proc->command = command;
-    return proc;
-  }
-  exec_command_env(command, new_envp);
-  return NULL;
-}
-
-@
-\subsection{start\_the\_spadclient}
-run a AXIOM client in the main process
-<<startthespadclient>>=
-static void
-start_the_spadclient(void)
-{
-  char command[256];
-  if (start_clef)
-#ifdef RIOSplatform
-    sprintf(command, 
-	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
-	    ClefProgram, SpadClientProgram);
-#else
-  sprintf(command, 
-	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
-	  ClefProgram, SpadClientProgram);
-#endif
-  else
-#ifdef RIOSplatform
-    sprintf(command, 
-	    "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
-	    SpadClientProgram);
-#else
-  sprintf(command, 
-	  "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s", 
-	  SpadClientProgram);
-#endif
-  if (tpd == 1) 
-    fprintf(stderr,"sman:start_the_spadclient: %s\n",command);
-  spawn_of_hell(command, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_local\_spadclient}
-<<startthelocalspadclient>>=
-static void
-start_the_local_spadclient(void)
-{
-  char command[256];
-  if (start_clef)
-    sprintf(command, "%s  %s", ClefProgram, SpadClientProgram);
-  else
-    sprintf(command, "%s", SpadClientProgram);
-  if (tpd == 1) 
-    fprintf(stderr,"sman:start_the_local_spadclient: %s\n",command);
-  spawn_of_hell(command, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_nagman}
-<<startthenagman>>=
-static void
-start_the_nagman(void)
-{
-#if defined(HP9platform)
-  spawn_of_hell(NagManagerProgram,DoItAgain);
-#else
-  spawn_of_hell(NagManagerProgram,NadaDelShitsky );
-#endif
-}
-
-@
-\subsection{start\_the\_session\_manager}
-<<startthesessionmanager>>=
-static void
-start_the_session_manager(void)
-{
-  spawn_of_hell(SessionManagerProgram, Die);
-}
-
-@
-\subsection{start\_the\_hypertex}
-<<startthehypertex>>=
-static void
-start_the_hypertex(void)
-{
-  char prog[512];
-
-  if (PasteFile){
-    sprintf(prog, "%s -k -ip %s", HypertexProgram, PasteFile);
-    spawn_of_hell(prog, NadaDelShitsky);
-  }
-  else if (MakeRecordFile){
-    sprintf(prog, "%s -k -rm %s", HypertexProgram,MakeRecordFile );
-    spawn_of_hell(prog, NadaDelShitsky);
-  }
-  else if (VerifyRecordFile){
-    sprintf(prog, "%s -k -rv %s", HypertexProgram, VerifyRecordFile);
-    spawn_of_hell(prog, NadaDelShitsky);
-  }
-  else	spawn_of_hell(HypertexProgram, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_graphics}
-<<startthegraphics>>=
-static void
-start_the_graphics(void)
-{
-  spawn_of_hell(GraphicsProgram, DoItAgain);
-}
-
-@
-\subsection{fork\_Axiom}
-<<forkAxiom>>=
-/* Start the AXIOM session in a separate process, */
-/* using a pseudo-terminal to catch all input and output */
-static void 
-fork_Axiom(void)
-{
-  char augmented_ws_path[256];  /* will append directory path */
-  char *tmp_pointer;
-  SpadProcess *proc;
-
-  proc =  fork_you(Die);
-  child_pid = (proc == NULL ? 0 : proc->proc_id);
-  switch(child_pid) {
-  case -1 :
-    fprintf(stderr, "Can't create a new process \n");
-    exit(0);
-  case 0:
-    /* Dissasociate from my parents group so all my child processes */
-    /* look at my terminal as the controlling terminal for the      */
-    /* group                                                        */
-
-    if(setsid() < 0) {
-      perror("Dissassociating from parents group");
-      exit(-1);
-    }
-
-    close(ptsNum);
-    /* Now reopen the server side, so that pg, su, etc. work properly */
-
-    if ((ptsNum =  open(ptsPath, O_RDWR)) < 0 ) {
-      perror("fork_Axiom: Failed to reopen server");
-      exit(-1);
-    }
-#if defined(SUN4OS5platform) || defined(HP10platform)
-    ioctl(ptsNum,I_PUSH,"ptem");
-    ioctl(ptsNum,I_PUSH,"ldterm");
-#endif
-
-    /* since I am the child, I can close ptc, and dup pts for all its */
-    /* standard descriptors                                           */
-
-    if( (dup2(ptsNum, 0) == -1) ||
-        (dup2(ptsNum, 1) == -1) ||
-        (dup2(ptsNum, 2) == -1)  ) {
-      perror("trying to dupe the child");
-      exit(-1);
-    }
-    close(ptcNum);
-    close(ptsNum);
-
-
-    /* I also have to turn off echoing, since I am echoing all the */
-    /* input myself                  */
-
-    childbuf.c_lflag &= ~ECHO;
-    if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) {
-      perror("setting the term buffer");
-      exit(-1); 
-    }
-    strcpy(augmented_ws_path,ws_path);          /* write the name    */
-    strcat(augmented_ws_path," ");              /* space             */
-    strcat(augmented_ws_path,ws_path);          /* name again        */
-    tmp_pointer = (char *)
-      strrchr(augmented_ws_path,'/');      /*pointer to last /  */
-    *(++tmp_pointer) = '\0';
-    exec_command_env(augmented_ws_path, new_envp);
-
-    /*    fprintf(stderr, "Cannot execute the %s system.\n", ws_path); */
-
-    exit(0);
-  }
-}
-
-@
-\subsection{start\_the\_Axiom}
-<<starttheAxiom>>=
-static void
-start_the_Axiom(char **envp)
-{
-  server_num = make_server_number();
-  clean_up_old_sockets();
-  if (server_num == -1) {
-    fprintf(stderr, "could not get an AXIOM server number\n");
-    exit(-1);
-  }
-  if (ptyopen(&ptcNum, &ptsNum, ptcPath, ptsPath) == -1) {
-    perror("start_the_Axiom: ptyopen failed");
-    exit(-1);
-  }
-  fix_env(envp, server_num);
-  fork_Axiom();
-  close(ptsNum);
-}
-
-@
-\subsection{clean\_up\_sockets}
-<<cleanupsockets>>=
-static void
-clean_up_sockets(void)
-{
-  char name[256];
-  sprintf(name, "%s%d", SpadServer, server_num);
-  unlink(name);
-  sprintf(name, "%s%d", SessionServer, server_num);
-  unlink(name);
-  sprintf(name, "%s%d", SessionIOName, server_num);
-  unlink(name);
-  sprintf(name, "%s%d", MenuServerName, server_num);
-  unlink(name);
-}
-
-@
-\subsection{read\_from\_spad\_io}
-<<readfromspadio>>=
-static void
-read_from_spad_io(int ptcNum)
-{
-  int ret_code = 0, i=0;
-  static int mes_len =0; 
-  ret_code = read(ptcNum, big_bad_buf, BufSize);
-  if (ret_code == -1) {
-    clean_up_sockets();
-    exit(-1);
-  }
-  if (session_io == NULL) {
-    if (ret_code < mes_len)
-      mes_len -= ret_code;
-    else {
-      if (mes_len > 0) {
-	i = mes_len;
-	mes_len = 0;
-      }
-      else
-	i = 0;
-      ret_code = write(1, big_bad_buf+i, ret_code-i);
-    }
-  }
-  else
-    ret_code = swrite(session_io, big_bad_buf, ret_code,
-		      "writing to session man");
-  if (ret_code == -1) {
-    perror("writing output to session manager");
-    clean_up_sockets();
-    exit(-1);
-  }
-}
-
-@
-\subsection{read\_from\_manager}
-<<readfrommanager>>=
-static void
-read_from_manager(int ptcNum)
-{
-  int ret_code;
-  ret_code = sread(session_io, big_bad_buf, BufSize, "reading session io");
-  if (ret_code == -1) {
-    return;
-  }
-  ret_code = write(ptcNum, big_bad_buf, ret_code);
-  if (ret_code == -1) {
-    return;
-  }
-}
-
-@
-\subsection{manage\_spad\_io}
-<<managespadio>>=
-static void
-manage_spad_io(int ptcNum)
-{
-  int ret_code, i, p;
-  fd_set rd;
-  while (1) {
-    rd = socket_mask;
-    FD_SET(ptcNum, &rd);
-    if (session_io != NULL)
-      FD_SET(session_io->socket, &rd);
-    ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
-    if (ret_code == -1) {
-      perror("Session manager select");
-      clean_up_sockets();
-      exit(-1);
-    }
-    if (FD_ISSET(ptcNum, &rd)) {
-      read_from_spad_io(ptcNum);
-    }
-    for(i=0; i<2; i++) {
-      if (server[i].socket > 0 && FD_ISSET(server[i].socket, &rd)) {
-	p = accept_connection(server+i);
-	switch(p) {
-	case SessionIO:
-	  session_io = purpose_table[SessionIO];
-	  /*  printf("connected session manager\n\r");*/
-	  printf("\n");
-	  break;
-	default:
-	  printf("sman: Unkown connection request type: %d\n", p);
-	  break;
-	}
-      }
-    }
-    if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) {
-      read_from_manager(ptcNum);
-    }
-  }
-}
-
-@
-\subsection{init\_spad\_process\_list}
-<<initspadprocesslist>>=
-static void
-init_spad_process_list(void)
-{
-  spad_process_list = NULL;
-}
-
-@
-\subsection{print\_spad\_process\_list}
-<<printspadprocesslist>>=
-#if 0
-static void
-print_spad_process_list()
-{
-  SpadProcess *proc;
-  for(proc = spad_process_list; proc != NULL; proc = proc->next)
-    fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id,
-	    proc->death_action);
-}
-#endif
-
-@
-\subsection{find\_child}
-<<findchild>>=
-static SpadProcess *
-find_child(int proc_id)
-{
-  SpadProcess *proc;
-  for(proc = spad_process_list; proc != NULL; proc = proc->next)
-    if (proc->proc_id == proc_id) return proc;
-  return NULL;
-}
-
-@
-\subsection{kill\_all\_children}
-<<killallchildren>>=
-static void
-kill_all_children(void)
-{
-  char name[256];
-  SpadProcess *proc;
-  
-  
-  for(proc = spad_process_list; proc != NULL; proc = proc->next) {
-    kill(proc->proc_id, SIGTERM);
-  }
-  sprintf(name, "/tmp/hyper%d.input",server_num);
-  unlink(name);
-
-}
-
-@
-\subsection{clean\_up\_terminal}
-<<cleanupterminal>>=
-static void
-clean_up_terminal(void)
-{
-  tcsetattr(0, TCSAFLUSH, &oldbuf);
-}
-
-@
-\subsection{monitor\_children}
-<<monitorchildren>>=
-static void
-monitor_children(void)
-{
-  int dead_baby, stat;
-  SpadProcess *proc;
-  while (1) {
-    stat = 0;
-    dead_baby = wait(&stat);
-    /* Check the value of dead_baby, since wait may have returned
-       a pid but subsequently we have received a signal.  Yeuch! */
-    if (dead_baby == -1 && death_signal) {
-      kill_all_children();
-      clean_up_sockets();
-      clean_up_terminal();
-      sleep(2);
-      exit(0);
-    }
-    /* Check the value of dead_baby, since wait may have returned
-       a pid but subsequently we have received a signal.  Yeuch! */
-    if(dead_baby == -1 && nagman_signal) {
-      nagman_signal=0;
-      spawn_of_hell(NagManagerProgram,NadaDelShitsky);
-      continue;
-    }
-
-    if (dead_baby == -1) {
-      fprintf(stderr, "sman: wait returned -1\n");
-      continue;
-    }
-    proc = find_child(dead_baby);
-    if (proc == NULL) {
-      /*      fprintf(stderr, "sman: %d is not known to be a child process\n",
-	      dead_baby);
-	      */
-      continue;
-    }
-    switch(proc->death_action) {
-    case Die:
-      kill_all_children();
-      clean_up_sockets();
-      clean_up_terminal();
-      sleep(2);
-      exit(0);
-    case NadaDelShitsky:
-      break;
-    case DoItAgain:
-      spawn_of_hell(proc->command, DoItAgain);
-      break;
-    }
-  }
-}
-
-@
-\subsection{main}
-The main procedure should return an [[int]]. We change the return value
-here and in [[src/include/sman.h1]].
-<<result>>=
-  return(0);
-@
-<<main>>=
-int
-main(int argc, char *argv[],char *envp[])
-{
-  if (tpd == 1) fprintf(stderr,"sman:main entered\n");
-  bsdSignal(SIGINT,  SIG_IGN,RestartSystemCalls);
-  process_options(argc, argv);
-
-  init_term_io();
-  init_spad_process_list();
-  start_the_Axiom(envp);
-  if (open_server(SessionIOName) == -2) {
-    fprintf(stderr, "Fatal error opening I/O socket\n");
-    clean_up_sockets();
-    exit(-1);
-  }
-  start_the_session_manager();
-  if (start_spadclient)       start_the_spadclient();
-  if (start_local_spadclient) start_the_local_spadclient();
-  if (start_nagman)           start_the_nagman();
-  if (start_ht)               start_the_hypertex();
-  if (start_graphics)         start_the_graphics();
-  sleep(1);
-
-  if (fork_you(Die) != NULL) {
-    sman_catch_signals();
-    monitor_children();
-    exit(0);
-  }
-  manage_spad_io(ptcNum);
-  if (tpd == 1) fprintf(stderr,"sman:main exit\n");
-<<result>>
-}
-
-@
-\subsection{sman}
-<<sman>>=
-#define _SMAN_C
-
-<<includes>>
-<<variables>>
-<<processarguments>>
-<<shouldIclef>>
-<<inX>>
-<<setupdefaults>>
-<<processoptions>>
-<<deathhandler>>
-<<nagmanhandler>>
-<<smancatchsignals>>
-<<fixenv>>
-<<inittermio>>
-<<strPrefix>>
-<<checkspadproc>>
-<<cleanupoldsockets>>
-<<forkyou>>
-<<execcommandenv>>
-<<spawnofhell>>
-<<startthespadclient>>
-<<startthelocalspadclient>>
-<<startthenagman>>
-<<startthesessionmanager>>
-<<startthehypertex>>
-<<startthegraphics>>
-<<forkAxiom>>
-<<starttheAxiom>>
-<<cleanupsockets>>
-<<readfromspadio>>
-<<readfrommanager>>
-<<managespadio>>
-<<initspadprocesslist>>
-<<printspadprocesslist>>
-<<findchild>>
-<<killallchildren>>
-<<cleanupterminal>>
-<<monitorchildren>>
-<<main>>
-
-@
-\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.
-*/
-
-@
-<<*>>=
-<<license>>
-<<sman>>
-@ 
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} nothing
-\end{thebibliography}
-\end{document}
diff --git a/src/sman/spadclient.c.pamphlet b/src/sman/spadclient.c.pamphlet
deleted file mode 100644
index 5b2149a..0000000
--- a/src/sman/spadclient.c.pamphlet
+++ /dev/null
@@ -1,89 +0,0 @@
-\documentclass{article}
-\usepackage{axiom}
-\begin{document}
-\title{\$SPAD/src/sman spadclient.c}
-\author{The Axiom Team}
-\maketitle
-\begin{abstract}
-\end{abstract}
-\eject
-\tableofcontents
-\eject
-\section{spadclient}
-<<spadclient>>=
-#define _SPADCLIENT_C
-
-#include <stdio.h>
-#include <signal.h>
-#include "com.h"
-#include "bsdsignal.h"
-
-#include "bsdsignal.h1"
-#include "sockio-c.h1"
-#include "spadclient.h1"
-
-Sock *sock;
-
-static void 
-inter_handler(int sig)
-{
-  send_signal(sock, SIGUSR2);
-  fflush(stderr);
-}
-
-
-int 
-main(void)
-{
-  sock = connect_to_local_server(SessionServer, InterpWindow, Forever);
-  bsdSignal(SIGINT, inter_handler,RestartSystemCalls); 
-  remote_stdio(sock);
-  return(0);
-}
-
-@
-\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.
-*/
-
-@
-<<*>>=
-<<license>>
-<<spadclient>>
-@ 
-\eject
-\begin{thebibliography}{99}
-\bibitem{1} nothing
-\end{thebibliography}
-\end{document}



