Open swatson555 opened 2 years ago
Can you give an example of what you mean? See https://cisco.github.io/ChezScheme/csug9.5/system.html#./system:s38 for details on Chez Scheme's eval
function that takes an optional environment argument.
This is what happens when trying to build a boot file:
This isn't the same error I've had working with Chez. The error I've encountered is eval
will throw an unbound variable exception. This is how I'm building:
(generate-wpo-files #t)
(compile-imported-libraries #t)
(compile-program "hello.ss")
(compile-whole-program "hello.wpo" "hello.cwp")
(strip-fasl-file "hello.cwp" "hello.cwp"
(fasl-strip-options inspector-source
source-annotations
profile-source))
(make-boot-file "hello.boot" '("scheme" "petite") "hello.cwp")
Try adding (expand '(import (n)))
to hello.ss before calling eval
. This will load the compile-time information for library (n).
If you do (eval '(import (n))
, then the variable binding will be available in the interaction environment, and you can use (eval 'var)
.
I tried expand
but eval
still can't find the library. I'm not sure under what conditions eval
will throw an exception but, I think I still have code that will produce this in Chez in my archive and, if I can find it I'll try to see how I did that.
There's also Chez specific procedures for working with env
which also share similar problems. https://cisco.github.io/ChezScheme/csug9.5/binding.html#./binding:h5
I had a look at the code that produced the unbound variable exception and, it doesn't do this in newer versions of Chez. It gives a similar "library not found" exception.
Would you please zip up all the files you've used to demonstrate the trouble and attach to this issue so that I can reproduce the behavior?
This zip file contains the build script, test program source, and library source.
Thanks for sharing the zip @swatson555, there are actually a few issues you're running into here.
compile-whole-program
does not preserve the library entry points like (n)
unless you specify libs-visible?
as #t
in the (compile-whole-program input-filename output-filename libs-visible?)
version of the call. Generally, this information is not needed at run time, unless you want to use the library explicitly in eval
(as in your example) or environment
. You can read more about that in Section 12.4 of the Chez Scheme User's Guide.hello.ss
is compiled, (n)
is not identified as a dependency because it is not imported and nothing in the library is referenced. You can see this actually, when you run build.ss
because it never even tries to compile (n)
when compile-program
is invoked, even though the compile-imported-libraries
parameter is set to #t
. When the output is executed the eval
will cause scheme to look for your library (and compile it if necessary, which in this case it is). You can see this by enabling import-notify
and using load-program
to load the hello.cwp
program file:
% scheme
Chez Scheme Version 9.5.5
Copyright 1984-2020 Cisco Systems, Inc.
(import-notify #t) (load-program "hello.cwp") import: did not find source file "n.chezscheme.sls" import: did not find source file "n.ss" import: did not find source file "n.sls" import: did not find source file "n.scm" import: did not find source file "n.sch" import: did not find object file "n.chezscheme.so" import: did not find object file "n.so" Exception in environment: library (n) not found Type (debug) to enter the debugger.
If we extend the `library-directories` to include `lib`, it will find the file, and run the program correctly (though not the boot file---perhaps @burgerrg has some insight on that part). ```scheme [akeep@hawkeye hello-2]% scheme Chez Scheme Version 9.5.5 Copyright 1984-2020 Cisco Systems, Inc. (import-notify #t) (library-directories (cons "lib" (library-directories))) (load-program "hello.cwp") import: did not find source file "lib/n.chezscheme.sls" import: did not find source file "lib/n.ss" import: found source file "lib/n.sls" import: did not find corresponding object file "lib/n.so" import: loading source file "lib/n.sls" Hello, World!
- Even if
(n)
were imported, thehello.ss
program would not record that(n)
is necessary for it building, because only code that is compiled is used to determine the imports, and the code ineval
is not evaluated until run time.
So, here are a few changes that can build a hello.boot
that will contain (n)
(recognizing that this is a little different from your original intention).
Changes to hello.ss
(comments inline):
(import (chezscheme) (n)) ;; 1. add the import for (n)
(define foo var) ;; 2. reference something from (n)
(display
(eval 'var (environment '(n))))
(newline)
and changes to build.ss
(comments inline):
#!/usr/bin/env scheme --script
(generate-wpo-files #t)
(compile-imported-libraries #t)
(library-directories (cons "lib" (library-directories))) ;; 1. add the "lib" directory to library-directories
(compile-program "hello.ss")
(compile-whole-program "hello.wpo" "hello.cwp" #t) ;; 2. add the _libs-visible?_ #t argument.
(strip-fasl-file "hello.cwp" "hello.cwp"
(fasl-strip-options inspector-source
source-annotations
profile-source))
(make-boot-file "hello.boot" '("scheme" "petite") "hello.cwp")
With these changes, I was able to get the following to work:
% ./build.ss
compiling hello.ss with output to hello.so
compiling lib/n.sls with output to lib/n.so
[akeep@hawkeye hello]% scheme --boot hello.boot
Hello, World!
Chez Scheme Version 9.5.5
Copyright 1984-2020 Cisco Systems, Inc.
>
Incidentally, Chez cannot compile the arguments to eval
or environment
in general because they can be constructed at run time.
This isn't viable work around because in the case where the name var
exists in the current environment the compiler will throw an exception that there are multiple definitions of the same name.
Fortunately, naming is an easy problem to work around because R6RS allows you to rename and limit imports, so you can do something like:
(import (chezscheme) (rename (only (n) var) (var something-else)))
(define foo something-else)
And if this is being generated as the output of a macro something-else
could just be a gensym (actually you could even generate a gensym and use that directly:
% scheme
Chez Scheme Version 9.5.5
Copyright 1984-2020 Cisco Systems, Inc.
> (gensym)
#{g0 mpf482drvcnazscbdytjja3wj-0}
Then rewrite to:
#!chezscheme
(import (chezscheme) (rename (only (n) var) (var #{g0 mpf482drvcnazscbdytjja3wj-
(define foo #{g0 mpf482drvcnazscbdytjja3wj-0})
The #!chezscheme
is necessary to inform the reader to accept extended Chez Scheme syntax.
However, it is worth noting that you are not really getting any benefit from compile-whole-program
with regards to the (n)
library, since, compile-whole-program
cannot inline a library you are not really using. (In your use case, if you have libraries you are using directly, you will still get the benefits of those of course.)
Since you are building a boot file, you can simply include other libraries with the program. The way to do this is to compile lib/n.sls
separately (since compiling hello.ss
will not cause it to be compiled otherwise), and then include it in the boot file call:
#!/usr/bin/env scheme --script
(generate-wpo-files #t)
(compile-imported-libraries #t)
(compile-program "hello.ss")
(compile-whole-program "hello.wpo" "hello.cwp")
(compile-library "lib/n.sls" "lib/n.so") ;; 1. compile any additional libraries
(strip-fasl-file "hello.cwp" "hello.cwp"
(fasl-strip-options inspector-source
source-annotations
profile-source))
;; 2. add the libraries before the program, so that they will be loaded and available in the boot file.
(make-boot-file "hello.boot" '("scheme" "petite") "lib/n.so" "hello.cwp")
This approach will work without needing to change the hello.ss
code.
Evaluating variables in a different environment only works in interpreter mode. Compiled code can't evaluate variables in a different environment using
eval
.