[plt-scheme] Questions about modules in embedded system
At Thu, 7 Oct 2004 14:00:55 -0400, Geoff Schmidt wrote:
> Question one: [...]
> 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?
I can't think of a better way.
> 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.
To me, it seems easier to have a C-based function that accepts a Scheme
object and registers it --- much like your answer to question one.
But if you want to get bindings from the namespace, I suggesting using
`eval' (via scheme_eval_string(), for example).
> Question three: How can I (from C) set! the value of a variable bound
> to X in (lib ("frontend.ss" "app"))? [...] Do I need
> to use scheme_module_bucket and change a field of the bucket returned?
For the reasons that you've pointed out (finding the right module,
etc.) and more, I wouldn't try to do that.
> 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.
Sounds reasonable to me.
> 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?
Yes. That's pretty much how mzc --exe works.
The code below (for v299) is somewhat different, but it's something I
have readily available. It copies files out of the "collects" tree into
the current directory, keeping the "collects" directory structure in
the copy. Going from this code to a single file is not too difficult, I
think.
> And what does the --embedded option to mzc do?
Not what you want. It's for compiling separate modules that will be
combined into a single DLL.
Matthew
----------------------------------------
(require (lib "moddep.ss" "syntax"))
(define (copy mod-path rel-to)
(let ([path (if (module-path-index? mod-path)
(resolve-module-path-index mod-path rel-to)
(resolve-module-path mod-path rel-to))])
(let ([target
(let-values ([(base name dir?) (split-path path)])
(let ([dest-dir
;; Figure out where path is relative to "collects",
;; and generate directories to the file.
(let loop ([path base])
(let-values ([(base name dir?) (split-path path)])
(if (string=? (path->string name) "collects")
(current-directory)
(let ([dest (loop base)])
(let ([next (build-path dest name)])
(unless (directory-exists? next)
(make-directory next))
next)))))])
(build-path dest-dir name)))])
;; Copy the module file, then recur over imports
(printf "Copying ~a to ~a~n" path target)
(when (file-exists? target)
(delete-file target))
(copy-file path target)
(let ([code (get-module-code path "no-such-dir")])
(let-values ([(a b c) (module-compiled-imports code)])
(map (lambda (x)
(unless (symbol? x)
(copy x path)))
(append a b c)))))))
(copy '(lib "class.ss") (current-directory))