Hi all,

Based on recent discussions [1] I want to propose a new design for the 
intermediate structure of phoenix3.

This email will be the attempt to both explain the design, and formalize 
what phoenix is, and what phoenix expressions are.
An implementation can be found at [2]. Please feel free to comment on the 
concepts and design decision that were made. I urge you to read through [1] 
to better understand the motivation behind the need of such a refactoring.
I am not very happy with the names of most of the classes I implemented. 
Suggestions welcome!
Please also note, that this will only affect the "low level" design (as in 
how to make proto work as we want ;)). The "high level API as documented in 
[3] will not be affected by this changes.

At the very heart of the design, are phoenix_algorithm and meta_grammar.

template <typename Tag, typename Actions>
struct phoenix_algorithm;

template <typename Actions>
struct meta_grammar;

The responsibility of meta_grammar is to dispatch based on the expression 
tag to phoenix_algorithm. phoenix_algorithm then specifies what expression is 
valid (for the given tag), this is called ruled,  and binds the Action to 
this rule. This is done through template specializations and matching 
against proto grammars. This mechanism is also our first customization point 
in that design which is useful for defining new phoenix expressions.

Inside the core, terminals are already being handled.
Terminals are:
   1) regular, stored by value, C++ objects
   2) C++ value stored with some wrapper around (i.e. 
   3) placeholders

The first point is simply implemented with a plain proto::terminal<_> and 
needs no further attention, phoenix::val is implement with the help of this.
The second point is actually more interesting, which is our next 
customization point: Based on a hook-able is_custom_terminal<T> trait, users 
can register whatever wrapper they have. This allows transparent handling of 
these wrapper inside of phoenix.
Last but not least are the placeholder. This design finally solves the 
placeholder unification problem, by deciding on a newly introduced 
boost::is_placeholder<T> trait whether a given terminal value is a 
placeholder! This way, any placeholder meeting phoenix' requirements can be 
used inside phoenix now! The other way round, is not in the scope of 
With these tools in our box, we are able to define a very powerful EDSL. 
Please note, that until now, I only explained the data part of this design, 
that means, everything explained above has no specific behavior attached.
After setting up all we need with these constructs (oh, please do not forget 
all the tools proto already provides), the only thing we can say is if, or 
if not a given expression is a valid phoenix lambda expression. By default, 
everything but the terminals described above is disabled, and can be enabled 
on a need-by-need basis.

The next thing worth explaining is the Action template parameter to 
phoenix_algorithm and meta_grammar. With this parameter, the evaluation of 
our phoenix expression is controlled and customizable.
As part of the core, the evaluator Actions are provided and defined for the 
above mentioned terminal rules. Adding one more customization point:
unwrap_custom_terminal<T>, which needs specialization on the wrapper to 
transparently handle it.

With the help of these customization points it will be a pleasure to fulfill 
all the promised goodies [4] and [5]

I hope this explanation attempt wasn't too confuse.
Feel free to ask and please do comment :)

[1] http://thread.gmane.org/gmane.comp.lib.boost.proto/160
[2] http://github.com/sithhell/boosties/tree/master/phoenix
[4] http://boost-spirit.com/home/2010/07/23/phoenix3-gsoc-project/
[5] http://cplusplus-soup.com/2010/07/23/lisp-macro-capability-in-c/
proto mailing list

Reply via email to