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

Re: Top Level Forms, etc.

    Can someone give me some clues regarding AKCL's compilation of top-level
    forms.  I have a file with stuff like this:
    (in-package :constraints)
    (use-package '(:foo :bar))
    (import '(mumble::define-condition mumble::make-condition))

    (define-condition ...)

    First, when I try to compile my file I get lots of complaints about
    these first three forms being in a bad place.  What?  I've never heard
    of this and one can even see examples of this in Steele.  What do
    these messages mean in AKCL?

I just compiled the following file in AKCL:

(in-package :constraints)
(use-package '(:foo :bar))
(import '(mumble::define-condition mumble::make-condition))

(defun jim () 7)
There were no warnings and it compiled and loaded correctly.

     I get lots of complaints about
    these first three forms being in a bad place.  What?  I've never hear

My guess is that these were not the first forms in your file.

There is definitely a section in Steele which talks about the package
forms being the first in the file.

from p 183 of CLTL

`The IN-PACKAGE function is intended to be placed at the start of a file ..'

If you put them after the first you get a warning.  The reason for
this warning, is that on loading compiled code the package operations
must be evaluated FIRST, before the constants vector (symbols
,constant list structure etc) can be correctly read in, which in turn
must happen before the rest of the forms in the file get eval'd.

No matter where you put the package operations in the file they will
all be effectively moved to the front.    This normally does not matter
since the constants vector will have the correct packages:

(in-package "JIM")

(defun foo () 3)

(in-package "JANE")

(defun foo () 3)

Will turn out ok (in akcl), because the constant vector will look
something like #(JIM::FOO JANE::FOO).  The value of *package* at the
time of both definitions while loading compiled code will be the
package "JANE" but, that should not affect the first definition, since
the packages of its constants were determined at compile time.

Of course there are ways of making those constants be constructed at
load time, and that is one reason why there has to be some
restriction, which says it is not really correct to put the
(in-package "JANE") where it is.  But unless you are constructing
constants at load time it will `work' (in AKCL) to misplace the
in-package statements.   It is not recommended however if you want
your code to be portable.   In fact I have found to be portable,
a single uncompiled file which defines all your packages and does
all the importing and exporting, should be loaded before
any other files are loaded.   Then each package should contain
just one in-package statement at the beginning.

In order to facilitate constructing such a file, AKCL contains
(in cmpnew/collectfn.lsp) a function

(get-packages (&optional (st "sys-package.lisp"))

which when evaluated writes out a sequence of appropriate in-package,
export, import, shadow,... statements to build the current state
of the packages.    So if you load in your system interpreted
you may use this facility to build a package definition file, and
so eliminate all sorts of randomly placed package statements.
I would not advise compiling this package definition file, but
loading it interpreted should be portable across lisps.