Am Do., 27. Aug. 2020 um 04:14 Uhr schrieb Alex Shinn <xxxxxx@gmail.com>:
On Tue, Aug 25, 2020 at 5:13 PM Marc Nieper-Wißkirchen <xxxxxx@nieper-wisskirchen.de> wrote:
Am Di., 25. Aug. 2020 um 09:58 Uhr schrieb Alex Shinn <xxxxxx@gmail.com>:

> Note your own syntax-case implementation for Chibi currently doesn't support cyclic literals.

It should as far as the language allows this. Can you give me an
example, which I would have to repair?

It's your own TODO on datum->syntax.

Right. :) When I wrote the syntax-case implementation, it was first just a proof of concept. I will eventually fix syntax->datum using a hash table that remembers those parts of the datum the procedure has already seen.

The current state is that, per R7RS, any cyclic literals must be directly quoted,
which means match-letrec can support them.  The idea of cycles in indirectly
quoted data, via other macros, is disallowed by the standard, with quasiquote
given as a specific example.  So I guess we can leave the cycles as is.

(let-syntax
    ((q
      (syntax-rules ()
        ((_ x) (quote x)))))
  (q #0=(#0#)))

is allowed by my reading of R7RS and is logically sound. Circular references are allowed only in literals but whether a certain datum in the input is a literal can only be detected after macro expansion. The example of quasiquote doesn't apply because quasiquote does not need to expand into quote.

Regardless of the above, not all literals need to be quoted (whether before or after macro expansion): #0=#(#0#) is a well-defined vector literal.

So in any case, macros scanning bodies mustn't scan inside vector literals or they may loop. But not scanning vectors means that the scanner may not see enough:

(let-syntax
    ((uncover
       (syntax-rules ()
         ((_ #(x)) x))))
  (uncover #(id)))

This expression expands into a reference to `id`. A scanner skipping vector literals wouldn't see `id`, though. (This is another reason why the Petrowsky/Kiselyov idea is broken beyond R5RS.)
 
Regarding match-letrec, we seem to have different perceptions of the
order of magnitude probability of a bug in real code.  Keep in mind that
this library has had a completely broken implementation of match-letrec
for 15 years while being used by multiple implementations.

This says a lot about how much match-letrec has actually been used...
You can write brittle and short-sighted code with any framework,
I wouldn't draw too many conclusions from that.  I can imagine
ways to write this more cleanly with syntax-rules.

Actually, I find your code very clean and easy to read.
 
I'm not arguing syntax-rules is the best macro system by any
means.  But there are two reasons to prefer a SRFI which
at least _can_ be implemented in pure syntax-rules.  Firstly,
because syntax-rules is the lowest common denominator.
Secondly because, in the same spirit of the "lambda the ultimate"
papers where we stretched how much could be done with just
lambda as a primitive, it is interesting to see how much can be
done with a simple macro system.  Doubtless there are better
axioms than syntax-rules, but most efforts are in more complex,
rather than simpler, systems.

+100

In no way, I want to see a pure syntax-rules implementation gone. A syntax-rules has one more benefit: As the system is rather restricted, you can prove a lot for it, including hygiene. So every subsystem implemented solely with syntax-rules inherits these properties.

What you wrote was one of my main motivations to write SRFI 148. It is just a macro language implemented portably in syntax-rules that compiles to syntax-rules during expansion.

If you take a look at the three examples there, you hopefully understand why I wrote that it may be worthwhile to have another match implementation in terms of SRFI 148.

Marc