|
Proto : |
Subject: [proto] [phoenix3] New design proposal
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2010-10-18 15:25:03
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.
boost::reference_wrapper)
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
phoenix.
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
[3]
https://svn.boost.org/svn/boost/sandbox/SOC/2010/phoenix3/libs/phoenix/doc/html/index.html
[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 list run by eric at boostpro.com