ashinn / chibi-scheme

Official chibi-scheme repository
Other
1.21k stars 141 forks source link

Implement SRFI 139: Syntax Parameters #383

Closed mnieper closed 7 years ago

mnieper commented 7 years ago

Rationale: One cannot write a portable library to implement syntax parameters so support by the core system is needed.

ashinn commented 7 years ago

Out of curiosity, what do you want this for?

johnwcowan commented 7 years ago

From the Guile manual:

Syntax parameters (http://barzilay.org/misc/stxparam.pdf) are a mechanism for rebinding a macro definition within the dynamic extent of a macro expansion. This provides a convenient solution to one of the most common types of unhygienic macro: those that introduce a unhygienic binding each time the macro is used. Examples include a lambda form with a return keyword, or class macros that introduce a special self binding.

With syntax parameters, instead of introducing the binding unhygienically each time, we instead create one binding for the keyword, which we can then adjust later when we want the keyword to have a different meaning. As no new bindings are introduced, hygiene is preserved. This is similar to the dynamic binding mechanisms we have at run-time (see parameters), except that the dynamic binding only occurs during macro expansion. The code after macro expansion remains lexically scoped.

ashinn commented 7 years ago

Sure, I know what they are. I meant, what do you as a user of chibi want to do with syntax parameters?

After adhering to R7RS, I still try to keep Chibi as small as possible, and need evidence and usually multiple requests before adding new features.

mnieper commented 7 years ago

Chibi already implements a superset of R7RS, so adding a feature to Chibi that does not result in code bloat still seems to be in line with Chibi's philosophy. I have the impression that adding syntax-parameters would need something in the order of 50 lines of code, so wouldn't change the code size of Chibi notably. (Had I asked to add, say, syntax-case to Chibi, I think I would need much more compelling wherefores.)

Now to use cases (roughly from less to more compelling) that I have in mind should syntax parameters become available.

1) Being able to implement a lambda form with a "return" keyword (instead of using verbose code using call/cc explicitly) or to implement loops with "break" and "continue" keywords is simply nice to have. (How often do you make up non-descriptive names of your inner loops, say "lp", "loop", "loop1", because you have no "continue".)

2) The syntax of some more complicated macros can be simplified. Imagine a pattern matcher which uses a =>-syntax to bind a failure procedure. Had I syntax parameters, I would have a "fail" keyword. Should I need the failure procedure, I could still get it via (lambda () (fail)).

3) If I want to have a similar failure procedure in the case of the cond- or case-keyword, I can either change the syntax of these built-ins so that a failure procedure can be bound (as with the =>-syntax of the pattern matcher defined above), but this change should be compatible with the R7RS syntax of case or cond, or, if I had syntax parameters, I could simply use the form (fail).

4) The same is true for an improved let so that it gets the powers of and-let (and more). With syntax parameters, I can add a keyword, say abort, that I can use in the let-bindings such that when used, further let-bindings are not processed, but let* returns false.

5) Syntax parameters can be used to emulate some parts for what library parameters (that we are discussing elsewhere) can be used.

6) Take a general pattern matcher (like (chibi match)) that you want to use to process an expression in an er-macro-transformer. Things are complicated because forms may be wrapped in syntactic closures. It would be nice if the pattern matcher could automatically unwrap the syntactic closures while matching. A general pattern matcher would need an extra parameter, say maybe-unwrap, that it applies while matching. How can a user specify such a parameter? Either as a parameter in the sense of SRFI 39 (slow and with wrong scoping (dynamic, not lexical)), as an explicit argument to match (so the interfaces to match, match-let, match-let, match-lambda, match-lambda have all to be changed) or as an implicit syntax parameter (so the syntax of match, match-let, ... can be left untouched).

7) Say, I would like to extend quasiquote to allow ellipses. For example, ((x ,a) ...) should evaluate to ((x 1) (x 2) (x 3)) if a evaluates to (1 2 3). Such an extension is incompatible to quasiquote from (scheme base) because ... is interpreted differently. I could either name the extension quasiquote*, but this would not let me use the special-syntax, or I could use a syntax parameter, say quasiquote-ellipsis, that I can locally bind to an identifier that takes the role of the ellipsis. (Initially, it is bound to a secret identifier, so that the resulting extended quasiquote is compatible with quasiquote from (scheme base).) Similar parameterizations of quote or quasiquote are possible in conjunction with SRFI 116, so that immutable lists are produced, etc.

Finally, I can hardly imagine that syntax parameters (with their use cases above) become a mainstream feature of Scheme if only the few systems that are going to support R7RS-large and more will provide it. But without being able to use syntax parameters in the most important implementations, proposals like a syntactic version of make-coroutine-generator where yield is automatically bound have no chance.

mnieper commented 7 years ago

One more use case: (chibi match) uses quasiquote as auxiliary syntax. If I want to use a custom version of quasiquote in the bodies of each match clause, the best I can do is the following:

(import (rename (custom quasiquote) (quasiquote custom-quasiquote)))
...
(match x
  (`(1 ,b ,c)
   (let-syntax ((quasiquote (syntax-rules () ((_ form) (custom-quasiquote form)))))
     body1 body2 ...))
  ...)

Now if syntax parameters were supported, one could patch (chibi match) so that it defines a syntax-parameter that allows to customize the auxiliary syntax it uses. E.g.:

(import (custom quasiquote))
(match-with-quasiquote quasiquote
  (match x
    (`(1 ,b ,c) body1 body2 ...)
    ...))

Here, match-with-quasiquote is syntactic sugar that uses syntax-parameterize in its expansion.

ashinn commented 7 years ago

Hypothetical uses aside, what are you trying to write in chibi-scheme at this moment that requires this feature?

I don't think this is particularly difficult to implement, but I have extremely limited time, and it does require maintenance and attention to corner cases.

mnieper commented 7 years ago

If you could give me a hint for where in Chibi's code I should look first (or a general idea), I could try to add this feature and send you a pull-request.

(I once tried to implement it using sc-macro-transformer and macro-expand alone, but never tried to finish this try.)

As to non-hypothetical use cases: I have already coded the extension to quasiquotation and a pattern matcher (in the style of http://www.cs.indiana.edu/chezscheme/match/) (which I mentioned in the use cases) and could add the features that only work with syntax parameters immediately.

Marc

Alex Shinn notifications@github.com schrieb am Sa., 14. Jan. 2017 um 15:07 Uhr:

Hypothetical uses aside, what are you trying to write in chibi-scheme at this moment that requires this feature?

I don't think this is particularly difficult to implement, but I have extremely limited time, and it does require maintenance and attention to corner cases.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ashinn/chibi-scheme/issues/383#issuecomment-272626271, or mute the thread https://github.com/notifications/unsubscribe-auth/AA45w8hUN48rRT8t2Fa0mjO2Cv1oHxgFks5rSNa5gaJpZM4La0-f .

ashinn commented 7 years ago

Yes, patches are welcome! It is basically mutating an env cell for the dynamic extent of expansion of the body? I think you can do this all in Scheme.

I'm not sure I understand your match+quasiquote example. You want to define your own custom version of quasiquote, provide an alternate version of (chibi match) which refers to a quasiquote syntax parameter, and override that parameter when importing the custom quasiquote? (More concretely, what is the custom quasiquote doing differently?)