symbol '%find-macro-clause' unbound with users SRFI-8
main.scm:
(import (scheme base)
(scheme write)
(srfi 8))
(receive (a b) (values 1 2)
(begin
(display a)
(newline)
(display b)
(newline)))
srfi/8.sld:
(define-library (srfi 8) (import (scheme base)) (export receive) (include "8.scm"))
srfi/8.scm:
(define-syntax receive
(syntax-rules ()
((receive formals expression body ...)
(call-with-values (lambda () expression)
(lambda formals body ...)))))
stklos -I . main.scm gives error:
**** Error while executing command ("main.scm")
Where: in compile
Reason: symbol '%find-macro-clause' unbound in module 'stklos'
- >
- #[closure 7fa63a2f8f00]
- >
- compile
- #[closure 7fa63a2f8140]
- >
- #[closure 7fa63a2f80c0]
- %call-for-values
- >
- call-with-values
- ...
Set shell variable STKLOS_FRAMES to set visible frames
EXIT
If you comment out the srfi 8 import and copy the code directly to the file it works.
Hello @Retropikzel
Indeed. The %find-macro-clause procedure is inside module stklos, but libraries won't load it.
STklos module sdo automatically load the stklos module, so this:
(define-module
srfi/8
(import (scheme base))
(export receive)
(include "8.scm"))
works.
Of course, the library definition should work...
You can also (import stklos) in the library definition, it will then work.
The root of the problem seems to be issue #703 : local symbols which is used by exported syntax is not really exported. This seems to be what happened here...
@egallesio is this something easy to fix?
Hi @Retropikzel,
Thanks for signaling this issue. I will try to correct this rapidly (but not probably before next week).
@egallesio is this something easy to fix?
This particular issue is probably easy to correct, but I suppose it will be more difficult to have a correct behavior with the problem you exposed in #703. More on this soon, I hope.
Hi,
Last commit corrects this issue.
Happy new year.
@Retropikzel it seems that your original code now works! :)
@egallesio I'll review old libraries and SRFIs and see if we ca nremove some of the "(export %find-macro-clause)) from them.
Thank you very much! :)
@egallesio I'll review old libraries and SRFIs and see if we ca nremove some of the "
(export %find-macro-clause))from them.
Normally, there is no more occurrence of %find-macro-clause in the source tree. Thanks @jpellegrini
I think this might also be similar.
main.scm:
(import (scheme base)
(scheme write)
(foo))
(display "The value of bar is: ")
(display bar)
(newline)
foo.sld:
(define-library
(foo)
(import (scheme base))
(export bar)
(begin
(define bar
(guard (error
(else "bar"))
(vector-ref (vector) 100)))))
stklos main.scm:
**** Error while executing command ("main.scm")
Where: in %execute
Reason: symbol 'current-exception-handler' unbound in library (foo)
stklos -V git stuff:
(build.git.branch "master") (build.git.commit "834eae3")
Workaround foo.scm:
(define-library
(foo)
(import (scheme base))
(export bar)
(begin
(define bar
(call-with-current-continuation
(lambda (k)
(with-exception-handler
(lambda (x) (k "bar"))
(lambda () (vector-ref (vector) 100))))))))
I also tested foo.scm:
(define-library
(foo)
(import (scheme base))
(export bar)
(begin
(define bar
(with-exception-handler
(lambda (x) "bar")
(lambda () (vector-ref (vector) 100))))))
And got:
**** Error while executing command ("main.scm")
Where: in with-exception-handler
Reason: exception handler returned on non-continuable exception
I have no idea what the last one should do, but I thought I'd test it to be more thorough.
@egallesio I think this has to do with #410 . Macros are created but they do not remember the environment in which they are created -- this is why macros created in modules have such problem:
(let ((x 10))
(let-syntax ((a (syntax-rules () ((_) x))))
(let ((x 20))
(a))))
STklos answers 20, but it should be 10.
So when a macro is created inside a module, there is a similar problem. It doesn't remember the module definitions (which it should, without need for importing)...
If there was a way to get code compiled within a module, then it would be possible to get the macro system to remember the bindings (we'd just compile the macro in the proper module).
Or did I get something wrong?
I have applied a quick fix for this problem, but I'll need to modify the implementation of guard, since it's behavior with multiple values is incorrect.
About the code
(with-exception-handler
(lambda (x) "bar")
(lambda () (vector-ref (vector) 100)))
The error about an exception handler returned on non-continuable exception is normal. This is the R7RS expected behavior. In raise it is said that
If the handler returns, a secondary exception is raised in the same dynamic environment as the handler.
All the other scheme systems I have tested also detect an error in this case.
STklos answers 20, but it should be 10
Yes, this is a known problem (See https://github.com/egallesio/STklos/pull/239#issuecomment-1163217488). I hope to change that in not so far future. For now, don't forget that let-syntax is a joke :smiling_face_with_tear: .
If there was a way to get code compiled within a module, then it would be possible to get the macro system to remember the bindings (we'd just compile the macro in the proper module).
This is another problem. In fact, the complexity here comes from the fact that when we compile a file, which imports a library, we do not load at all the code of the library, since it can have undesirable side effects (displays, system interactions, ...) So the compiler reads the metadata of the .ostk file which contain the expander of the macro. If this expander uses some functions or non-exported macros, it cannot find them in the metadata. Things could be simpler, if we don't use compile-file, since imported code will be executed (but it would imply that we could have a different behavior depending on we use compile-file or not).
With pure R7RS libraries, we could imagine the loading of only the definitions parts of the library (that is, everything except the begin part) and rebuild the environment of the imported library. However, this is not OK with STklos modules, where definitions and code can be interleaved. For now, I have not an easy solution for this problem.
Hope that I was clear in my explanation.
This is another problem. In fact, the complexity here comes from the fact that when we compile a file, which imports a library, we do not load at all the code of the library, since it can have undesirable side effects (displays, system interactions, ...) So the compiler reads the metadata of the
.ostkfile which contain the expander of the macro. If this expander uses some functions or non-exported macros, it cannot find them in the metadata. Things could be simpler, if we don't usecompile-file, since imported code will be executed (but it would imply that we could have a different behavior depending on we usecompile-fileor not).
@egallesio I was thinking about this, and I would see three options:
- Disable I/O, disable external assignments (in fact, disable all side effects except assigning to variables in the module), load the module, and enable them again
- Disable I/O only (since the user would expect the assignments to work) while loading
- Just let all side-effects happen (principle of least surprise -- the user coded that, so the expectation is that those things will be executed...)
What do you think?
If there was a way to get code compiled within a module, then it would be possible to get the macro system to remember the bindings (we'd just compile the macro in the proper module).
This is another problem. In fact, the complexity here comes from the fact that when we compile a file, which imports a library, we do not load at all the code of the library, since it can have undesirable side effects (displays, system interactions, ...) So the compiler reads the metadata of the
.ostkfile which contain the expander of the macro. If this expander uses some functions or non-exported macros, it cannot find them in the metadata. Things could be simpler, if we don't usecompile-file, since imported code will be executed (but it would imply that we could have a different behavior depending on we usecompile-fileor not).With pure R7RS libraries, we could imagine the loading of only the definitions parts of the library (that is, everything except the
beginpart) and rebuild the environment of the imported library. However, this is not OK with STklos modules, where definitions and code can be interleaved. For now, I have not an easy solution for this problem.Hope that I was clear in my explanation.
Maybe the implementation of the idea in issue #754 would help with this?