I keep trying to find information with the help of Google, and without
spending any money (I'm not long on cash right now), about a few
implementation details of Common Lisp. I'm coming to a solid grasp on
how compiled closures are generated, but there are a few other areas I'm
not so solid on. Hopefully someone can straighten me out on these.
Note that these are all 'what is the normal/preferred/niftiest way?'
questions, as I'm sure each implementation has its own method.
1. How are keyword arguments to compiled procedures handled? Is an
associative list passed in and marshalled by name by the entry code to
the procedure, or is there a smarter way?
2. How are global data objects handled in a natively compiled program?
How about in loaded-in files? When I load a file that involves compiled
closures, for instance, how is the environment stored in that file and
put into play with the existing Lisp image/environment?
Thanks to anyone who replies on this. :)
Ari
Ari Johnson <·····@hotmail.com> wrote in message news:<·····················@fed1read03>...
>
> 1. How are keyword arguments to compiled procedures handled? Is an
> associative list passed in and marshalled by name by the entry code to
> the procedure, or is there a smarter way?
In the limiting case, the function has to have code which can take a
perfectly conventional list and extract the keywords & values etc from
it. This happens in some case like this:
(defun foo (x &key (y 3 yp))
(format t "~&X = ~S, Y = ~S (~:[default~;provided~])~%"
x y yp))
(apply #'foo (list 1 ':y 13))
However there are a lot of cases where a system may be able to do much
better than that. Assuming that there is some mechanism of passing
fixed argument lists efficiently (in registers / an array / however),
then you can essentially compile multuple entry points to a function,
and then, if you can spot the keywords & other hair at compile time -
which you often can - compile a call to a fixed-argument-list version.
In fact, you can (I think) even do this yourself with compiler macros
and a hairy version of DEFUN, if your CL has efficient fixed-argument
functions, but no clever optimisation of keyword & optional arguments
in the compiler.
(defun-hairy foo (x &key (y 3 yp)
...)
would generate two definitions:
(defun foo (x &key (y 3 yp))
(foo/fixed x y yp))
(defun foo/fixed (x y yp)
...)
and a compiler-macro for FOO which would try and expand to a call to
FOO/FIXED if possible.
Of course the devil is in the details.
--tim
Ari Johnson <·····@hotmail.com> writes:
> 1. How are keyword arguments to compiled procedures handled? Is an
> associative list passed in and marshalled by name by the entry code
> to the procedure, or is there a smarter way?
I believe that typically, essentially the arguments are passed to the
function as a list. This list might well not be encoded as the normal
lisp lists are, but rather, for example, as a sequence of words on the
stack. Then, this list must be scanned by the callee for the keywords
and the corresponding variable set to the matching value. In
general. In some cases it's desirable and possible to short-cut this
process at compile-time.
> 2. How are global data objects handled in a natively compiled
> program? How about in loaded-in files? When I load a file that
> involves compiled closures, for instance, how is the environment
> stored in that file and put into play with the existing Lisp
> image/environment?
This is what read does. The "compiled" versions of read would be
"fasls", which are just specialized versions of read, but I believe
they essentially do the same thing. The linking happens the normal
way, e.g. by symbol lookup in packages, etc. Compiled code can be
stored just as an array of the bytes that make up the machine-code,
and so on. It's all pretty trivial, really.
--
Frode Vatvedt Fjeld
Frode Vatvedt Fjeld wrote:
> This is what read does. The "compiled" versions of read would be
> "fasls", which are just specialized versions of read, but I believe
> they essentially do the same thing. The linking happens the normal
> way, e.g. by symbol lookup in packages, etc. Compiled code can be
> stored just as an array of the bytes that make up the machine-code,
> and so on. It's all pretty trivial, really.
It sounds trivial, but it's felt like one of those "too good to be true"
things to me. It also seems as if both keyword arguments and compiled
globals would be slow to load, the way you've described each. But maybe
that doesn't matter so much. Thanks for the info.
P� Tue, 20 Apr 2004 00:52:27 -0700, skrev Ari Johnson <·····@hotmail.com>:
> Frode Vatvedt Fjeld wrote:
>
>> This is what read does. The "compiled" versions of read would be
>> "fasls", which are just specialized versions of read, but I believe
>> they essentially do the same thing. The linking happens the normal
>> way, e.g. by symbol lookup in packages, etc. Compiled code can be
>> stored just as an array of the bytes that make up the machine-code,
>> and so on. It's all pretty trivial, really.
>
> It sounds trivial, but it's felt like one of those "too good to be true"
> things to me. It also seems as if both keyword arguments and compiled
> globals would be slow to load, the way you've described each. But maybe
> that doesn't matter so much. Thanks for the info.
It is slow to load. However lisp provides an image which is pre-linked.
As the number of functions grows one can add them to the image.
(My compiler uses save-image, this is the usual but not spesified
by the ANSI spec). Anyhow this is why lisp generally loads faster
than Java which altso does runtime linkage.
--
Sender med M2, Operas revolusjonerende e-postprogram: http://www.opera.com/