[plt-scheme] namespace-attach-module
At Sun, 04 Feb 2007 23:52:06 +0100, Jakub Piotr Cłapa wrote:
> I'm trying to load an external file and execute it in the namespace of a
> required module as a means of UI for my simple commandline app.
>
> I'm doing something like this:
>
> (module avrp mzscheme
> (require "avr-isp.scm")
>
> (open-isp-device)
>
> (with-handlers ([exn:fail:user? (lambda (exn)
> (send-request 'disconnect)
> (printf "~A~n" (exn-message exn)))])
>
> (let ([new-ns (make-namespace)])
> (define (module-path->symbol module-path)
> ((current-module-name-resolver) module-path 'avr-isp #f #f))
>
> (namespace-attach-module (current-namespace) (module-path->symbol
> "avr-isp.scm") new-ns)
> (parameterize ([current-namespace new-ns])
> (namespace-require '(file "avr-isp.scm"))
> (load "script.avrp")))
> )
> )
>
> And it works (also with different combinations of parameters to the
> resolver or even without the resolver) in
>
> mzscheme -tvm- avrp.scm
But it only works when you're in the same directory as "avrp.scm", right?
If you run
% mkdir tmp
% cd tmp
% mzscheme -tvm- ../arvp.scm
you'll get an error.
The `mzc --exe' result is essentially the same problem. Even when you
run the generated executable in the same directory as the source, the
modules are embedded by `mzc --exe' into a kind of parallel filesystem.
When you call the module name resolver, "avr-isp.scm" doesn't refer to
that parallel filesystem.
The second argument to the module name resolver lets you specify
"avr-isp.scm" relative to some other module. For that argument, you
want a reference to the enclosing module's (run-time) name. One way to
get that name is to use `syntax-source-module' on a quoted syntax
constant within the module; then you have to recur on the result, in
case the result is relative to some other path... see below. Yes, there
should be a nicer way to do this.
Matthew
----------------------------------------
(module avrp mzscheme
(require "avr-isp.scm")
(with-handlers ([exn:fail:user? (lambda (exn)
(printf "~A~n" (exn-message exn)))])
(let ([new-ns (make-namespace)])
(define (module-path->symbol module-path)
((current-module-name-resolver)
module-path
(let loop ([m (syntax-source-module #'here)])
(if (symbol? m)
m
(let-values ([(name base) (module-path-index-split m)])
((current-module-name-resolver)
name
(if base (loop base) #f)
#f))))
#f #f))
(let ([name (module-path->symbol "avr-isp.scm")])
(namespace-attach-module (current-namespace)
name
new-ns)
(parameterize ([current-namespace new-ns])
(namespace-require name)
(load "script.avrp"))))
))