On Apr 11, 2009, at 7:51 AM, Derick Eddington wrote:
...
Thank you for the informative response. I had been assuming that
building a new boot file sees the bindings from the version it's
building and not those from the pre-built boot file used by the
builder
process.
So, let's start from the beginning.
Building a boot file proceeds in two steps. First, all libraries
that end up in the boot file are expanded (the files containing
these libraries are listed in makefile.ss). Once all libraries
are expanded, the resulting core forms are compiled then serialized
to the new boot file.
To do the first step, you need an expander that knows how to handle
the base libraries. This expander must know about the libraries
that are going to be used, and what identifiers are exported from
them, and their meanings. We have two choices here. You can make
a new expander (by importing the psyntax libraries directly), and
initialize it manually with the set of required libraries and their
exports, etc., and use that expander in the first step in
bootstrapping. Alternatively, you can use the expander already
built-in to ikarus with its included set of libraries and exports.
Ikarus now uses the second approach, which means that the expander
and libraries in the building process are used for expanding the
base libraries. The first approach listed above is cleaner, and
would get around this two-step bootstrapping issue (though you'd
still not be able to use the new not-yet-defined identifiers at
macro-expansion time, but that's a minor inconvenience). This
would also allow us to expand the base libraries using a different
scheme implementation (if that's ever needed) since we won't have
to rely on the built-in expander. For now, it doesn't seem to be
worth the effort since I don't run into these problems often enough.
So, before you do this, you (or rather, I) need to refresh the
included boot files (both the 32- and 64-bit versions)
How does one do this? I had been assuming the pre-built boot file was
the boot file built (by you) left over from building the previous
revision. But looking at the log, I can see the last change to it was
revision 1729! And now I remember that I rarely see the boot file
included in repository updates.
Bootfiles are too big to be updated with every revision, so, I only
update them when absolutely necessary. I refresh them manually, by
building new bootfiles (for both the 32-bit and 64-bit versions) and
overwrite the old ones.
to include
directory-streams. Once that's done, they can be used in defining
other primitives.
Alternatively, you can simply define directory-list in ikarus.io.ss
where it can lexically see the definitions of directory-streams and
there will be no problems with that.
Good to know.
This might be the right place to define it, since you might want
to have some internal common helpers.
Alternatively, you can define it in a new library, and let it
import directory-streams directly from the (ikarus.io) library.
Why does this work but importing them from (ikarus) into an existing
library does not? I guess because the (ikarus) library is from the
pre-built boot file, but the (ikarus.io) library is from the new
version
being built?
Yes.
If that's true, I'm curious to know why the (ikarus) used
to resolve bindings for the new boot file can't be from the new
version
as well. I guess because all the bindings for the new (ikarus) aren't
yet known by the build process because it's still in the middle of
figuring them out?
The bindings of each library are listed explicitly in makefile.ss.
The build process does some sanity checks once all libraries are
expanded to ensure that all listed identifiers are actually defined
and that no exported identifier is defined twice, etc. There is
some magic that makefile.ss does to emit code responsible for
initializing the expander (i.e. constructing the libraries and
populating them with the proper bindings) in the next bootfile.
This new library should be included in the list of libraries after
(ikarus.io) otherwise, something wrong might happen (or not).
I think I already understand this "otherwise, something wrong might
happen (or not)" is because anything which uses values from some
library
needs those values to actually exist (otherwise segfaults have
happened
to me) so the used libraries must be instantiated first, but it's
possible the values don't actually get used even though some
library is
imported, which is why you say "(or not)". (?)
Yes. For example, the procedure assertion-violation (or die) is
not defined until later in the boot process, while there exist
some references to this procedure in files that are initialized
beforehand. So, as long as the variable's value is not used,
everything would be fine. So, you can reference the variable in
a procedure, but that procedure should not be called until the
variable is initialized. So, it works kinda optimistically:
assume that all variable exist, and start initializing them one
by one, and if something goes wrong (segfault), tough luck. The
converse is almost impossible; you cannot assume that nothing
exists and start building things from scratch. You have to
start somewhere, and I prefer to start with the whole set. :-)
Thanks, I've been wanting to better understand how Ikarus bootstraps.
Let me know if you have other questions.
Aziz,,,