I am completly new to the world of functional languages and Lisp
dialects. I have been reading a few blogs and articles over the
internet (My SICP book is on its way!).
I was wondering if there is a simple way to see how primitive
functions (or even the ones I defined previously) are implemented. For
example, if I want to check how + function is implemented how could I
do that?
I am using emacs 23.2.1 (is that enough to know?).
Regards
It varies widely based on your dialect and implementation. If you're
using Common Lisp you can use disasseble
http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_disassemble.html.
e.g. to see to see the implementation of of + just type (disassemble
'+)
If you are using an open source implementation you can try downloading
the source and poking around.
In a coherently set-up emacs/Slime, you can M-. and jump to
definition. So we find that DEFUN in SBCL is implemented as follows:
(defmacro-mundanely defun (&environment env name args &body body)
"Define a function at top level."
#+sb-xc-host
(unless (symbol-package (fun-name-block-name name))
(warn "DEFUN of uninterned function name ~S (tricky for GENESIS)"
name))
(multiple-value-bind (forms decls doc) (parse-body body)
(let* (;; stuff shared between LAMBDA and INLINE-LAMBDA and NAMED-
LAMBDA
(lambda-guts `(,args
,@decls
(block ,(fun-name-block-name name)
,@forms)))
(lambda `(lambda ,@lambda-guts))
#-sb-xc-host
(named-lambda `(named-lambda ,name ,@lambda-guts))
(inline-lambda
(when (inline-fun-name-p name)
;; we want to attempt to inline, so complain if we can't
(or (sb!c:maybe-inline-syntactic-closure lambda env)
(progn
(#+sb-xc-host warn
#-sb-xc-host sb!c:maybe-compiler-notify
"lexical environment too hairy, can't inline
DEFUN ~S"
name)
nil)))))
`(progn
;; In cross-compilation of toplevel DEFUNs, we arrange for
;; the LAMBDA to be statically linked by GENESIS.
;;
;; It may seem strangely inconsistent not to use NAMED-LAMBDA
;; here instead of LAMBDA. The reason is historical:
;; COLD-FSET was written before NAMED-LAMBDA, and has special
;; logic of its own to notify the compiler about NAME.
#+sb-xc-host
(cold-fset ,name ,lambda)
(eval-when (:compile-toplevel)
(sb!c:%compiler-defun ',name ',inline-lambda t))
(eval-when (:load-toplevel :execute)
(%defun ',name
;; In normal compilation (not for cold load) this
is
;; where the compiled LAMBDA first appears. In
;; cross-compilation, we manipulate the
;; previously-statically-linked LAMBDA here.
#-sb-xc-host ,named-lambda
#+sb-xc-host (fdefinition ',name)
,doc
',inline-lambda
(sb!c:source-location)))))))
You will find this routine in SBCL's defmacro.lisp.
I am not sure how this will help you besides providing examples of
your Lisp implementation innards.
HTH
If you're using emacs with a well configured slime and inferior lisp
(= Common Lisp implementation, emacs calls "inferior" its subprocesses),
then it should be enough to type M-. after the name of the function (in
a buffer with slime-mode activated, such as a .lisp file).
For example,
C-u M-x slime RET ccl RET
C-x C-f /tmp/a.lisp RET
(defun M-.
opens /data/src/languages/ccl/ccl-trunk-linuxx86/lib/macros.lisp on:
(defmacro defun (spec args &body body &environment env &aux global-name inline-spec)
"Define a function at top level."
(validate-function-name spec)
(setq args (require-type args 'list))
(setq body (require-type body 'list))
...
(I downloaded and compiled ccl myself).
On the other hand, with sbcl, I get:
cond: Error: failed to find the WRITE-DATE of /usr/lib64/sbcl/src/code/defboot.lisp: No such file or di
(I installed sbcl thru my distribution packages, and they didn't deem
the sources of sbcl worthwhile to install into /usr/lib64/sbcl/src).
But if you install them, slime can bring you to the mentionned file on:
(defmacro-mundanely defun (&environment env name args &body body)
"Define a function at top level."
#+sb-xc-host
(unless (symbol-package (fun-name-block-name name))
(warn "DEFUN of uninterned function name ~S (tricky for GENESIS)" name))
(multiple-value-bind (forms decls doc) (parse-body body)
...
You may also easily find the source of emacs lisp operators (or your own
emacs lisp functions), with: C-h f RET C-x o TAB RET
C-x C-f /tmp/a.el RET
(defun C-h f RET C-x o TAB RET
but then again, you need to have the sources of emacs around, including
the C sources, to see them. (Which again, means you cannot trust your
distribution to have done it, but that you have to donwload the sources
of emacs and compile them yourself).
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
I'll check these later today and let you know if I was able to
succeed :)
P.S.: I am quite impressed with how fast you guys answered my
question. I am really glad. Thanks again!
Regards
On 29 maio, 23:46, "Pascal J. Bourguignon" <p...@informatimago.com>
wrote: