thunk libraries
Matthias Radestock <[email protected]>
| Newsgroups | gmane.comp.java.sisc.devel |
|---|---|
| Message-ID | <[email protected]> |
The current mechanism of compiling modules into loadable libraries has
one major drawback: The code in the module is executed when the module
gets defined but not when the module is loaded from the library. Thus
defining a module and loading a module can have different results. This
really only matters if the module body performs actions that depend on
state outside the module or modifies state outside the module.
Unfortunately adding methods to generic procedures imported from other
modules is such a state-modifying action and is very common inside
module bodies.
The solution I came up with is to have a new kind of library, a "thunk
library". Thunk libraries contain exactly one thunk that gets executed
when the library is loaded. Modules and the code to load any libraries
they depend on can be compiled into thunks in thunk libraries.
I propose the introduction of a syntactic form, define-library, for
creating libraries from modules. The form is an extension of the module
form. Executing it defines a module but also creates a thunk as
described above. Thunks can be placed into libraries with a new function
create-library-from-thunk. Loading such a library has *exactly* the same
effect as evaluating the define-library form.
(define-library (<name> <req-lib> ...)
(<export> ...)
. <body>)
==>
(let ([env (sisc-initial-environment)])
;;In order to ensure that libraries do not accidentally rely on
;;bindings in the current interaction environment we compile
;;libraries in a fresh environment that only contains the initial
;;sisc bindings.
;;
;;We load any required libraries into our compilation environment so
;;that macro expansion can use them. In order to achieve the degree
;;of isolation we are aiming for, the compilation environment must
;;not see libraries loaded in the interaction environment and vice
;;versa; ATM it's not obvious how this could be accomplished.
(eval '(begin (clear-libraries)
(require-library (symbol->string <req-lib>)) ...) env)
;;COMPILE is meant to expand, optimize and compile the given
;;expression in the given environment, returning a thunk that when
;;invoked executes the compiled code. This is different from the
;;current behaviour
(let ([res (compile
'(begin (require-library (symbol->string <req-lib>))
...
(module <name> (<export> ...) . <body>))
env)])
;;"Manually" load the newly created library into the interaction
;;environment. This will establish a syntax binding for <name>.
(res)
;;record the fact that we have loaded the library and also
;;register the thunk so that we can get hold of it later
(provide-thunk-library (symbol->string '<name>) res)))
;;create a "thunk library" from a thunk. The thunk in a thunk library
;;gets executed when the library is loaded.
(create-library-from-thunk (library-thunk "<name>")
"some-path/some-file.slt")
;;Example
(define-library (sisc/lib/srfi/srfi-1 sisc/lib/r5rs
sisc/lib/srfi/optional-args
sisc/lib/srfi/srfi-8)
(cons list xcons ...)
(import* sisc/lib/r5rs for-each cons pair? null? ...)
(import sisc/lib/srfi/optional-args)
(import sisc/lib/srfi/srfi-8)
(include "srfi-1.scm")
(add-feature 'srfi-1))
(create-library-from-thunk (library-thunk "sisc/lib/srfi/srfi-1-lib")
"/tmp/build/sisc/lib/srfi/srfi-1.slt")
I'm wondering whether the above or some alternative solution would
benefit from any of the new features introduced in the latest version
psyntax.
Matthias.
-------------------------------------------------------
This SF.net email is sponsored by: ObjectStore.
If flattening out C++ or Java code to make your application fit in a
relational database is painful, don't do it! Check out ObjectStore.
Now part of Progress Software. http://www.objectstore.net/sourceforge