[plt-scheme] Questions about modules in embedded system

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Oct 7 15:54:10 EDT 2004

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

> 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.



(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")
			    (let ([dest (loop base)])
			      (let ([next (build-path dest name)])
				(unless (directory-exists? next)
				  (make-directory 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))

Posted on the users mailing list.