-
-
Notifications
You must be signed in to change notification settings - Fork 81
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
Problem with syntax-rules expander? #532
Comments
I've seen something similar to that related to |
Ah, I see. We unwrap identifiers to make field names (in If we also unwrap the constructor arguments, it works in in this example, but it becomes unhygienic and will fail on more complex cases. My idea is to replace them with gensym-ed names. |
I have a question. define-record-type has a function which generates accessor names automatically. So, I think hygienic macro (syntax-rules) can't realize define-record-type. In above case, if |
Hayamaya: Yes, automatic generation of names do not work well with hygiene. |
I'm totally ok with keeping the current behavior as-is since it's undefined. Although if someone has a hack to get it work, I'd appreciate it. I'm trying to run srfi-159 code from chibi, then remove chibi sepcific bits to make gauche support (scheme show). |
Let's keep this open until we find a reasonable solution (either fix it or wontfix). |
Never mind. Found it :D srfi-159 here I come! |
Actually in this case, after staring some more at (chibi monad environment), get-props and set-props! are only used inside the syntax-rules block, not exposed to outside. So however they are renamed internally, it should still work because all references are also renamed consistently. |
Well, I realized there' a simple bug. Could you try this fix? It's only a missing quote.
|
Yes that fixed it! I'm seeing another problem with syntax-rules, but unlikely related to records. I'll open another one if I can reduce the problem to some small example. |
Quote strips syntactic information. As far as we follow srfi-99's syntactic/procedural layer design, we have to quote field descriptions to pass to procedural layer, so it should be the right thing. |
I can't wrap my head around this, and attempting to create a smaller example did not work out so well. So if anyone's interested, if you checkout https://github.com/pclouds/Gauche/commits/sigh and run
The "tell" is an internal macro defined by define-environment-monad in lib/chibi/show/base.scm. Now if you uncomment the these two in base.scm
which gives the "tell" and "ask" macros public names, the problem is gone. All I could tell is it starts from
and gets to this part (in enviroment.scm)
This is NOT a problem for my work on porting srfi-159 because I removed this monad macro anyway (and probably will replace it with srfi-165). This is just in case it shows a bug in syntax-rules |
There's definitely something wrong with macro expansion. I've updated 'sigh' branch to pprint the expansion. The gist of this is nested macros ('u' aka 'with!' calling 'tell' macro, which should expands to '%tell' function; both 'tell' and '%tell' should be renamed) that are all defined by the top level macro define-monad-environment. A simple example shows that all macros are expanded normally. However, pprint the macro expansion of 'with!' shows this
"tell" is still here (and it does not look renamed either) while it should have been expanded down to '%tell'. This is probably why 'tell' is considered unbounded when executed. |
There's a hidden feature that dumps input and output of each macro expansion. It could provide some clue. Evaluate the following:
(I just found you have to autoload pprint first to make it work---just evaluate |
Shiro oh Shiro! Had I known about It did not help much though, for some reason Gauche stopped expanding at This is the last step
only when I give
|
I've totally forgotten about |
The environment monad in chibi is created by a macro provided by '(chibi environment monad)' but that macro does not work in Gauche. Problem with rtd-constructor, do manual expansion (see shirok#532). Avoid that macro by providing the expanded version of the monad. In the future this code is probably replaced with srfi-165.
The environment monad in chibi is created by a macro provided by '(chibi environment monad)' but that macro does not work in Gauche. Problem with rtd-constructor, do manual expansion (see shirok#532). Avoid that macro by providing the expanded version of the monad. In the future this code is probably replaced with srfi-165.
I looked at this again after srfi-159 has been merged. Even after replacing monad.scm (the expanded version) with define-monad-environment from chibi (i.e. the original version), the problem was gone, all tests passed. So syntax-rules looked innocent. However, that was the macro defintion and macro expansion in the same .scm file. If I move the define-monad-environment macro to a separate library, problems reappear. Plenty of srfi-159 tests failed with "unbound variable: #<identifier ...>". So it probably has something to do with exporting symbols (or identifiers or whatever that is) not with hygienic renaming business. Changes are in my "sigh" branch. The top commit is bad, the one before that good. |
The problem is "fixed" by moving the wrapper macro outside the library. Before pclouds@0b3ddbe
and after it
|
Small example to demonstrate. This yyy.scm works (import (scheme base) (scheme write))
(define-syntax x1
(syntax-rules ()
((x1 y1)
(x2 x3 y1))))
(define-syntax x2
(syntax-rules ()
((x2 x3 y1)
(begin
(define-syntax x3
(syntax-rules ()
((x3 x4) x4)))
(define-syntax y1
(syntax-rules ()
((y1 y2) (x3 y2))))))))
(x1 bar)
(write (bar 1)) while this yyy.scm does not (import (scheme base) (scheme write) (xxx))
(x1 bar)
(write (bar 1)) the xxx.scm contains the same part from the first yyy.scm (define-library (xxx)
(export x1)
(import (scheme base))
(begin
(define-syntax x1
(syntax-rules ()
((x1 y1)
(x2 x3 y1))))
(define-syntax x2
(syntax-rules ()
((x2 x3 y1)
(begin
(define-syntax x3
(syntax-rules ()
((x3 x4) x4)))
(define-syntax y1
(syntax-rules ()
((y1 y2) (x3 y2)))))))))) |
I changed yyy1.scm and yyy2.scm as follows. yyy1.scm
yyy2.scm
Then, the result is as follows.
So, in the latter case, x1 and x3 is in the different modules. This might be a something hint but I don't know this is bug or spec ... |
I didn't know apropos could be used this way, thanks! I don't know if it's bug or spec either but it worked with at least sagittarius and chibi (didn't try more schemes) |
It's a bit clearer with
All the expansions look ok, except that x3.0 is not bounded... |
If we make x3 a procedure instead of a macro, then it works. Sounds to me like nested define-syntax should be exported the same way as define? (define-library (xxx)
(export x1)
(import (scheme base))
(begin
(define-syntax x1
(syntax-rules ()
((x1 y1)
(x2 x3 y1))))
(define x2
(syntax-rules ()
((x2 x3 y1)
(begin
(define (x3 x4) x4)
(define-syntax y1
(syntax-rules ()
((y1 y2) (x3 y2)))))))))) Output with trace-macro on. It's interesting that the last line is x3.139.0 (renamed again, or?)
|
may be related to #328 |
This seems like a hygiene problem. x3 macro is not renamed when defined in r7rs.user, but it's called renamed by y1 macro. yyy3.scm works even though (I think) it should not (import (scheme base) (scheme write) (xxx))
(x1 bar)
;(write (bar 1)) ==> expanding to (x3 1)
(write (x3 1))
(newline) |
This fixes the problem here (and still passes the test suite) but I'm too green in this area to even judge if I'm going the right direction. @shirok if you have time please have a look, greatly appreciated. What I'm trying to do here is instead of registering the nested macro (x3) in the expanded context (yyy.scm) I try to keep the macro in macro-definition environment (xxx.scm) instead because other macros in the same level (e.g. y1) will refer to it that way. I try to use the same rename trick in pass1/define to hopefully not mess everything else up. One thing I'm sure could go wrong is how to detect this case, wrapped-identifier? works here but it's probably too loose. diff --git a/src/compile-1.scm b/src/compile-1.scm
index 19865a439..cd35f0802 100644
--- a/src/compile-1.scm
+++ b/src/compile-1.scm
@@ -711,23 +711,29 @@
($const-undef)))
(define-pass1-syntax (define-syntax form cenv) :null
(check-toplevel form cenv)
;; Temporary: we use the old compiler's syntax-rules implementation
;; for the time being.
(match form
[(_ name expr)
(let* ([cenv (cenv-add-name cenv (variable-name name))]
[transformer (pass1/eval-macro-rhs 'define-syntax expr cenv)])
- ;; See the "Hygiene alert" in pass1/define.
- (%insert-syntax-binding (cenv-module cenv) (unwrap-syntax name)
- transformer)
+ (if (wrapped-identifier? name)
+ (begin
+ (%rename-toplevel-identifier! name)
+ (%insert-syntax-binding (identifier-module name)
+ (unwrap-syntax name)
+ transformer))
+ ;; See the "Hygiene alert" in pass1/define.
+ (%insert-syntax-binding (cenv-module cenv) (unwrap-syntax name)
+ transformer))
($const-undef))]
[_ (error "syntax-error: malformed define-syntax:" form)]))
;; Experimental
(define-pass1-syntax (define-hybrid-syntax form cenv) :gauche
(pass1-define-hybrid-syntax form cenv))
(define-pass1-syntax (define-inline/syntax form cenv) :gauche ;deprecated
(pass1-define-hybrid-syntax form cenv))
(define (pass1-define-hybrid-syntax form cenv) |
Your fix does make sense, though I need to look more closely. |
Ok, the problem is certainly |
Does 28f229a address the original issue? |
Works beautifully. Thanks! An immediate effect of this is gauche users can now use |
Thanks for your work to identify the problem. |
Great work! |
Aha. And the "fix" of that particular case 0f85b90 is pretty much the same as the fix of this one. The old fix didn't involve cross-module reference, and back then modification of pass1/define fixed that particular issue, but we should've done the same thing for define-syntax and define-macro. |
This is a simplified code from '(chibi monad environment)'
The expansion should be something like this, which I tested was working
(define-record-type foo (make-state port output %props) state? (port env-port env-port-set!) (output env-output env-output-set!) (%props get-props set-props!))
But instead I got
Not sure what was the problem (might as well be me...)
The text was updated successfully, but these errors were encountered: