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

2 ways to compile macros correctly

 From the discussion, it seems there are two major ways to implement
isolation of the compiler environment from the week-old running
environment so that the compiler doesn't side-effect the running
environment (assuming your operating system doesn't allow you to
simply create a second virtual machine identical to the original but
with copy-on-write):
 (1) You can implement copy-on-write at the LISP level, if you have
  tree-structured packages or can fake the same out by long names of packages.
 (2) You can install all compiler side-effects as unusual properties
  instead of the usual properties.

To implement (1), when you start a compilation you make a complete
copy of all the packages in the current environment, origined from
some lower level instead of the top level of the package-tree, except
you don't actualy copy the packages (hashtables) you merely set up an
indirect vector that is copy-on-write, so the first time you actually
modify any package that hashtable gets copied but the ones you haven't
modified don't need to get copied at all. If you implement hashtables
as balanced binary trees instead of as linear arrays, you only have
to copy the log(N) path down to the change rather than en masse the
whole contiguous hash array.

To implement (2) (Moon's suggestion I believe), whenever a macro
definition is compiled, you store it as a CMACRO instead of a normal
MACRO, whenever a global SETQ occurs, you use the CVALUE property
instead of the VALUE cell, likewise for CFUNCTION property instead of
FUNCTION cell, CDEFSTRUCT instead of DEFSTRUCT, etc. etc.  When the
compiler is looking for the definition of a macro or auxilary function
needed for macro etc. it looks first for the C... which overrides the
normal definition if both are present. Meanwhile the compiler innerds
continues to use the normal definitions and totally ignore he C...
stuff, so none of the C... stuff can break the compiler itself.

CLtL should specify the semantics, namely that (1) the compiled-file
environment should be initialized to the current running environment
unless that is overridden (virgin LISP wanted instead for example),
(2) side-effects due to compiling definitions and SETQs etc. should
afect only the compiled-file environment not the compiler-innerds =
current-running-LISP environment, (3) when done with a batch of
compilations the compiled-file environment should be discarded unless
for some reason the operator wants it kept around for later use
compiling more files or debugging etc. -- The method of implementation
should be up to the compiler writer, with the above two methods (and
spawn extra process on Unix or other multi-virtual-machine systems as
a third method) merely suggested as ways it can done.

Alternately the above can be summarized by two postulates, (1) as it
says now, later loading the compiled file should have the same
semantics as later loading it interpreted, (2) anything needed to make
(1) work shouldn't modify the current running environment (in which
the compiler itself runs) in any way even temporarily except of course
for consuming memory and time.

(Opinion of REM)