Hi,

I'm not sure I can really help, but I'll throw in some of the things I've learned while watching the Perl 6 design team do its work (and from occasional attempts to contribute there).

When you design an API or a syntax, you'll need examples of use cases. Write them down.

A use case could be
  "Find all PAST::Block nodes with exactly one statement, and replace
   it by that statement"
or
   "remove all PAST nodes with the 'DEBUG' attribute set"

I've seen you already have one:

Am 31.05.2010 04:11, schrieb Tyler Curtis:
So, how would we define my hypothetical "PAST::Op node with its
'pirop' attribute set to 'add', two PAST::Val children whose 'returns'
attributes are in this list of types"

More would be great :-)

I'm curious what others think of the two syntax proposals
included(XPath and Regexes), and if anyone has any other ideas of
possible syntaxes.

For finding nodes there are two basic approaches: declarative and procedural.

A declarative approach is like a regex, ie you say what you want. For example if '{...} stands for a node, '.' stands for attributes and "@" stands for child nodes:

{
  .type = Op
  .pirop = add
  @ = (
     { .returns = (Num|Integer) }    # two child nodes
     { .returns = (Num|Integer) }    # with these attributes each
  )
}

You could implement the (Num|Integer) matching by handling the matcher to a regex engine, maybe it would then look like ^[Num|Integer]$ instead - still fine.



A procedural approch is just a lump of code that returns True when the given node matches the criteria.

This is a Perl 6 example which assumes that the node is set to $_ (so that you can call methods on it with .foo instead of $_.foo)

{
   my $success =  .type eq 'Op'
      && .pirop eq 'add'
      && .childs == 2;    # numeric context = number of child nodes

   for .childs {   # re-aliases $_ to each child node in term
       $success &&= .returns eq 'Num' !! .returns eq 'Integer'
   }
}

(This would be wrapped in a block that catches exceptions, so if a PAST node has no 'pirop' attribute set, it will die, and count as not matching).

You can see it's much more clumsy, but also more general - you have a Turing complete matching language.

Of course it would also give you the freedom to provide the matcher in any language you want, like PIR, NQP, winxed, or even HLLs in some cases.

Bonus points for offering a mixture of both approaches: for example a simple, declarative filter for op types and literal attributes, and procedural filters for fine tuning.


For the replacing operation I'm pretty sure that a procedural approach is superior to a declarative one. So maybe just implement the ability to hand a callback that receives a found PAST node, and returns the new node. Maybe you can provide some helper functions for often needed tasks (what that will be is pretty obvious once you start to implement your use cases) to make things easier for the optimization author.


I hope I haven't just stated the obvious, and that you'll find some convenient way to write optimization rules.

Cheers,
Moritz
_______________________________________________
http://lists.parrot.org/mailman/listinfo/parrot-dev

Reply via email to