[Prev][Next][Index][Thread]

Re: Crash course on macros?



On 5 May 2000, Nolan Darilek wrote:
> Great and informative! Thanks.
> 
> >>>>> "Rob" == Rob Myers <robm@tdv.com> writes:
> 
>     Rob> The only really confusing thing to macros (apart from #key
>     Rob> and #rest macro parameters...) is the ?:body syntax. There
>     Rob> *should* be a name before :body, ie:
> 
>     Rob> define macro begin { begin ?theBody:body end } => { ?theBody
>     Rob> }; end;
> 
> Ah, so [?theBody:body] can be translated as:
> theBody is a variable of type body?

Yes and, for each possible constraint, you can have one occurency per
left-hand side where you omit the name (before the ':'), in which case
it's understood to be the same as the constraint name.

> What about:
> ?other:*
> 
> Does that mean 'other' matches anything which hasn't matched yet?

Basically, yes.  There are some rules whose details I can never quite
remember, about how "hungry" the parser is but "*" means "anything"
(provided you keep brackets balanaced).  The set of possible constraints
is (from Chapter 10 of the DRM -- hopefully FunO will have the online
distribtion out soon :-)::
  Constraint   Grammar accepted
  expression   /expression/
  variable     /variable/
  name         NAME
  token        TOKEN
  body         /body_opt/
  case-body    /case-body_opt/
  macro        /macro/
  *            (wildcard)

The other magic characters apart from ':' are
  ? NAME    On LHS, binds NAME according to constraint.  On RHS inserts
            the fragment bound to NAME
  ?? NAME   On LHS, after #key only, binds NAME to sequence of all values
            of all occurences of keyword NAME; constraints apply to each
            occurence individually.  On RHS, "??NAME, ..." inserts all
            bound values separated by ',' (can use ';' or
            BINARY-OPERATOR).
  ...       On LHS/RHS matches/inserts fragment matching the current
            aux-rule.  (In aux-rule "foo:" it's a shorthand for ?:foo".)
  ?= NAME   On RHS only, inserts reference to NAME in the lexical context
            where the macro was called (i.e., breaks macro hygiene).

The best thing is to read Chapter 10 of the DRM, when you can get hold of
one :-)

>     Rob> Can you give examples of macros using the constructs that are
>     Rob> problematic so people can take a look and go through them?
> 
> ... The [collectors] library includes the following macro:
> 
> define macro collecting
> [...]
>   { collecting (?vars) ?:body end }
>     => { ?vars;
>          ?body }
> vars:
>   { }
>     => { }
>   { ?var, ... }
>     => { ?var; ... }
> var:
> [...]
>   { ?base-name:name ?options:* }
>     => { let (?base-name) = collector-protocol(<list>, ?options);
>          assert-collector-protocol-ok(?base-name) }
> [...]
> 
> options:
>   { }
>     => { }
>   { ?:name ?:expression ... }
>     => { as-keyword(?#"name"), ?expression, ... }
> // Problem here!
>   { = ?:expression ... }
>     => { from:, ?expression, ... }
> end macro;
> 
> I don't quite understand how the { = ... } works, and I seem to
> remember someone stating that d2c can't handle that at the moment. Is
> it somehow possible to rewrite that in a different way?

>From a quick reading of the DRM macro grammar, I'd say the above isn't
actually correct Dylan!  I think you ought to have to put '\' before the
'=', since you're mentioning an operator in a non-infix-call way.  (You
have to do the same to write methods on '='.)  If that doesn't work, you
could try "lifting" the "options:" aux-rules into the "var:" aux-rules. 
That means you'd have 12 (4*3) "var:" rules instead of 4 but it might do
until (a)  d2c is fixed; or (b) the above sources are fixed ;-) 

HTH,
Hugh





Follow-Ups: References: