[Prev][Next][Index][Thread]
RE: Macro loops infinitely --- GD bug?
To cut to the chase, the easiest way to express this is probably:
  define macro one-definer
    { define one ?:name ?once end }
      => { define constant ?name = list(?once) }
  once:
    {  } => {  }
    { ?inner:*; ... } => { ?inner, ... }
  inner:
    {  } => {  }
    { ?:expression, ... } => { ?expression, ... }
  end macro;
There are a couple of reasons for the infinite recursions in the
other formulations. First, selection of a matching pattern within
a rule set is performed and committed to without consulting any
aux-rules referred to[*]. For example, if a macro contains:
  rule:
    { ?subrule } => { something }
    { ?any:* }   => { something else }
  subrule:
    { ?:name } => { ?name }
the ?any:* pattern will never be reached. That's because:
    { ?subrule } => { something }
is actually just shorthand for:
    { ?subrule:* } => { something }
i.e. an unconstrained wildcard match followed by an aux-rule
transformation.  
The safest way to think of aux-rules is as transformers applied
after pattern matching and before substitution. A match failure 
in an aux-rule transformation won't cause backtracking within 
the invoking rule set because at that point pattern matching is
a done deal in that rule set.
The shorthand that allows the constraint to be elided on a pattern
variable that names an aux-rule set has always been confusing and
I recommend that people don't use it. Always declare the wildcard
constraint explicitly.
The other thing that often comes as a surprise is just how many
cases a pattern like this is happy to match:
  { ?stuff:*; ... } => { something }
Between wildcarding and the implicit separator folding rules,
all of these inputs match (to at least one level):
            // the empty fragment
  1         // an input with no separator at all
  1;        // an input with a terminator
  1; 2      // an input with a separator
That's why it's important to put unambiguous base cases (like the
empty patterns in the example) first within a rule set.
-- Keith
[*] Technically there's one exception to this to do with 
"intermediate word" handling, but it's not something macro 
writers have to worry about.
References: