Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

symbol '%find-macro-clause' unbound with users SRFI-8 #705

Open
Retropikzel opened this issue Dec 24, 2024 · 11 comments
Open

symbol '%find-macro-clause' unbound with users SRFI-8 #705

Retropikzel opened this issue Dec 24, 2024 · 11 comments

Comments

@Retropikzel
Copy link

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.

@jpellegrini
Copy link
Contributor

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?

@egallesio
Copy link
Owner

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.

egallesio added a commit that referenced this issue Jan 4, 2025
This instruction is accessible through the the special compiler form
    (%%symbol-value 'a 'STklos)
which will produce the following code
    000:  CONSTANT-PUSH        0
    002:  CONSTANT             1
    004:  SYMBOL-VALUE
    005:

    Constants:
    0: a
    1: STklos

This compiler form is used in `define-syntax` expansion which uses the
unexportded `find-clause` function defined in MBE module. In STklos modules,
this symbol is available through the symbol %find-macro-clause. However, in
pure R7RS libraries, this symbol is not available (as well as the find-module
function). The hack here consists to use %%symbol-value in the expandion of
define-syntax since it is always available even if not exported by any module.

NOTE: This special form can probaly be useful in other low level places where
we need to have an access to unexported symbols. Note that the current version
of %%symbol-value does not support the optional third parameter of
symbol-value.

This should correct the issue #705 signaled by @Retropikzel
egallesio added a commit that referenced this issue Jan 4, 2025
@egallesio
Copy link
Owner

Hi,

Last commit corrects this issue.

Happy new year.

@jpellegrini
Copy link
Contributor

@Retropikzel it seems that your original code now works! :)

@jpellegrini
Copy link
Contributor

@egallesio I'll review old libraries and SRFIs and see if we ca nremove some of the "(export %find-macro-clause)) from them.

@Retropikzel
Copy link
Author

Thank you very much! :)

@egallesio
Copy link
Owner

@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

@Retropikzel
Copy link
Author

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.

@jpellegrini
Copy link
Contributor

@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?

egallesio added a commit that referenced this issue Jan 8, 2025
The `guard` syntax used the following symbols (not available in pure R7RS
libs)
  - current-exception-handler
  - %continuable-exception?
  - %continuable-exception-value
@egallesio
Copy link
Owner

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.

@egallesio
Copy link
Owner

STklos answers 20, but it should be 10

Yes, this is a known problem (See #239 (comment)). I hope to change that in not so far future. For now, don't forget that let-syntax is a joke 🥲 .

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants