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 mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto