axiom-developer
[Top][All Lists]
Advanced

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

[Axiom-developer] hacking-tips-n-tricks.input.pamphlet


From: David MENTRE
Subject: [Axiom-developer] hacking-tips-n-tricks.input.pamphlet
Date: Fri, 08 Aug 2003 22:19:21 +0200
User-agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.2 (gnu/linux)

Hello,

I have collected Tim's posts on this list regarding way to hack more
easily on Axiom. Here is the resulting .pamphlet file.

You can produce it with the following commands:
  noweave -delay hacking-tips-n-tricks.input.pamphlet  > 
hacking-tips-n-tricks.tex
  latex hacking-tips-n-tricks.tex 
  latex hacking-tips-n-tricks.tex 

(I suppose you have the noweb package installed somewhere)

Best regards,
d.

\documentclass{article}
\usepackage{noweb}
\begin{document}
\title{Tips \& tricks to hack on Axiom}
\author{Nicolas Bourbaki}
\date{8th of August, 2003}
\maketitle
\begin{abstract}
This short document gives some hints to hack on Axiom. All of those tips
come from posts by Tim Daly on axiom-developer mailing list during
July 2003.
\end{abstract}

\tableofcontents

\section{Playing with lisp in Axiom}

If you wish you can look at the [[.clisp]] (boot translation), [[.lisp]]
(hand written lisp) or [[.lsp]] (compiler output) files, modify them,
and reload them. All of the translated code is translated to common lisp
and the common lisp lies in [[int/algebra]] and its
subdirectories. Essentially you can consider the compiler/interpreter
sources to live in this subdirectory.

You can drop into lisp by typing:
<<axiom-prompt>>=
)fin
@ 
and return to the Axiom prompt by typing:
<<axiom-prompt>>=
(restart)
@ 

You can issue any lisp command (e.g. call the function foo) thus:
<<axiom-prompt>>=
)lisp (foo)
@ 

\section{Direct typing of lisp under Axiom's interpreter}

You can type

<<axiom-prompt>>=
)lisp (setq $DALYMODE t)
@ 

and then any line that begins with an open-paren at the Axiom
prompt will be given directly to the lisp. e.g. after setting
[[$dalymode]] above you can type:

<<axiom-prompt>>=
(pprint |$InteractiveFrame|)
@ 

directly to the Axiom prompt. It makes lisp debugging easier.

\section{Setting your startup preferences}

If you add a file in your home directory called ``[[axiom.input]]'' (or
``[[.axiom.input]]'', depending on your CVS version) it will be read and
executed when axiom starts. This is useful for various reasons including
setting various switches. Mine reads:

<<.axiom.input>>=
)lisp (pprint "running .axiom.input")
)set quit unprotected
)set message autoload off
)set message startup off
@ 

You can execute any command in [[.axiom.input]]. Be aware that this will
\emph{also} be run while you are doing a "make" in Axiom compilation so
be careful what you ask do.

\section{Knowing the current Axiom's version}

There is code (called yearweek) in [[src/interp/util.lisp.pamphlet]]
that \emph{timestamps} Axiom during the build process. The format of
Axiom's version number is (badly) documented in the file. It is also
documented in [[src/interp/Makefile.pamphlet]]. It is a variable of the
form:
\begin{quote}
  YYYYMMDDxxx where YYYY is the year, MM is the month, DD is the day
  and xxx is a unique number identifying a build.
\end{quote}

Every interpsys image should have a [[*yearweek*]] variable, thus:

<<axiom-prompt>>=
)lisp *yearweek*
@ 

should give you the current version of your Axiom.

\section{Controlling Axiom's break behavior}

You can control whether Axiom will stop on errors by typing
<<axiom-prompt>>=
)set break break
@ 

If you type:
<<axiom-prompt>>=
)set break
@ 
Axiom will show you the various options.

\section{Getting lisp code generated from boot code}

If you are making changes to boot code it is sometimes helpful to
check the generated lisp code to ensure it does what you want.
You can convert an individual boot file to common lisp using the
[[boottran::boottocl]] function:

<<axiom-prompt>>=
)fin       -- drop into common lisp
(boottran::boottocl "foo.boot") 
@

when you do this it creates a [[foo.clisp]] file in
[[../../int/interp]]. 

Alternatively if you work from the pamphlet file the process is
more painful as you have to do

<<axiom-prompt>>=
)cd (yourpath)/int/interp
)sys notangle ../../src/interp/foo.boot.pamphlet >foo.boot
)fin
(boottran::boottocl "foo.boot") 
(restart)
@ 

