[/==============================================================================
    Copyright (C) 2001-2010 Joel de Guzman
    Copyright (C) 2001-2005 Dan Marsden
    Copyright (C) 2001-2010 Thomas Heller

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
===============================================================================/]

[section:actions More on Actions]

As you know from the [link phoenix.inside.actor Actors in Detail] section,
Actions are what brings life to a Phoenix expression tree.

When dealing with a Phoenix expression tree, it gets evaluated top-down.
Example:

    _1 + 3 * _2

Can be visualized as an AST in the following way:

[$images/simple_ast.png]

In terms of actions this means:

* `rule::plus` is matched
* evaluate left:
 * `rule::placeholder` is matched
* evaluate right:
 * `rule::multiplies` is matched
  * evaluate left:
    * `rule::value` is matched
  * evaluate right:
    * `rule::placeholder` is matched

Every time a rule is matched, an action will be called. The action determines
how the Phoenix AST will be traversed.

[heading Writing an Action]

As mentioned in [link phoenix.inside.actor Actors in Detail] actions are
__proto_primitive_transforms__ for convenience Phoenix provides an abstraction
to this:

    template <typename Fun>
    struct call;

This is similar to __proto_call__ but does more. It calls the `Fun` function
object passed as template parameter with the `Context` and the children of the
expression associated with the rule.

Lets have an (simplified) example on how to write an evaluation action for
`rule::plus`:

    struct plus_eval
    {
        typedef int result_type;

        template <typename Lhs, typename Rhs, typename Context>
        result_type operator()(Lhs const& lhs, Rhs const &rhs, Context & ctx)
        {
            return eval(lhs, ctx) + eval(rhs, ctx);
        }
    };

    template <>
    struct default_actions::when<rule::plus>
        : call<plus_eval>
    {};

That's it. When evaluating a `plus` expression, the `plus_eval` callable gets
called with the left hand side and right hand side expression and the associated
Context.

[*But there is more:] As Actions /can/ be full fletched __proto_transforms__, you can
in fact use any proto expression you can imagine as the action. Phoenix predifines a
set of callables and transform to deal with the Context information passed along and
of course every Phoenix expression can be used as a Phoenix grammar or
__proto_pass_through_transform__.

[variablelist
 [
  [`functional::context(Env, Actions)`]
  [A __proto_callable__ that creates a new context out of the `Env` and `Actions` parameter]
 ]
 [
  [`functional::env(Context)`]
  [A __proto_callable__ that returns the environment out of the `Context` parameter]
 ]
 [
  [`functional::actions(Context)`]
  [A __proto_callable__ that returns the actions out of the `Context` parameter]
 ]
 [
  [`_context`]
  [A __proto_primitive_transform__ that returns the current context]
 ]
 [
  [`_env`]
  [A __proto_primitive_transform__ that returns the current environment]
 ]
 [
  [`_actions`]
  [A __proto_primitive_transform__ that returns the current actions]
 ]
 [
  [`context(env, actions)`]
  [A regular function that creates a context]
 ]
 [
  [`env(ctx)`]
  [A regular function that returns the environment from the given context]
 ]
 [
  [`actions(ctx)`]
  [A regular function that returns the actions from the given context]
 ]
]

Phoenix is equipped with a predefined set of expressions, rules and actions to
make all the stuff work you learned in the __phoenix_starter_kit__ and __phoenix_modules__
sections. See the [link phoenix.inside.rules next section] for more details!

[endsect]
