[plt-scheme] Questions about modules in embedded system

From: Geoff Schmidt (gschmidt at mit.edu)
Date: Thu Oct 7 14:00:55 EDT 2004

I am trying to embed PLT Scheme in an OS X program, so I can write the 
guts of my application in portable Scheme and do the GUI frontend using 
native OS X tools. I want to abstract the GUI frontend (the view and 
controller) from the scheme backend (the model) as cleanly as possible, 
to make it easier to write new frontends for other platforms. I am 
having some trouble understanding the module system.

My plan was to keep the Scheme guts in a private collects tree shipped 
with the application, with a module called "backend" that provides all 
of the definitions that the GUI uses. Then, I wanted to have a second 
module "frontend" defined by the GUI that provides all of the 
definitions used by Scheme code to manipulate the GUI.

Question one: Some of the primitives in "frontend" close over GUI 
object handles that aren't known until fairly late in the GUI's life 
(awakeFromNib:). Moreover, they are registered in many different 
places, from the constructors of the GUI objects they close over. But 
primitive modules must be completely defined 
(scheme_finish_primitive_module) before they can be used, and anyway, 
the compiler needs a definitive list of "frontend" exports at build 
time. My workaround is to define a regular module called "frontend" in 
the collects tree, with a bunch of lines like (define entry1 
entry-unbound) that reserve a slot for every primitive that might get 
loaded, and have the GUI fill in these slots as objects are 
constructed. Is there a better way to register primitives for the 
Scheme code to call, when the primitives and the objects they close 
over aren't all known before the Scheme code starts running?

Question two: Given that (require (lib "backend.ss" "app")) has been 
called in the initial namespace, how do I (from C) get the value of an 
symbol X such as eval would do when evaluating (f x)? 
scheme_lookup_global doesn't seem to work for imports -- because it 
only searches the binding list, not the import list? I need to do this 
to resolve the actual entrypoints so I can apply() them.

Question three: How can I (from C) set! the value of a variable bound 
to X in (lib ("frontend.ss" "app"))? My current workaround is to expose 
a function (through "backend") that is defined in "frontend" which 
takes the variable X to set in "frontend" and its new value. Do I need 
to use scheme_module_bucket and change a field of the bucket returned? 
How do I get the first argument to scheme_module_bucket? My best guess 
is that it's a symbol that is listed in the "module registry" as 
mapping to a module declaration (the result of compiling (module ..)?) 
-- and then this is mapped to a module instance somehow? Would this 
symbol be 'frontend? Then how is the module registry managed to avoid 
conflicts between (lib "foo.ss" "111") and (lib "foo.ss" "222")? I am 
thinking that current-module-name-prefix is involved but I can't quite 
work out how it works.

Also: when distributing an application such as this, you'd like to ship 
a self-contained system (no system collects tree required) but you'd 
like to minimize the size of your program. Is there an easy way to 
figure out what parts of the system collections are used by your code, 
so you can ship only those? If I wrote a script to do so, say by 
walking the module tree, any reason I couldn't just concatenate all of 
the referenced source files in load order and compile them into a 
single .zo and (load) that -- assuming I transformed the names to not 
collide, and wrote a custom module name resolver to map (lib ...) into 
a transformed name?

And what does the --embedded option to mzc do? I can't find it in the 
documentation.

Thanks for the great software, and thanks in advance for any help --
Geoff Schmidt



Posted on the users mailing list.