The [[)cd]] step tells axiom to cd to the int/interp subdirectory.

The [[)sys notangle...]] extracts the boot file from the pamphlet file

The [[)fin]] step drops into common lisp

The [[(bootran...]] converts the "foo.boot" file to "foo.clisp"

The [[(restart)]] re-enters the top level loop

\section{Getting lisp code from algebra code}

If you want to watch the domain-level functions get called from a
particular domain (e.g [[CHAR]]) you can look in the [[int/algebra]]
directory. You will find either [[CHAR.lsp]] or [[CHAR.NRLIB/code.lsp]].
That file will contain the lisp code that results from compiling the
domain. You can trace any (or all) functions from that domain.  (Indeed
there is a file called [[monitor.lisp.pamphlet]] that will do those kind
of things. It exists only for debugging reasons).

If you want to trace [[CHAR]] operations you can look at this lisp
code, load it as interpreted code, and watch it execute. type:

<<axiom-prompt>>=
)cd (yourpath)/int/algebra
)lisp (load "CHAR.NRLIB/code.lsp")
)lisp (trace |CHAR;=;2$B;1|)
)lisp (trace |CHAR;<;2$B;2|)
....
@ 

(look at the code.lsp file for the rest of the names).

Generally, for debugging I create a file called [[d.lisp]]
that contains a sequence of commands so I can rerun them
every time I restart Axiom. So, for instance, my current
file says things like:

<<d.lisp>>=
(in-package "BOOT")   ;;; where Axiom runs
#+:akcl
(defun S- (l1 l2)
 (reverse (set-difference l1 l2 :test #'equal)))
#-akcl
(defun S- (l1 l2)
 (reverse (set-difference l1 l2 :test #'equal)))
(load "RING.NRLIB/code.lsp")
... etc
@ 

Then when I start Axiom I type:

<<axiom-prompt>>=
)lisp (load "/tmp/d.lisp")
@ 

Additionally it is sometimes helpful to run debugsys rather than
interpsys. Common lisp gives you some debugging facilities. For example,
trace takes conditions that allow you to control what it does. Also
you can use the step function. So you can type:

<<axiom-prompt>>=
)lisp (step (+ (* 2 4) 5))
@ 

and watch each step of the evaluation. Since all of Axiom is really just
common lisp (boot files turn into [[int/interp/fn.clisp]] files, spad
files become [[int/interp/fn.NRLIB/code.lsp]] files and lisp files just
become [[int/interp/lisp]] files) you can watch anything execute.

The best place to look for the failure is likely in some subfunction
of [[|knownInfo|]]. You can watch this function execute by typing:

<<axiom-prompt>>=
)lisp (setq *print-arry* t)    ;; show the contents of vectors
)lisp (setq *print-circle* t)  ;; watch for circular structures
)lisp (setq *print-pretty* t)  ;; indent reasonably
)lisp (setq *print-length* 5)  ;; limit the length to some value
)lisp (setq *print-level* 5)   ;; limit the depth to some value
)lisp (trace |knownInfo|)
)co xpoly )con XPR           
@ 

\section{Observing the Axiom interpreter at work}

As a developer note you can see the interpreter searching for
operations by doing the following:

<<axiom-prompt>>=
)lisp (setq |$monitorNewWorld| t)
@ 

The messages are terse but you can more about what the interpreter
is trying to do.

\section{On Axiom's frames}

Axiom stores its variable bindings in a ``\emph{frame}'' which,
internally is an alist stored in the variable [[|$InteractiveFrame|]].

Suppose you have the following Axiom interpreter command:

<<axiom-prompt>>=
dom:=MonoidRing(Polynomial PrimeField 5, Permutation Integer)
@ 


If you create the 'dom' variable above you can see it by doing:

<<axiom-prompt>>=
)lisp (pprint |$InteractiveFrame|)
@ 

\section{Looking into dynamic lookups of Axiom}

Axiom creates arrays of functions and does a dynamic lookup using a
macro called [[SPADCALL]]. (Look at the [[.lsp]] files in the
subdirectories under [[int/algebra]]) To see this macro expanded you can
start up Axiom and type:
<<axiom-prompt>>=
)lisp (macroexpand '(spadcall a b))
@ 

Each algebra file has its own private vector and there is no central
place where recursion occurs. You can see this call-vector by doing:

<<axiom-prompt>>=
1
)lisp (setq *print-array* t)
)lisp (setq *print-circle* t)
)lisp (hget |$ConstructorCache| '|Integer|)
@ 
The Axiom compiler hard-codes indexes into the call vector using the
spadcall macro.

\end{document}




reply via email to

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