[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: