Macros and internal schema definitions

A good question was asked on the Freenode #scheme channel. Consider the following code in the diagram:

(define alpha 1) (define-syntax foo (syntax-rules (quote alpha) ((_ alpha msg) (define bar 2)) ((_ other msg) (syntax-error msg)) ) ) (define (beta) (foo alpha "beta") (define alpha 3) 'beta ) (define (gamma) (define alpha 4) (foo alpha "gamma") 'gamma ) (define (delta alpha) (foo alpha "delta") 'delta ) 

Which of the beta , gamma and delta should cause syntax errors? What is there to do? I tested this with Chibi Scheme, where beta excellent, and gamma and delta fail. I wonder if this is the alleged behavior or just a bug in Chibi.

According to the standard, it seems that macro expansion should occur before internal definitions are rewritten in letrec* . So beta and gamma should crash, since foo will match internally defined alpha , not global.

However, the standard does not explicitly state how internal definitions work, only they can be considered as shortrec. I get the same behavior with the Racket R5RS, so it seems like I'm missing something in the standard requiring this behavior.

+5
source share
3 answers

OK, I finally understand your question. Running your code was tricky because you had a syntax error function that signals a syntax error only if it exits in fully extended code. Whatever.

I think the answer to your question is this:

These Schema guys (Dybvig, Felleisen, Hieb, Clinger, Rees, Wand, Flatt, Culpepper, etc.) are pretty smart!

In particular, somehow Scheme / Racket manages to figure out how the binding structure works, even if it does not know what it will bind or not. You're right! This is madness! But the algorithm described by Dybvig et al. does some very smart things to ensure that hygiene keeps track of whether identifiers are "identifier-peer" or "associated-identifier-peer" (Flata terminology), even if he does not yet know which one connects the other. I personally recommend reading Macros That Work Together (Flatt, Culpepper, Darais, Findler) to better understand this.

Sorry if I misunderstood your question, or if my tone is inappropriate!

+1
source

It may be too much depending on the implementation side, but this is due to the order in which the macros expand. Theoretically, all definitions contain alpha , so it should not coincide with one in literal keywords. However, macro decomposition must be performed before the define forms are expanded to letrec* , otherwise the compiler will not be able to correctly define the internal definition. Therefore, at that moment, the compiler may or may not see the bindings. (The scale of the macro extension is not specified on R7RS, so the implementation can also choose its own timing.)

In the case of beta compiler did not catch the binding, so the macro expander can still see that alpha is the same binding as the global one. Other cases are the opposite.

+1
source

First of all, delta absent (must not match alpha ) because it explicitly lexically binds alpha to a different binding than the one under which your sytnax-rules appears. Interesting are beta and gamma .

In accordance with section 5.2.2. R4RS (p. 13) and R5RS (p. 16), section 5.3.2. R7RS (p. 26) and section 11.3. R6RS (p. 32), the binding “region” set in the internal definition is the integer <body> in which the definition appears . And your macro call to foo clearly within the same <body> as those internal definitions.

R7RS also goes a little further and warns us:

Note that such a body [i.e. one that contains internal definitions] may not be obvious until another syntax is decrypted.

Thus, a spoiled order of events is allowed, but there is no ambiguity; your syntax-rules should not match the alpha branch if the binding for alpha by any internal definition is in the same <body> as the macro call. Therefore, beta and gamma also absent.

Appendix A

If we complicate things further, and your macro itself conditionally bound alpha , for example

 (syntax-rules (alpha) ((_ alpha x) (define alpha x))) 

then at first it seems that this seems ambiguous, but I believe that this is solved by the fact that the macro expander will rename a specific identifier alpha in accordance with hygiene, that is, we will not obscure alpha , which we are matching as a literal, so the coincidence is fine, and above it will just create a binding for the renamed alpha , inaccessible outside the macro body.

Appendix B

There is a limitation at the end of section 5.3. R5RS (p. 17), end of section 5.4. from R7RS (p. 26) and in the middle of section 10. to R6RS (p. 30), which mentions that the sequence of definitions should not contain a definition that changes the meaning of any of them (In fact, it’s a little more complicated, all three different wordings are used in the standard, but this should be a reasonable summary.)

In your example, it is not clear to me whether the probability that your syntax-rules expands to a syntax error is considered to mean "value". If you find this ambiguous, then your beta and gamma are “errors” (undefined behavior) according to R5RS and R7RS and “syntax violation” according to R6RS.

If your example contained another binding in the second branch of your syntax-rules (ideally this definition is the same for the same variable), then this nitpick will not be applied, so your question is worth it.

0
source

Source: https://habr.com/ru/post/1203263/


All Articles