apparent bug in sample implementation of SRFI 148 William D Clinger (18 Jul 2017 17:17 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (18 Jul 2017 19:01 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (18 Jul 2017 20:53 UTC)
Re: apparent bug in sample implementation of SRFI 148 William D Clinger (18 Jul 2017 23:33 UTC)
Re: apparent bug in sample implementation of SRFI 148 William D Clinger (19 Jul 2017 12:36 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (19 Jul 2017 13:41 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (19 Jul 2017 14:09 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (19 Jul 2017 14:27 UTC)
Re: apparent bug in sample implementation of SRFI 148 William D Clinger (19 Jul 2017 15:42 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (19 Jul 2017 17:34 UTC)
Re: apparent bug in sample implementation of SRFI 148 William D Clinger (19 Jul 2017 20:31 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (19 Jul 2017 21:07 UTC)
Re: apparent bug in sample implementation of SRFI 148 William D Clinger (20 Jul 2017 01:22 UTC)
Re: apparent bug in sample implementation of SRFI 148 William D Clinger (20 Jul 2017 01:37 UTC)
(missing)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (20 Jul 2017 08:01 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (20 Jul 2017 12:53 UTC)
Re: apparent bug in sample implementation of SRFI 148 Al Petrofsky (20 Jul 2017 23:06 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (21 Jul 2017 08:16 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (21 Jul 2017 13:13 UTC)
Re: apparent bug in sample implementation of SRFI 148 Alex Shinn (22 Jul 2017 10:53 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (22 Jul 2017 10:59 UTC)
Re: apparent bug in sample implementation of SRFI 148 Alex Shinn (22 Jul 2017 11:11 UTC)
Re: apparent bug in sample implementation of SRFI 148 Marc Nieper-Wißkirchen (20 Jul 2017 05:44 UTC)
Re: apparent bug in sample implementation of SRFI 148 Takashi Kato (20 Jul 2017 06:48 UTC)

Re: apparent bug in sample implementation of SRFI 148 William D Clinger 20 Jul 2017 01:22 UTC

I am reverting to the renaming semantics Larceny has been using for
10 years.  That means tonight's nightly builds will not be able to
run the sample implementation of SRFI 148.  I will explain why in a
moment.

Marc Nieper-Wißkirchen wrote:

> Yes, I think in fact the main point that needs to be resolved is whether a
> pattern variable is bound (for the purposes of hygiene) by a syntax rule as
> much as a variable is bound by a lambda form.

In Larceny, pattern variables are indeed bound, but I don't think
that's important.  That binding happens after (and has to happen
after) the matching that determines whether the identifiers are
pattern variables or literals.

> From the view of a macro writer, the syntax-rules system is more powerful
> when pattern variables are being renamed, because this would allow me to
> generate arbitrary many pattern variables by the usual tricks.

That renaming is the reason your sample implementation doesn't work
in Larceny (with the reverted semantics).  If an identifier occurs
within a template but not within the corresponding pattern, it is
renamed when the template is transcribed.  Those identifiers do
indeed act as generated pattern variables, which is the problem.
For your sample implementation to work, some of them need to be
treated as literals instead of pattern variables.

In the sample implementation of SRFI 147 (not 148), an identifier
named :continuation is inserted by

    the 4th rule of expand-transformer
    the 1st rule of syntax-rules-aux
    the 2nd rule of syntax-rules-aux
    the 4th rule of syntax-rules-aux

Those inserted identifiers are renamed for hygiene.  That means the
identifiers named :continuation that are introduced by the 1st and
2nd rules of syntax-rules-aux, in the hope that they will end up as
literals, will not match the identifier named :continuation that is
introduced by the fourth rule of expand-transformer or by the fourth
rule of syntax-rules-aux.  Instead of being recognized as literals,
which appears to be your intention, the :continuation identifiers
introduced by the fourth rules of those two macros will act as pattern
variables.

That is why your sample implementation doesn't run in Larceny.  Here
is an example:

(let-syntax
  ((m (em-syntax-rules ()
        ((m 'a) 'a))))
  (m '(define x 10))
  x)

eventually expands into an expression whose de-mangled form is

(begin
  (define-syntax
    o
    (em-syntax-rules-aux2
      o
      free-identifier=?
      ()
      ...
      ()
      (((m 'a) 'a))
      ()))
  (expand-transformer
    (let-syntax-aux (m) () () ((m '(define x 10)) x))
    o))

The define-syntax form expands into something like

(expand-transformer (scheme-define-syntax o)
  (em-syntax-rules-aux2
      o
      free-identifier=?
      ()
      ...
      ()
      (((m 'a) 'a))
      ()))

which matches the 4th rule of expand-transformer so it becomes
something like

(em-syntax-rules-aux2
  (:continuation&&91
     expand-transformer
     (scheme-define-syntax o))
  o
  free-identifier=?
  ()
  ...
  ()
  (((m 'a) 'a))
  ())

I have written :continuation&&91 to remind you that :continuation
has been renamed.  This is a tentative renaming, which will end up
resolving to the same binding as :continuation if it ends up as a
free variable of the final output, but that isn't what's going to
happen.  The form above eventually turns into something like

(scheme-define-syntax
  o
  (scheme-syntax-rules
    (quote :prepare :call :continuation&&87)
    ((_ (:continuation&&91 c ...) :prepare s %x)
     (c ... (ck s "arg" (o) %x)))
    ((_ (:continuation&&90 c ...) :prepare s . args)
     (c ...
        (syntax-error
          "bad arguments to macro call"
          .
          args)))
    ((_ (:continuation&&89 c ...) :call s 'a)
     (c ... (ck s 'a)))
    ((_ (:continuation&&88 c ...) . args)
     (c ... (ck () (o . args))))
    ((_ :prepare s %x) (ck s "arg" (o) %x))
    ((_ :prepare s . args)
     (syntax-error
       "bad arguments to macro call"
       .
       args))
    ((_ :call s 'a) (ck s 'a))
    ((_ . args) (ck () (o . args)))))

Skipping a few steps, the macro expander has to figure out
whether the four renamed occurrences of :continuation are
pattern variables or literals.  To decide which, the macro
expander has to match :continuation&&91 (say) against the
literal :continuation&&87.  Those don't match unless you ignore
the renaming, in which case other bad things happen as you
pointed out, so they don't match.  That means all of the
:continuation identifiers in the four rules where they appear
are treated as pattern variables, which causes the fourth rule
to match when the last was intended.  That's why

(m '(define x 10))

turns into

((define x 10) (ck () (o)))

instead of

(ck () (o '(define x 10)))

which is why Larceny reports a definition outside any legal
context.

Now the mystery is why the sample implementation works with
all the other systems you tried.  They might be renaming less
aggressively than Larceny, or they might be using a different
semantics when matching identifiers that occur in patterns
against the literals.

If you had to add a definition of :continuation to get your
implementation to work in those systems, that's a clue.  They
might be resolving the bindings of identifiers just before
they decide whether the identifiers are pattern variables or
literals, and that resolution might fail for some reason if
:continuation isn't bound.  That sounds very much like using
free-identifier=?, however, which (as you pointed out) does
the wrong thing for a different example.

Will