From 1059c6e7c4a4b350c56abe6974dd3cb79ff9920d Mon Sep 17 00:00:00 2001 From: John Fletcher Date: Fri, 6 Mar 2015 07:27:56 +0000 Subject: [PATCH] Commit release-3.2.0 changes after conflict resolution --- ChangeLog | 25 + doc/html/index.html | 365 +++- doc/html/phoenix-doc_HTML.manifest | 91 + doc/html/phoenix/acknowledgments.html | 95 ++ doc/html/phoenix/actor.html | 91 + doc/html/phoenix/basics.html | 274 +++ doc/html/phoenix/examples.html | 50 + .../examples/adding_an_expression.html | 159 ++ .../phoenix/examples/extending_actors.html | 321 ++++ .../transforming_the_expression_tree.html | 200 +++ doc/html/phoenix/inside.html | 60 + doc/html/phoenix/inside/actions.html | 210 +++ doc/html/phoenix/inside/actor.html | 412 +++++ doc/html/phoenix/inside/custom_terminals.html | 81 + doc/html/phoenix/inside/expression.html | 274 +++ .../inside/expression/boilerplate_macros.html | 516 ++++++ .../inside/placeholder_unification.html | 57 + doc/html/phoenix/inside/rules.html | 1031 +++++++++++ doc/html/phoenix/introduction.html | 71 + doc/html/phoenix/lazy_list.html | 105 ++ doc/html/phoenix/lazy_list/background.html | 82 + .../lazy_list/implementation_details.html | 293 ++++ doc/html/phoenix/lazy_list/testing.html | 53 + .../lazy_list/tutorial_with_examples.html | 66 + .../arithmetic_functions.html | 80 + .../list_generation.html | 66 + .../phoenix/lazy_list/what_is_provided.html | 180 ++ doc/html/phoenix/lazy_list/where_next_.html | 47 + doc/html/phoenix/maintenance.html | 100 ++ doc/html/phoenix/maintenance/background.html | 79 + doc/html/phoenix/maintenance/experience.html | 54 + .../experience/bugs_to_be_fixed.html | 55 + .../maintenance/experience/compilers.html | 102 ++ .../experience/maintenance_tools.html | 53 + .../phoenix/maintenance/method_in_use.html | 72 + ...nderstanding_of_how_maintenance_works.html | 82 + doc/html/phoenix/modules.html | 102 ++ doc/html/phoenix/modules/bind.html | 81 + .../bind/binding_function_objects.html | 57 + .../modules/bind/binding_functions.html | 70 + .../bind/binding_member_functions.html | 73 + .../bind/binding_member_variables.html | 75 + .../bind/compatibility_with_boost_bind.html | 55 + doc/html/phoenix/modules/core.html | 60 + doc/html/phoenix/modules/core/arguments.html | 195 +++ doc/html/phoenix/modules/core/nothing.html | 53 + doc/html/phoenix/modules/core/references.html | 117 ++ doc/html/phoenix/modules/core/values.html | 85 + doc/html/phoenix/modules/function.html | 151 ++ .../modules/function/adapting_functions.html | 371 ++++ doc/html/phoenix/modules/object.html | 56 + doc/html/phoenix/modules/object/casts.html | 72 + .../phoenix/modules/object/construction.html | 81 + doc/html/phoenix/modules/object/delete.html | 62 + doc/html/phoenix/modules/object/new.html | 81 + doc/html/phoenix/modules/operator.html | 369 ++++ doc/html/phoenix/modules/scope.html | 67 + doc/html/phoenix/modules/scope/lambda.html | 195 +++ doc/html/phoenix/modules/scope/let.html | 191 +++ .../modules/scope/local_variables.html | 70 + doc/html/phoenix/modules/statement.html | 115 ++ .../statement/___do_while_____statement.html | 74 + .../statement/___if_else_____statement.html | 89 + .../modules/statement/block_statement.html | 92 + .../modules/statement/for_statement.html | 82 + .../modules/statement/if__statement.html | 55 + .../modules/statement/switch__statement.html | 75 + .../phoenix/modules/statement/throw_.html | 85 + .../statement/try__catch__statement.html | 90 + .../modules/statement/while__statement.html | 70 + doc/html/phoenix/modules/stl.html | 53 + doc/html/phoenix/modules/stl/algorithm.html | 1143 +++++++++++++ doc/html/phoenix/modules/stl/container.html | 603 +++++++ doc/html/phoenix/organization.html | 362 ++++ doc/html/phoenix/references.html | 91 + doc/html/phoenix/starter_kit.html | 105 ++ doc/html/phoenix/starter_kit/arguments.html | 77 + .../construct__new__delete__casts.html | 72 + .../phoenix/starter_kit/lazy_functions.html | 110 ++ .../phoenix/starter_kit/lazy_operators.html | 152 ++ .../phoenix/starter_kit/lazy_statements.html | 74 + doc/html/phoenix/starter_kit/more.html | 59 + doc/html/phoenix/starter_kit/references.html | 75 + doc/html/phoenix/starter_kit/values.html | 118 ++ doc/html/phoenix/what_s_new.html | 55 + doc/html/phoenix/what_s_new/phoenix_3_0.html | 68 + .../phoenix/what_s_new/phoenix_3_0_5.html | 61 + .../phoenix_3_0_6__boost_1_57_0_.html | 56 + .../phoenix/what_s_new/phoenix_3_1_0.html | 62 + .../phoenix/what_s_new/phoenix_3_1_1.html | 61 + .../phoenix/what_s_new/phoenix_3_2_0.html | 50 + ...phoenix___warning_on__lambda_and_let_.html | 72 + doc/html/phoenix/wrap_up.html | 77 + doc/lazy_list.qbk | 419 +++++ doc/maintenance.qbk | 3 - doc/phoenix3.qbk | 20 + doc/what_s_new.qbk | 7 +- include/boost/phoenix/function/lazy_list.hpp | 1514 +++++++++++++++++ .../boost/phoenix/function/lazy_operator.hpp | 670 ++++++++ .../boost/phoenix/function/lazy_prelude.hpp | 830 +++++++++ include/boost/phoenix/function/lazy_reuse.hpp | 242 +++ include/boost/phoenix/version.hpp | 4 +- test/Jamfile | 5 + .../boost_bind_compatibility/bind_dm_test.cpp | 3 +- test/function/lazy_list2_tests.cpp | 42 + test/function/lazy_list3_tests.cpp | 54 + test/function/lazy_list_tests.cpp | 78 + test/function/lazy_operator_tests.cpp | 46 + test/include/function/lazy_headers.cpp | 10 + test/scope/lambda_tests3a.cpp | 3 +- test/scope/let_tests.cpp | 2 +- test/scope/let_tests_157.cpp | 2 +- 112 files changed, 17154 insertions(+), 24 deletions(-) create mode 100644 doc/html/phoenix-doc_HTML.manifest create mode 100644 doc/html/phoenix/acknowledgments.html create mode 100644 doc/html/phoenix/actor.html create mode 100644 doc/html/phoenix/basics.html create mode 100644 doc/html/phoenix/examples.html create mode 100644 doc/html/phoenix/examples/adding_an_expression.html create mode 100644 doc/html/phoenix/examples/extending_actors.html create mode 100644 doc/html/phoenix/examples/transforming_the_expression_tree.html create mode 100644 doc/html/phoenix/inside.html create mode 100644 doc/html/phoenix/inside/actions.html create mode 100644 doc/html/phoenix/inside/actor.html create mode 100644 doc/html/phoenix/inside/custom_terminals.html create mode 100644 doc/html/phoenix/inside/expression.html create mode 100644 doc/html/phoenix/inside/expression/boilerplate_macros.html create mode 100644 doc/html/phoenix/inside/placeholder_unification.html create mode 100644 doc/html/phoenix/inside/rules.html create mode 100644 doc/html/phoenix/introduction.html create mode 100644 doc/html/phoenix/lazy_list.html create mode 100644 doc/html/phoenix/lazy_list/background.html create mode 100644 doc/html/phoenix/lazy_list/implementation_details.html create mode 100644 doc/html/phoenix/lazy_list/testing.html create mode 100644 doc/html/phoenix/lazy_list/tutorial_with_examples.html create mode 100644 doc/html/phoenix/lazy_list/tutorial_with_examples/arithmetic_functions.html create mode 100644 doc/html/phoenix/lazy_list/tutorial_with_examples/list_generation.html create mode 100644 doc/html/phoenix/lazy_list/what_is_provided.html create mode 100644 doc/html/phoenix/lazy_list/where_next_.html create mode 100644 doc/html/phoenix/maintenance.html create mode 100644 doc/html/phoenix/maintenance/background.html create mode 100644 doc/html/phoenix/maintenance/experience.html create mode 100644 doc/html/phoenix/maintenance/experience/bugs_to_be_fixed.html create mode 100644 doc/html/phoenix/maintenance/experience/compilers.html create mode 100644 doc/html/phoenix/maintenance/experience/maintenance_tools.html create mode 100644 doc/html/phoenix/maintenance/method_in_use.html create mode 100644 doc/html/phoenix/maintenance/my_understanding_of_how_maintenance_works.html create mode 100644 doc/html/phoenix/modules.html create mode 100644 doc/html/phoenix/modules/bind.html create mode 100644 doc/html/phoenix/modules/bind/binding_function_objects.html create mode 100644 doc/html/phoenix/modules/bind/binding_functions.html create mode 100644 doc/html/phoenix/modules/bind/binding_member_functions.html create mode 100644 doc/html/phoenix/modules/bind/binding_member_variables.html create mode 100644 doc/html/phoenix/modules/bind/compatibility_with_boost_bind.html create mode 100644 doc/html/phoenix/modules/core.html create mode 100644 doc/html/phoenix/modules/core/arguments.html create mode 100644 doc/html/phoenix/modules/core/nothing.html create mode 100644 doc/html/phoenix/modules/core/references.html create mode 100644 doc/html/phoenix/modules/core/values.html create mode 100644 doc/html/phoenix/modules/function.html create mode 100644 doc/html/phoenix/modules/function/adapting_functions.html create mode 100644 doc/html/phoenix/modules/object.html create mode 100644 doc/html/phoenix/modules/object/casts.html create mode 100644 doc/html/phoenix/modules/object/construction.html create mode 100644 doc/html/phoenix/modules/object/delete.html create mode 100644 doc/html/phoenix/modules/object/new.html create mode 100644 doc/html/phoenix/modules/operator.html create mode 100644 doc/html/phoenix/modules/scope.html create mode 100644 doc/html/phoenix/modules/scope/lambda.html create mode 100644 doc/html/phoenix/modules/scope/let.html create mode 100644 doc/html/phoenix/modules/scope/local_variables.html create mode 100644 doc/html/phoenix/modules/statement.html create mode 100644 doc/html/phoenix/modules/statement/___do_while_____statement.html create mode 100644 doc/html/phoenix/modules/statement/___if_else_____statement.html create mode 100644 doc/html/phoenix/modules/statement/block_statement.html create mode 100644 doc/html/phoenix/modules/statement/for_statement.html create mode 100644 doc/html/phoenix/modules/statement/if__statement.html create mode 100644 doc/html/phoenix/modules/statement/switch__statement.html create mode 100644 doc/html/phoenix/modules/statement/throw_.html create mode 100644 doc/html/phoenix/modules/statement/try__catch__statement.html create mode 100644 doc/html/phoenix/modules/statement/while__statement.html create mode 100644 doc/html/phoenix/modules/stl.html create mode 100644 doc/html/phoenix/modules/stl/algorithm.html create mode 100644 doc/html/phoenix/modules/stl/container.html create mode 100644 doc/html/phoenix/organization.html create mode 100644 doc/html/phoenix/references.html create mode 100644 doc/html/phoenix/starter_kit.html create mode 100644 doc/html/phoenix/starter_kit/arguments.html create mode 100644 doc/html/phoenix/starter_kit/construct__new__delete__casts.html create mode 100644 doc/html/phoenix/starter_kit/lazy_functions.html create mode 100644 doc/html/phoenix/starter_kit/lazy_operators.html create mode 100644 doc/html/phoenix/starter_kit/lazy_statements.html create mode 100644 doc/html/phoenix/starter_kit/more.html create mode 100644 doc/html/phoenix/starter_kit/references.html create mode 100644 doc/html/phoenix/starter_kit/values.html create mode 100644 doc/html/phoenix/what_s_new.html create mode 100644 doc/html/phoenix/what_s_new/phoenix_3_0.html create mode 100644 doc/html/phoenix/what_s_new/phoenix_3_0_5.html create mode 100644 doc/html/phoenix/what_s_new/phoenix_3_0_6__boost_1_57_0_.html create mode 100644 doc/html/phoenix/what_s_new/phoenix_3_1_0.html create mode 100644 doc/html/phoenix/what_s_new/phoenix_3_1_1.html create mode 100644 doc/html/phoenix/what_s_new/phoenix_3_2_0.html create mode 100644 doc/html/phoenix/what_s_new/phoenix___warning_on__lambda_and_let_.html create mode 100644 doc/html/phoenix/wrap_up.html create mode 100644 doc/lazy_list.qbk create mode 100644 include/boost/phoenix/function/lazy_list.hpp create mode 100644 include/boost/phoenix/function/lazy_operator.hpp create mode 100644 include/boost/phoenix/function/lazy_prelude.hpp create mode 100644 include/boost/phoenix/function/lazy_reuse.hpp create mode 100644 test/function/lazy_list2_tests.cpp create mode 100644 test/function/lazy_list3_tests.cpp create mode 100644 test/function/lazy_list_tests.cpp create mode 100644 test/function/lazy_operator_tests.cpp create mode 100644 test/include/function/lazy_headers.cpp diff --git a/ChangeLog b/ChangeLog index edd1569..e940f8b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -47,12 +47,37 @@ CHANGELOG - DEVELOP +- V3.2.0 + +- Bump version number to 3.2.0 in version.hpp. + +- New header files in boost/phoenix/function + These are the first versions of the lazy functionality being introduced. + This is reimplementation of the ideas in FC++ on top of Phoenix. + The Phoenix code used is Phoenix.Function, along with Boost.Function. + lazy_prelude.hpp This is the top level header and also has prelude functions. + lazy_operator.hpp This defines lazy operators such as plus and minus. + lazy_list.hpp This defines list a lazy list class and associated code. + lazy_reuser.hpp This defines the reuser functions used in the code. + +- New tests for lazy functionality. + test/include/function/lazy_headers Test of the header structure. + test/function/lazy_list_tests Simple tests of list. + test/function/lazy_list2_tests More tests of list. +- Develop documentation for version 3.2.0 + This includes a new section on the lazy list implementation. + - V3.1.1 + - Bump version number to 3.1.1 in version.hpp and branch for release. + - New tests for lazy functions using existing phoenix/function capability. lazy_argument_tests, lazy_make_pair_tests, lazy_templated_struct_tests + - New example bind_goose.cpp comparing boost.bind and boost.phoenix.bind. + - Changes to let_tests and more_let_tests to avoid failing cases. + - Updates to documentation. - V3.1.0 diff --git a/doc/html/index.html b/doc/html/index.html index 7e482fc..20fb02a 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -1,16 +1,353 @@ - - - - Redirect to generated documentation - - - - Automatic redirection failed, please go to - http://boost-sandbox.sourceforge.net/libs/phoenix/doc/html/ - + + +Chapter 1. Phoenix 3.2.0 + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
Next
+
+
+

+Chapter 1. Phoenix 3.2.0

+

+Joel de Guzman +

+

+Dan Marsden +

+

+Thomas Heller +

+

+John Fletcher +

+
+
+

+ 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) +

+
+
+
+

Table of Contents

+
+
What's New
+
+
Phoenix + - warning on lambda and let
+
Phoenix 3.2.0
+
Phoenix 3.1.1
+
Phoenix 3.1.0
+
Phoenix + 3.0.6 (Boost 1.57.0)
+
Phoenix 3.0.5
+
Phoenix 3.0
+
+
Introduction
+
Starter Kit
+
+
Values
+
References
+
Arguments
+
Lazy Operators
+
Lazy Statements
+
Construct, + New, Delete, Casts
+
Lazy Functions
+
More
+
+
Basics
+
Organization
+
Actor
+
Modules
+
+
Core
+
+
Values
+
References
+
Arguments
+
Nothing
+
+
Function
+
Adapting + Functions
+
Operator
+
Statement
+
+
Block Statement
+
if_ Statement
+
if_else_ Statement
+
switch_ + Statement
+
while_ + Statement
+
do_while_ Statement
+
for_ Statement
+
try_ + catch_ Statement
+
throw_
+
+
Object
+
+
Construction
+
New
+
Delete
+
Casts
+
+
Scope
+
+
Local Variables
+
let
+
lambda
+
+
Bind
+
+
Binding + Function Objects
+
Binding Functions
+
Binding + Member Functions
+
Binding + Member Variables
+
Compatibility + with Boost.Bind
+
+
STL
+
+
Container
+
Algorithm
+
+
+
Inside Phoenix
+
+
Actors in Detail
+
Phoenix Expressions
+
Boilerplate + Macros
+
More on Actions
+
Predefined Expressions and Rules
+
Custom Terminals
+
Placeholder Unification
+
+
Advanced Examples
+
+
Extending Actors
+
Adding an expression
+
Transforming + the Expression Tree
+
+
Lazy List
+
+
Background
+
What is provided
+
Tutorial with + examples
+
+
Arithmetic + functions
+
List + Generation
+
+
Implementation + Details
+
Testing
+
Where Next?
+
+
Maintenance
+
+
Background
+
My + Understanding of how maintenance works
+
Method in use
+
Experience
+
+
Maintenance + Tools
+
Bugs + to be fixed
+
Compilers
+
+
+
Wrap Up
+
Acknowledgments
+
References
+
+
+

+ + Preface +

+

+ Functional programming is so called because a program consists entirely + of functions. The main program itself is written as a function which receives + the program's input as its argument and delivers the program's output as its + result. Typically the main function is defined in terms of other functions, + which in turn are defined in terms of still more functions until at the bottom + level the functions are language primitives. +

+

+ John Hughes-- Why Functional Programming + Matters +

+

+ +

+

+ + Description +

+

+ Phoenix enables Functional Programming (FP) in C++. The design and implementation + of Phoenix is highly influenced by FC++ + by Yannis Smaragdakis and Brian McNamara and the BLL + (Boost Lambda Library) by Jaakko Jaarvi and Gary Powell. Phoenix is a blend of + FC++ and BLL using the implementation techniques used in the Spirit + inline parser. +

+

+ Phoenix is a header only library. It is extremely modular by design. One can + extract and use only a small subset of the full library, literally tearing the + library into small pieces, without fear that the pieces won't work anymore. The + library is organized in highly independent modules and layers. +

+

+ + How + to use this manual +

+

+ The Phoenix library is organized in logical modules. This documentation provides + a user's guide and reference for each module in the library. A simple and clear + code example is worth a hundred lines of documentation; therefore, the user's + guide is presented with abundant examples annotated and explained in step-wise + manner. The user's guide is based on examples: lots of them. +

+

+ As much as possible, forward information (i.e. citing a specific piece of information + that has not yet been discussed) is avoided in the user's manual portion of each + module. In many cases, though, it is unavoidable that advanced but related topics + not be interspersed with the normal flow of discussion. To alleviate this problem, + topics categorized as "advanced" may be skipped at first reading. +

+

+ Some icons are used to mark certain topics indicative of their relevance. These + icons precede some text to indicate: +

+
+

Table 1.1. Icons

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
+

+ Icon +

+
+

+ Name +

+
+

+ Meaning +

+
+

+ +

+
+

+ Note +

+
+

+ Information provided is auxiliary but will give the reader a deeper + insight into a specific topic. May be skipped. +

+
+

+ +

+
+

+ Alert +

+
+

+ Information provided is of utmost importance. +

+
+

+ +

+
+

+ Tip +

+
+

+ A potentially useful and helpful piece of information. +

+
+
+
+

+ + ...To Joel's dear daughter, Phoenix +

+
+ + + +

Last revised: March 05, 2015 at 13:57:47 GMT

+
+
Next
+ diff --git a/doc/html/phoenix-doc_HTML.manifest b/doc/html/phoenix-doc_HTML.manifest new file mode 100644 index 0000000..63a9dbb --- /dev/null +++ b/doc/html/phoenix-doc_HTML.manifest @@ -0,0 +1,91 @@ +index.html +phoenix/what_s_new.html +phoenix/what_s_new/phoenix___warning_on__lambda_and_let_.html +phoenix/what_s_new/phoenix_3_2_0.html +phoenix/what_s_new/phoenix_3_1_1.html +phoenix/what_s_new/phoenix_3_1_0.html +phoenix/what_s_new/phoenix_3_0_6__boost_1_57_0_.html +phoenix/what_s_new/phoenix_3_0_5.html +phoenix/what_s_new/phoenix_3_0.html +phoenix/introduction.html +phoenix/starter_kit.html +phoenix/starter_kit/values.html +phoenix/starter_kit/references.html +phoenix/starter_kit/arguments.html +phoenix/starter_kit/lazy_operators.html +phoenix/starter_kit/lazy_statements.html +phoenix/starter_kit/construct__new__delete__casts.html +phoenix/starter_kit/lazy_functions.html +phoenix/starter_kit/more.html +phoenix/basics.html +phoenix/organization.html +phoenix/actor.html +phoenix/modules.html +phoenix/modules/core.html +phoenix/modules/core/values.html +phoenix/modules/core/references.html +phoenix/modules/core/arguments.html +phoenix/modules/core/nothing.html +phoenix/modules/function.html +phoenix/modules/function/adapting_functions.html +phoenix/modules/operator.html +phoenix/modules/statement.html +phoenix/modules/statement/block_statement.html +phoenix/modules/statement/if__statement.html +phoenix/modules/statement/___if_else_____statement.html +phoenix/modules/statement/switch__statement.html +phoenix/modules/statement/while__statement.html +phoenix/modules/statement/___do_while_____statement.html +phoenix/modules/statement/for_statement.html +phoenix/modules/statement/try__catch__statement.html +phoenix/modules/statement/throw_.html +phoenix/modules/object.html +phoenix/modules/object/construction.html +phoenix/modules/object/new.html +phoenix/modules/object/delete.html +phoenix/modules/object/casts.html +phoenix/modules/scope.html +phoenix/modules/scope/local_variables.html +phoenix/modules/scope/let.html +phoenix/modules/scope/lambda.html +phoenix/modules/bind.html +phoenix/modules/bind/binding_function_objects.html +phoenix/modules/bind/binding_functions.html +phoenix/modules/bind/binding_member_functions.html +phoenix/modules/bind/binding_member_variables.html +phoenix/modules/bind/compatibility_with_boost_bind.html +phoenix/modules/stl.html +phoenix/modules/stl/container.html +phoenix/modules/stl/algorithm.html +phoenix/inside.html +phoenix/inside/actor.html +phoenix/inside/expression.html +phoenix/inside/expression/boilerplate_macros.html +phoenix/inside/actions.html +phoenix/inside/rules.html +phoenix/inside/custom_terminals.html +phoenix/inside/placeholder_unification.html +phoenix/examples.html +phoenix/examples/extending_actors.html +phoenix/examples/adding_an_expression.html +phoenix/examples/transforming_the_expression_tree.html +phoenix/lazy_list.html +phoenix/lazy_list/background.html +phoenix/lazy_list/what_is_provided.html +phoenix/lazy_list/tutorial_with_examples.html +phoenix/lazy_list/tutorial_with_examples/arithmetic_functions.html +phoenix/lazy_list/tutorial_with_examples/list_generation.html +phoenix/lazy_list/implementation_details.html +phoenix/lazy_list/testing.html +phoenix/lazy_list/where_next_.html +phoenix/maintenance.html +phoenix/maintenance/background.html +phoenix/maintenance/my_understanding_of_how_maintenance_works.html +phoenix/maintenance/method_in_use.html +phoenix/maintenance/experience.html +phoenix/maintenance/experience/maintenance_tools.html +phoenix/maintenance/experience/bugs_to_be_fixed.html +phoenix/maintenance/experience/compilers.html +phoenix/wrap_up.html +phoenix/acknowledgments.html +phoenix/references.html diff --git a/doc/html/phoenix/acknowledgments.html b/doc/html/phoenix/acknowledgments.html new file mode 100644 index 0000000..7ad9502 --- /dev/null +++ b/doc/html/phoenix/acknowledgments.html @@ -0,0 +1,95 @@ + + + +Acknowledgments + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
    +
  1. + Hartmut Kaiser implemented the original lazy casts and constructors based + on his original work on Spirit SE "semantic expressions" (the + precursor to Phoenix), and guided Phoenix from the initial review of V2 + to the release of V3. +
  2. +
  3. + Eric Niebler did a 2.0 pre-release review and wrote some range related + code that Phoenix stole and used in the algorithms. Additionally he played + the leading role in inventing the extension mechanism as well as providing + early prototypes and helping with Boost.Proto code. DA Proto MAN! +
  4. +
  5. + Angus Leeming implemented the container functions on Phoenix-1 which I + then ported to Phoenix-2. +
  6. +
  7. + Daniel Wallin helped with the scope module, local variables, let and lambda + and the algorithms. I frequently discuss design issues with Daniel on Yahoo + Messenger. +
  8. +
  9. + Jaakko Jarvi. DA Lambda MAN! +
  10. +
  11. + Dave Abrahams, for his constant presence, wherever, whenever. +
  12. +
  13. + Aleksey Gurtovoy, DA MPL MAN! +
  14. +
  15. + Doug Gregor, always a source of inspiration. +
  16. +
  17. + Dan Marsden, did almost all the work in bringing Phoenix-2 out the door. +
  18. +
  19. + Thorsten Ottosen; Eric's range_ex code began life as "container_algo" + in the old boost sandbox, by Thorsten in 2002-2003. +
  20. +
  21. + Jeremy Siek, even prior to Thorsten, in 2001, started the "container_algo". +
  22. +
  23. + Vladimir Prus wrote the mutating algorithms code from the Boost Wiki. +
  24. +
  25. + Daryle Walker did a 2.0 pre-release review. +
  26. +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/actor.html b/doc/html/phoenix/actor.html new file mode 100644 index 0000000..d0d048a --- /dev/null +++ b/doc/html/phoenix/actor.html @@ -0,0 +1,91 @@ + + + +Actor + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Actor +

+

+ The Actor is the main concept + behind the library. Actors are function objects. An actor can accept 0 to + BOOST_PHOENIX_LIMIT arguments. +

+
+ + + + + +
[Note]Note

+ You can set BOOST_PHOENIX_LIMIT, + the predefined maximum arity an actor can take. By default, BOOST_PHOENIX_LIMIT is set to 10. +

+

+ Phoenix supplies an actor class + template whose specializations model the Actor + concept. actor has one template + parameter, Expr, that supplies + the underlying expression to evaluate. +

+
template <typename Expr>
+struct actor
+{
+    return_type
+    operator()() const;
+
+    template <typename T0>
+    return_type
+    operator()(T0& _0) const;
+
+    template <typename T0, typename T1>
+    return_type
+    operator()(T0& _0, T1& _1) const;
+
+    //...
+};
+
+

+ The actor class accepts the arguments through a set of function call operators + for 0 to BOOST_PHOENIX_LIMIT + arities (Don't worry about the details, for now. Note, for example, that we + skimp over the details regarding return_type). + The arguments are passed through to the evaluation mechanism. For more information + see Inside Actors. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/basics.html b/doc/html/phoenix/basics.html new file mode 100644 index 0000000..19aa028 --- /dev/null +++ b/doc/html/phoenix/basics.html @@ -0,0 +1,274 @@ + + + +Basics + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Basics +

+

+ Almost everything is a function in the Phoenix library that can be evaluated + as f(a1, a2, ..., a/n/), where n is the function's + arity, or number of arguments that the function expects. Operators are also + functions. For example, a + b is just + a function with arity == 2 (or binary). a + + b + is the same as add(a, b), a + + b + c is the + same as add(add(a, b), + c). +

+
+ + + + + +
[Note]Note

+ Amusingly, functions may even return functions. We shall see what this means + in a short while. +

+

+ + Partial + Function Application +

+

+ Think of a function as a black box. You pass arguments and it returns something + back. The figure below depicts the typical scenario. +

+

+ +

+

+ A fully evaluated function is one in which all the arguments are given. All + functions in plain C++ are fully evaluated. When you call the sin(x) function, you have to pass a number x. The + function will return a result in return: the sin of x. When you call the add(x, y) + function, you have to pass two numbers x and y. The function will return the + sum of the two numbers. The figure below is a fully evaluated add function. +

+

+ +

+

+ A partially applied function, on the other hand, is one in which not all the + arguments are supplied. If we are able to partially apply the function add above, we may pass only the first argument. + In doing so, the function does not have all the required information it needs + to perform its task to compute and return a result. What it returns instead + is another function, a lambda function. Unlike the original add + function which has an arity of 2, the resulting lambda function has an arity + of 1. Why? because we already supplied part of the input: 2 +

+

+ +

+

+ Now, when we shove in a number into our lambda function, it will return 2 plus + whatever we pass in. The lambda function essentially remembers 1) the original + function, add, and 2) the partial + input, 2. The figure below illustrates a case where we pass 3 to our lambda + function, which then returns 5: +

+

+ +

+

+ Obviously, partially applying the add + function, as we see above, cannot be done directly in C++ where we are expected + to supply all the arguments that a function expects. That's where the Phoenix + library comes in. The library provides the facilities to do partial function + application. And even more, with Phoenix, these resulting functions won't be + black boxes anymore. +

+

+ + STL + and higher order functions +

+

+ So, what's all the fuss? What makes partial function application so useful? + Recall our original example in the previous + section: +

+
std::find_if(c.begin(), c.end(), arg1 % 2 == 1)
+
+

+ The expression arg1 % + 2 == 1 evaluates to a lambda function. arg1 is a placeholder for an argument to + be supplied later. Hence, since there's only one unsupplied argument, the lambda + function has an arity 1. It just so happens that find_if + supplies the unsupplied argument as it loops from c.begin() + to c.end(). +

+
+ + + + + +
[Note]Note

+ Higher order functions are functions which can take other functions as arguments, + and may also return functions as results. Higher order functions are functions + that are treated like any other objects and can be used as arguments and + return values from functions. +

+

+ + Lazy + Evaluation +

+

+ In Phoenix, to put it more accurately, function evaluation has two stages: +

+
    +
  1. + Partial application +
  2. +
  3. + Final evaluation +
  4. +
+

+ The first stage is handled by a set of generator functions. These are your + front ends (in the client's perspective). These generators create (through + partial function application), higher order functions that can be passed on + just like any other function pointer or function object. The second stage, + the actual function call, can be invoked or executed anytime in the future, + or not at all; hence "lazy". +

+

+ If we look more closely, the first step involves partial function application: +

+
arg1 % 2 == 1
+
+

+ The second step is the actual function invocation (done inside the find_if function. These are the back-ends + (often, the final invocation is never actually seen by the client). In our + example, the find_if, if we + take a look inside, we'll see something like: +

+
template <class InputIterator, class Predicate>
+InputIterator
+find_if(InputIterator first, InputIterator last, Predicate pred)
+{
+    while (first != last && !pred(*first))  // <--- The lambda function is called here
+        ++first;                            //      passing in *first
+    return first;
+}
+
+

+ Again, typically, we, as clients, see only the first step. However, in this + document and in the examples and tests provided, don't be surprised to see + the first and second steps juxtaposed in order to illustrate the complete semantics + of Phoenix expressions. Examples: +

+
int x = 1;
+int y = 2;
+
+std::cout << (arg1 % 2 == 1)(x) << std::endl; // prints 1 or true
+std::cout << (arg1 % 2 == 1)(y) << std::endl; // prints 0 or false
+
+

+ + Forwarding + Function Problem +

+

+ Usually, we, as clients, write the call-back functions while libraries (such + as STL) provide the callee (e.g. find_if). + In case the role is reversed, e.g. if you have to write an STL algorithm that + takes in a predicate, or develop a GUI library that accepts event handlers, + you have to be aware of a little known problem in C++ called the "Forwarding + Function Problem". +

+

+ Look again at the code above: +

+
(arg1 % 2 == 1)(x)
+
+

+ Notice that, in the second-stage (the final evaluation), we used a variable + x. +

+

+ In Phoenix we emulated perfect forwarding through preprocessor macros generating + code to allow const and non-const references. +

+

+ We generate these second-stage overloads for Phoenix expression up to BOOST_PHOENIX_PERFECT_FORWARD_LIMIT +

+
+ + + + + +
[Note]Note

+ You can set BOOST_PHOENIX_PERFECT_FORWARD_LIMIT, + the predefined maximum perfect forward arguments an actor can take. By default, + BOOST_PHOENIX_PERFECT_FORWARDLIMIT + is set to 3. +

+

+ + Polymorphic + Functions +

+

+ Unless otherwise noted, Phoenix generated functions are fully polymorphic. + For instance, the add example + above can apply to integers, floating points, user defined complex numbers + or even strings. Example: +

+
std::string h("Hello");
+char const* w = " World";
+std::string r = add(arg1, arg2)(h, w);
+
+

+ evaluates to std::string("Hello + World"). The observant + reader might notice that this function call in fact takes in heterogeneous + arguments where arg1 is of + type std::string and arg2 + is of type char const*. add + still works because the C++ standard library allows the expression a + b + where a is a std::string + and b is a char + const*. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/examples.html b/doc/html/phoenix/examples.html new file mode 100644 index 0000000..c43bea1 --- /dev/null +++ b/doc/html/phoenix/examples.html @@ -0,0 +1,50 @@ + + + +Advanced Examples + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/examples/adding_an_expression.html b/doc/html/phoenix/examples/adding_an_expression.html new file mode 100644 index 0000000..1a516d6 --- /dev/null +++ b/doc/html/phoenix/examples/adding_an_expression.html @@ -0,0 +1,159 @@ + + + +Adding an expression + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is not a toy example. This is actually part of the library. Remember + the while lazy statement? Putting together + everything we've learned so far, we eill present it here in its entirety + (verbatim): +

+
BOOST_PHOENIX_DEFINE_EXPRESSION(
+    (boost)(phoenix)(while_)
+  , (meta_grammar)           // Cond
+    (meta_grammar)           // Do
+)
+
+namespace boost { namespace phoenix
+{
+    struct while_eval
+    {
+        typedef void result_type;
+
+        template <typename Cond, typename Do, typename Context>
+        result_type
+        operator()(Cond const& cond, Do const& do_, Context & ctx) const
+        {
+            while(eval(cond, ctx))
+            {
+                eval(do_, ctx);
+            }
+        }
+    };
+
+    template <typename Dummy>
+    struct default_actions::when<rule::while_, Dummy>
+        : call<while_eval, Dummy>
+    {};
+
+    template <typename Cond>
+    struct while_gen
+    {
+        while_gen(Cond const& cond) : cond(cond) {}
+
+        template <typename Do>
+        typename expression::while_<Cond, Do>::type const
+        operator[](Do const& do_) const
+        {
+            return expression::while_<Cond, Do>::make(cond, do_);
+        }
+
+        Cond const& cond;
+    };
+
+    template <typename Cond>
+    while_gen<Cond> const
+    while_(Cond const& cond)
+    {
+        return while_gen<Cond>(cond);
+    }
+}}
+
+

+ while_eval is an example + of how to evaluate an expression. It gets called in the rule::while action. + while_gen and while_ are the expression template front + ends. Let's break this apart to undestand what's happening. Let's start at + the bottom. It's easier that way. +

+

+ When you write: +

+
while_(cond)
+
+

+ we generate an instance of while_gen<Cond>, where Cond + is the type of cond. cond can be an arbitrarily complex actor + expression. The while_gen + template class has an operator[] accepting another expression. If we write: +

+
while_(cond)
+[
+    do_
+]
+
+

+ it will generate a proper composite with the type: +

+
expression::while_<Cond, Do>::type
+
+

+ where Cond is the type of + cond and Do + is the type of do_. Notice + how we are using Phoenix's Expression + mechanism here +

+
template <typename Do>
+typename expression::while_<Cond, Do>::type const
+operator[](Do const& do_) const
+{
+    return expression::while_<Cond, Do>::make(cond, do_);
+}
+
+

+ Finally, the while_eval does + its thing: +

+
while(eval(cond, ctx))
+{
+    eval(do_, ctx);
+}
+
+

+ cond and do_, + at this point, are instances of Actor. + cond and do_ + are the Actors passed as parameters + by call, ctx is the Context +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/examples/extending_actors.html b/doc/html/phoenix/examples/extending_actors.html new file mode 100644 index 0000000..2e7088d --- /dev/null +++ b/doc/html/phoenix/examples/extending_actors.html @@ -0,0 +1,321 @@ + + + +Extending Actors + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Actors are one of the main parts + of the library, and one of the many customization points. The default actor + implementation provides several operator() overloads which deal with the + evaluation of expressions. +

+

+ For some use cases this might not be enough. For convenience it is thinkable + to provide custom member functions which generate new expressions. An example + is the if_else_ +Statement + which provides an additional else member for generating a lazy if-else expression. + With this the actual Phoenix expression becomes more expressive. +

+

+ Another scenario is to give actors the semantics of a certain well known + interface or concept. This tutorial like section will provide information + on how to implement a custom actor which is usable as if it were a STL Container. +

+
+ + Requirements +
+

+ Let's repeat what we want to have: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Semantics +

+
+

+ a.begin() +

+
+

+ Returns an iterator pointing to the first element in the container. +

+
+

+ a.end() +

+
+

+ Returns an iterator pointing one past the last element in the container. +

+
+

+ a.size() +

+
+

+ Returns the size of the container, that is, its number of elements. +

+
+

+ a.max_size() +

+
+

+ Returns the largest size that this container can ever have. +

+
+

+ a.empty() +

+
+

+ Equivalent to a.size() == 0. (But possibly faster.) +

+
+

+ a.swap(b) +

+
+

+ Equivalent to swap(a,b) +

+
+

+ Additionally, we want all the operator() overloads of the regular actor. +

+
+ + Defining the + actor +
+

+ The first version of our container_actor + interface will show the general principle. This will be continually extended. + For the sake of simplicity, every member function generator will return + nothing + at first. +

+
template <typename Expr>
+struct container_actor
+	: actor<Expr>
+{
+	typedef actor<Expr> base_type;
+	typedef container_actor<Expr> that_type;
+	
+	container_actor( base_type const& base )
+		: base_type( base ) {}
+
+	expression::null<mpl::void_>::type const begin() const { return nothing; }
+	expression::null<mpl::void_>::type const end() const { return nothing; }
+	expression::null<mpl::void_>::type const size() const { return nothing; }
+	expression::null<mpl::void_>::type const max_size() const { return nothing; }
+	expression::null<mpl::void_>::type const empty() const { return nothing; }
+
+	// Note that swap is the only function needing another container.
+	template <typename Container>
+	expression::null<mpl::void_>::type const swap( actor<Container> const& ) const { return nothing; }
+};
+
+
+ + Using + the actor +
+

+ Although the member functions do nothing right now, we want to test if we + can use our new actor. +

+

+ First, lets create a generator which wraps the container_actor + around any other expression: +

+
template <typename Expr>
+container_actor<Expr> const
+container( actor<Expr> const& expr )
+{
+    return expr;
+}
+
+

+ Now let's test this: +

+
std::vector<int> v;
+v.push_back(0);
+v.push_back(1);
+v.push_back(2);
+v.push_back(3);
+
+(container(arg1).size())(v);
+
+

+ Granted, this is not really elegant and not very practical (we could have + just used phoenix::begin(v) from the Phoenix + algorithm module, but we can do better. +

+

+ Let's have an argument placeholder + which is usable as if it was a STL container: +

+
container_actor<expression::argument<1>::type> const con1;
+// and so on ...
+
+

+ The above example can be rewritten as: +

+
std::vector<int> v;
+v.push_back(0);
+v.push_back(1);
+v.push_back(2);
+v.push_back(3);
+
+(con1.size())(v);
+
+

+ Wow, that was easy! +

+
+ + Adding + life to the actor +
+

+ This one will be even easier! +

+

+ First, we define a lazy function + which evaluates the expression we want to implement. Following is the implementation + of the size function: +

+
struct size_impl
+{
+	// result_of protocol:
+	template <typename Sig>
+	struct result;
+
+	template <typename This, typename Container>
+	struct result<This(Container)>
+	{
+		// Note, remove reference here, because Container can be anything
+		typedef typename boost::remove_reference<Container>::type container_type;
+
+		// The result will be size_type
+		typedef typename container_type::size_type type;
+	};
+
+	template <typename Container>
+	typename result<size_impl(Container const&)>::type
+	operator()(Container const& container) const
+	{
+		return container.size();
+	}
+};
+
+

+ Good, this was the first part. The second part will be to implement the size + member function of container_actor: +

+
template <typename Expr>
+struct container_actor
+	: actor<Expr>
+{
+	typedef actor<Expr> base_type;
+	typedef container_actor<Expr> that_type;
+	
+	container_actor( base_type const& base )
+		: base_type( base ) {}
+
+	typename expression::function<size_impl, that_type>::type const
+	size() const
+	{
+		function<size_impl> const f = size_impl();
+		return f(*this);
+	}
+
+	// the rest ...
+};
+
+

+ It is left as an exercise to the user to implement the missing parts by reusing + functions from the Phoenix + Algorithm Module (the impatient take a look here: container_actor.cpp). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/examples/transforming_the_expression_tree.html b/doc/html/phoenix/examples/transforming_the_expression_tree.html new file mode 100644 index 0000000..b13db0b --- /dev/null +++ b/doc/html/phoenix/examples/transforming_the_expression_tree.html @@ -0,0 +1,200 @@ + + + +Transforming the Expression Tree + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This example will show how to write Actions + that transform the Phoenix AST. +

+
+

+ "Lisp macros transform the program structure itself, with + the full language available to express such transformations." +

+

+ Wikipedia +

+
+

+ What we want to do is to invert some arithmetic operators, i.e. plus will + be transformed to minus, minus to plus, multiplication to division and division + to multiplication. +

+

+ Let's start with defining our default action: +

+
struct invert_actions
+{
+    template <typename Rule>
+    struct when
+        : proto::_ // the default is proto::_
+    {};
+};
+
+

+ By default, we don't want to do anything, well, not exactly nothing, but + just return the expression. This is done by proto::_ + which, used as a transform, just passes the current expression along. Making + this action an identity transform. +

+

+ So, after the basics are set up, we can start by writing the transformations + we want to have on our tree: +

+
// Transform plus to minus
+template <>
+struct invert_actions::when<phoenix::rule::plus>
+    : proto::call<
+        proto::functional::make_expr<proto::tag::minus>(
+            phoenix::evaluator(proto::_left, phoenix::_context)
+          , phoenix::evaluator(proto::_right, phoenix::_context)
+        )
+    >
+{};
+
+

+ Wow, this looks complicated! Granted you need to know a little bit about + Boost.Proto + (For a good introduction read through the Expressive + C++ series). +

+

+ What is done is the following: +

+
    +
  • + The left expression is passed to evaluator (with the current context, + that contains our invert_actions) +
  • +
  • + The right expression is passed to evaluator (with the current context, + that contains our invert_actions) +
  • +
  • + The result of these two Proto + Transforms is passed to proto::functional::make_expr which returns the + freshly created expression +
  • +
+

+ After you know what is going on, maybe the rest doesn't look so scary anymore: +

+
// Transform minus to plus
+template <>
+struct invert_actions::when<phoenix::rule::minus>
+    : proto::call<
+        proto::functional::make_expr<proto::tag::plus>(
+            phoenix::evaluator(proto::_left, phoenix::_context)
+          , phoenix::evaluator(proto::_right, phoenix::_context)
+        )
+    >
+{};
+
+// Transform multiplies to divides
+template <>
+struct invert_actions::when<phoenix::rule::multiplies>
+    : proto::call<
+        proto::functional::make_expr<proto::tag::divides>(
+            phoenix::evaluator(proto::_left, phoenix::_context)
+          , phoenix::evaluator(proto::_right, phoenix::_context)
+        )
+    >
+{};
+
+// Transform divides to multiplies
+template <>
+struct invert_actions::when<phoenix::rule::divides>
+    : proto::call<
+        proto::functional::make_expr<proto::tag::multiplies>(
+            phoenix::evaluator(proto::_left, phoenix::_context)
+          , phoenix::evaluator(proto::_right, phoenix::_context)
+        )
+    >
+{};
+
+

+ That's it! Now that we have our actions defined, we want to evaluate some + of our expressions with them: +

+
template <typename Expr>
+// Calculate the result type: our transformed AST
+typename boost::result_of<
+    phoenix::evaluator(
+        Expr const&
+      , phoenix::result_of::context<int, invert_actions>::type
+    )
+>::type
+invert(Expr const & expr)
+{
+    return
+        // Evaluate it with our actions
+        phoenix::eval(
+            expr
+          , phoenix::context(
+                int()
+              , invert_actions()
+            )
+        );
+}
+
+

+ Run some tests to see if it is working: +

+
invert(_1);                    // --> _1
+invert(_1 + _2);               // --> _1 - _2
+invert(_1 + _2 - _3);          // --> _1 - _2 + _3
+invert(_1 * _2);               // --> _1 / _2
+invert(_1 * _2 / _3);          // --> _1 / _2 * _3
+invert(_1 * _2 + _3);          // --> _1 / _2 - _3
+invert(_1 * _2 - _3);          // --> _1 / _2 + _2
+invert(if_(_1 * _4)[_2 - _3]); // --> if_(_1 / _4)[_2 + _3]
+_1 * invert(_2 - _3));         // --> _1 * _2 + _3
+
+

+ + The complete example can be found here: example/invert.cpp +

+

+ Pretty simple ... +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside.html b/doc/html/phoenix/inside.html new file mode 100644 index 0000000..72eaf73 --- /dev/null +++ b/doc/html/phoenix/inside.html @@ -0,0 +1,60 @@ + + + +Inside Phoenix + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ This chapter explains in more detail how the library operates. The information + henceforth should not be necessary to those who are interested in just using + the library. However, a microscopic view might prove to be beneficial to advanced + programmers who wish to extend the library. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside/actions.html b/doc/html/phoenix/inside/actions.html new file mode 100644 index 0000000..661d33b --- /dev/null +++ b/doc/html/phoenix/inside/actions.html @@ -0,0 +1,210 @@ + + + +More on Actions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ As you know from the 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: +

+

+ +

+

+ 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. +

+
+ + Writing + an Action +
+

+ As mentioned in 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. +

+
+

+
+
functional::context(Env, Actions)
+

+ A Proto + Callable Transform that creates a new context out of the Env and Actions + parameter +

+
functional::env(Context)
+

+ A Proto + Callable Transform that returns the environment out of the + Context parameter +

+
functional::actions(Context)
+

+ A Proto + Callable Transform 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 Starter + Kit and Modules sections. See + the next section for more details! +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside/actor.html b/doc/html/phoenix/inside/actor.html new file mode 100644 index 0000000..f4f6647 --- /dev/null +++ b/doc/html/phoenix/inside/actor.html @@ -0,0 +1,412 @@ + + + +Actors in Detail + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + Actor +
+

+ The main concept is the Actor. + An Actor is a model of the + Polymorphic + Function Object concept (that can accept 0 to N arguments (where + N is a predefined maximum). +

+

+ An Actor contains a valid + Phoenix Expression, a call to one of the function call operator overloads, + starts the evaluation process. +

+
+ + + + + +
[Note]Note

+ You can set BOOST_PHOENIX_LIMIT, + the predefined maximum arity an actor can take. By default, BOOST_PHOENIX_LIMIT is set to 10. +

+

+ The actor template class + models the Actor concept: +

+
template <typename Expr>
+struct actor
+{
+    template <typename Sig>
+    struct result;
+
+    typename result_of::actor<Expr>::type
+    operator()() const;
+
+    template <typename T0>
+    typename result_of::actor<Expr, T0 &>::type
+    operator()(T0& _0) const;
+
+    template <typename T0>
+    typename result_of::actor<Expr, T0 const &>::type
+    operator()(T0 const & _0) const;
+
+    //...
+};
+
+
+

Table 1.9. Actor Concept Requirements

+
++++ + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Semantics +

+
+

+ actor(arg0, + arg1, + ..., argN) +

+
+

+ Function call operators to start the evaluation +

+
+

+ boost::result_of<Actor<Expr>(Arg0, + Arg1, + ..., ArgN)>::type +

+
+

+ Result of the evaluation +

+
+

+ result_of::actor<Expr, + Arg0, + Arg1, + ..., ArgN>::type +

+
+

+ Result of the evaluation +

+
+
+
+ + Function + Call Operators +
+

+ There are 2*N function call operators for 0 to N arguments (N == BOOST_PHOENIX_LIMIT). The actor class accepts + the arguments and forwards the arguments to the default evaluation action. +

+

+ Additionally, there exist function call operators accepting permutations + of const and non-const references. These operators are created for all N + <= BOOST_PHOENIX_PERFECT_FORWARD_LIMIT + (which defaults to 3). +

+
+ + + + + +
[Note]Note
+

+ Forwarding Function Problem +

+

+ There is a known issue with current C++ called the "Forwarding + Function Problem". The problem is that given an arbitrary + function F, using current + C++ language rules, one cannot create a forwarding function FF that transparently assumes the arguments + of F. +

+
+
+ + Context +
+

+ On an actor function call, before calling the evaluation function, the actor + created a context. This context consists + of an Environment and an + Action part. These contain + all information necessary to evaluate the given expression. +

+
+

Table 1.10. Context Concept Requirements

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Semantics +

+
+

+ result_of::context<Env, + Actions>::type +

+
+

+ Type of a Context +

+
+

+ context(e, + a) +

+
+

+ A Context containing environment e + and actions a +

+
+

+ result_of::env<Context>::type +

+
+

+ Type of the contained Environment +

+
+

+ env(ctx) +

+
+

+ The environment +

+
+

+ result_of::actions<Context>::type +

+
+

+ Type of the contained Actions +

+
+

+ actions(ctx) +

+
+

+ The actions +

+
+
+
+ + Environment +
+

+ The Environment is a model of Random + Access Sequence. +

+

+ The arguments passed to the actor's function call operator are collected + inside the Environment: +

+

+ +

+

+ Other parts of the library (e.g. the scope module) extends the Environment concept to hold other information + such as local variables, etc. +

+
+ + Actions +
+

+ Actions is the part of Phoenix which are responsible for giving the actual + expressions a specific behaviour. During the traversal of the Phoenix Expression + Tree these actions are called whenever a specified rule in the grammar matches. +

+
struct actions
+{
+    template <typename Rule>
+    struct when;
+};
+
+

+ The nested when template + is required to be Proto + Primitive Transform. No worries, you don't have to learn Boost.Proto + just yet! Phoenix provides some wrappers to let you define simple actions + without the need to dive deep into proto. +

+

+ Phoenix ships with a predefined default_actions + class that evaluates the expressions with C++ semantics: +

+
struct default_actions
+{
+    template <typename Rule, typename Dummy = void>
+    struct when
+        : proto::_default<meta_grammar>
+    {};
+};
+
+

+ For more information on how to use the default_actions class and how to attach + custom actions to the evaluation process, see more + on actions. +

+
+ + Evaluation +
+
struct evaluator
+{
+    template <typename Expr, typename Context>
+    unspecified operator()(Expr &, Context &);
+};
+
+evaluator const eval = {};
+
+

+ The evaluation of a Phoenix expression is started by a call to the function + call operator of evaluator. +

+

+ The evaluator is called by the actor + function operator overloads after the context is built up. For reference, + here is a typical actor::operator() + that accepts two arguments: +

+
template <typename T0, typename T1>
+typename result_of::actor<Expr, T0 &, T1 &>::type
+operator()(T0 &t0, T1 &t1) const
+{
+    fusion::vector2<T0 &, T1 &> env(t0, t1);
+
+    return eval(*this, context(env, default_actions()));
+}
+
+
+ + result_of::actor +
+

+ For reasons of symmetry to the family of actor::operator() there is a special metafunction usable + for actor result type calculation named result_of::actor. + This metafunction allows us to directly specify the types of the parameters + to be passed to the actor::operator() function. Here's a typical actor_result that accepts two arguments: +

+
namespace result_of
+{
+    template <typename Expr, typename T0, typename T1>
+    struct actor
+    {
+        typedef fusion::vector2<T0, T1>                                           env_tpe;
+        typedef typename result_of::context<env_type, default_actions>::type      ctx_type
+        typedef typename boost::result_of<evaluator(Expr const&, ctx_type)>::type type;
+    };
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside/custom_terminals.html b/doc/html/phoenix/inside/custom_terminals.html new file mode 100644 index 0000000..d8b5a05 --- /dev/null +++ b/doc/html/phoenix/inside/custom_terminals.html @@ -0,0 +1,81 @@ + + + +Custom Terminals + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Custom Terminals are used in Phoenix to handle special values transparently. + For example, as Phoenix captures everything by value, we needed to use boost::reference_wrapper to bring reference semantics + into Phoenix. +

+

+ Custom terminals could be any wrapper class: +

+
template <typename T>
+struct is_custom_terminal;
+
+

+ needs to be specialized in order for Phoenix to recognize this wrapper type. + default_action calls custom_terminal<T>. +

+

+ Example: +

+
// Call out boost::reference_wrapper for special handling
+template<typename T>
+struct is_custom_terminal<boost::reference_wrapper<T> >
+  : mpl::true_
+{};
+
+// Special handling for boost::reference_wrapper
+template<typename T>
+struct custom_terminal<boost::reference_wrapper<T> >
+{
+    typedef T &result_type;
+
+    template <typename Context>
+    T &operator()(boost::reference_wrapper<T> r, Context &) const
+    {
+        return r;
+    }
+};
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside/expression.html b/doc/html/phoenix/inside/expression.html new file mode 100644 index 0000000..87c6fa8 --- /dev/null +++ b/doc/html/phoenix/inside/expression.html @@ -0,0 +1,274 @@ + + + +Phoenix Expressions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ A Phoenix Expression is a model of the Proto + Expression Concept. These expressions are wrapped inside an Actor template. The actor + provides the function call operator which evaluates the expressions. The + actor is the domain specific + wrapper around Phoenix expressions. +

+

+ By design, Phoenix Expressions do not carry any information on how they will + be evaluated later on. They are the data structure on which the Actions will work. +

+

+ The library provides a convenience template to define expressions: +

+
template <template <typename> Actor, typename Tag, typename A0, ..., typename A1>
+struct expr_ext
+    : proto::transform<expr_ext<Actor, Tag, A0, ..., A1> >
+{
+    typedef unspecified base_expr;
+    typedef Actor<base_expr> type;
+
+    typedef unspecified proto_grammar;
+
+    static type make(A0 a0, ..., A1 a1);
+};
+
+template <typename Tag, typename A0, ..., typename A1>
+struct expr : expr_ext<actor, Tag, A0, ..., A1> {};
+
+

+ Notation +

+
+

+
+
A0...AN
+

+ Child node types +

+
a0...aN
+

+ Child node objects +

+
G0...GN
+

+ Boost.Proto + grammar types +

+
+
+

+ Expression Semantics +

+
++++ + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Semantics +

+
+

+ expr<Tag, + A0...AN>::type +

+
+

+ The type of Expression having tag Tag + and A0...AN children +

+
+

+ expr<Tag, + G0...GN> +

+
+

+ A Boost.Proto + grammar and Proto + Pass Through Transform +

+
+

+ expr<Tag, + A0...AN>::make(a0...aN) +

+
+

+ Returns a Phoenix Expression +

+
+
+ + + + + +
[Note]Note

+ You might have noticed the template template argument Actor + used in expr_ext. This + can be a user supplied custom Actor adding other member functions or objects + than the default actor + template. See Extending + Actors for more details. +

+
+ + meta_grammar +
+

+ Defining expressions is only part of the game to make it a valid Phoenix + Expression. In order to use the expressions in the Phoenix domain, we need + to "register" them to our grammar. +

+

+ The meta_grammar is a struct + for exactly that purpose. It is an openly extendable Boost.Proto + Grammar: +

+
struct meta_grammar
+    : proto::switch_<meta_grammar>
+{
+    template <typename Tag, typename Dummy>
+    struct case_
+        : proto::not_<proto::_>
+    {};
+};
+
+

+ As you can see, by default the meta_grammar + matches nothing. With every Module + you include this grammar gets extended by various expressions. +

+
+ + Example +
+

+ Define an expression: +

+
template <typename Lhs, typename Rhs>
+struct plus
+    : expr<proto::tag::plus, Lhs, Rhs>
+{};
+
+

+ And add it to the grammar: +

+
template <>
+struct meta_grammar::case_<proto::tag::plus>
+    : enable_rule<
+        plus<
+            meta_grammar
+          , meta_grammar
+        >
+    >
+{};
+
+

+ Define a generator function to make the life of our potential users easier: +

+
template <typename Lhs, typename Rhs>
+typename plus<Lhs, Rhs>::type
+plus(Lhs const & lhs, Rhs const & rhs)
+{
+    return expression::plus<Lhs, Rhs>::make(lhs, rhs);
+}
+
+

+ Look if it really works: +

+
plus(6, 5)();
+
+

+ returns 11! +

+
proto::display_expr(plus(5, 6));
+
+

+ prints: +

+
plus(
+    terminal(6)
+  , terminal(5)
+)
+
+

+ See define_expression.cpp + for the full example. +

+
+ + + + + +
[Note]Note

+ The example shown here only works because default_actions + knows how to handle an expression having the proto::tag::plus + and two children. This is because default_actions + uses the proto::_default<meta_grammar> + transform to evaluate operators and functions. Learn more about actions + here. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside/expression/boilerplate_macros.html b/doc/html/phoenix/inside/expression/boilerplate_macros.html new file mode 100644 index 0000000..d660d28 --- /dev/null +++ b/doc/html/phoenix/inside/expression/boilerplate_macros.html @@ -0,0 +1,516 @@ + + + +Boilerplate Macros + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ When having more and more expressions, you start to realize that this is + a very repetetive task. Phoenix provides boilerplate macros that make defining + Phoenix Expressions as you have seen in the previous + section look like a piece of cake. +

+
+ +
+ + Description +
+

+ BOOST_PHOENIX_DEFINE_EXPRESSION + is a macro that can be used to generate all the necessary boilerplate + to create Phoenix Expressions +

+
+ + Synopsis +
+
BOOST_PHOENIX_DEFINE_EXPRESSION(
+    (namespace_seq)(name)
+  , (child_grammar0)
+    (child_grammar1)
+    ...
+)
+
+
+ + Semantics +
+

+ The above macro generates the necessary code for an expression name in namespace namespace_seq. + The sequence of (child_grammarN) declares how many children the expression + will have and what proto::grammar + they match. +

+

+ The macro should be used at global scope. namespace_seq + shall be the sequence of namespaces under which the following symbols + will be defined: +

+
namespace tag
+{
+    struct name;
+}
+
+namespace expression
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct name
+        : boost::phoenix::expr<
+            tag::name
+          , A0
+          , A1
+            ...
+          , AN
+        >
+}
+
+namespace rule
+{
+    struct name
+        : boost::phoenix::expr<
+            child_grammar0
+          , child_grammar1
+            ...
+          , child_grammarN
+        >
+    {};
+}
+
+namespace functional
+{
+    struct make_name; // A polymorphic function object that can be called to create the expression node
+}
+
+namespace result_of
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct make_name; // The result type of the expression node
+}
+
+// convenience polymorphic function to create an expression node
+template <typename A0, typename A1 ... typename AN>
+result_of::make_name<A0, A1 ... AN>
+make_name(A0 const & a0, A1 const & a1 ... AN const & an);
+
+

+ This macros also adds a specialization for meta_grammar::case_<tag::name> to enable the rule for further use + in actions. +

+
+ + Header +
+
#include <boost/phoenix/core/expression.hpp>
+
+
+ + Example +
+

+ The example from the previous section can be rewritten as: +

+
BOOST_PHOENIX_DEFINE_EXPRESSION(
+    (plus)
+  , (meta_grammar)               // Lhs
+    (meta_grammar)               // Rhs
+)
+
+template <typename Lhs, typename Rhs>
+typename plus<Lhs, Rhs>::type
+plus(Lhs const & lhs, Rhs const & rhs)
+{
+    return expression::plus<Lhs, Rhs>::make(lhs, rhs);
+}
+
+
+
+ +
+ + Description +
+

+ BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG + is a macro that can be used to generate all the necessary boilerplate + to create Phoenix Expressions +

+
+ + Synopsis +
+
BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG(
+    (namespace_seq)(name)
+  , (child_grammar0)
+    (child_grammar1)
+    ...
+    (child_grammarN)
+  , N
+)
+
+
+ + Semantics +
+

+ The above macro generates the necessary code for an expression name in namespace namespace_seq. + N is the maximum number + of variable children. All but the last elements in the grammar sequence + are required children of the expression, and the last denotes a variable + number of children. The number of children an expression of this kind + can hold is therefor N-1 plus + the size of the sequence +

+

+ The macro should be used at global scope. namespace_seq + shall be the sequence of namespaces under which the following symbols + will be defined: +

+
namespace tag
+{
+    struct name;
+}
+
+namespace expression
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct name
+        : boost::phoenix::expr<
+            tag::name
+          , A0
+          , A1
+            ...
+          , AN
+        >
+    {};
+}
+
+namespace rule
+{
+    struct name
+        : expression::name<
+            child_grammar0
+          , child_grammar1
+            ...
+          , proto::vararg<child_grammarN>
+        >
+    {};
+}
+
+namespace functional
+{
+    struct make_name; // A polymorphic function object that can be called to create the expression node
+}
+
+namespace result_of
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct make_name; // The result type of the expression node
+}
+
+// convenience polymorphic function to create an expression node
+template <typename A0, typename A1 ... typename AN>
+result_of::make_name<A0, A1 ... AN>
+make_name(A0 const & a0, A1 const & a1 ... AN const & an);
+
+

+ This macros also adds a specialization for meta_grammar::case_<tag::name> to enable the rule for further use + in actions. +

+
+ + Header +
+
#include <boost/phoenix/core/expression.hpp>
+
+
+ + Example +
+
BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG(
+    (boost)(phoenix)(mem_fun_ptr)
+  , (meta_grammar)                // Pointer to Object
+    (meta_grammar)                // Member pointer
+    (meta_grammar)                // Variable number of arguments
+  , BOOST_PHOENIX_LIMIT
+)
+
+

+ This defines the member function pointer operator expression as described + in operators. +

+
+
+ +
+ + Description +
+

+ BOOST_PHOENIX_DEFINE_EXPRESSION_EXT + is a macro that can be used to generate all the necessary boilerplate + to create Phoenix Expressions +

+
+ + Synopsis +
+
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT(
+    actor
+  , (namespace_seq)(name)
+  , (child_grammar0)
+    (child_grammar1)
+    ...
+    (child_grammarN)
+  , N
+)
+
+
+ + Semantics +
+

+ The above macro generates the necessary code for an expression name in namespace namespace_seq. + The sequence of (child_grammarN) declares how many children the expression + will have and what proto::grammar + they match. +

+

+ The macro should be used at global scope. namespace_seq + shall be the sequence of namespaces under which the following symbols + will be defined: +

+
namespace tag
+{
+    struct name;
+}
+
+namespace expression
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct name
+        : boost::phoenix::expr_ext<
+            actor
+          , tag::name
+          , A0
+          , A1
+            ...
+          , AN
+        >
+}
+
+namespace rule
+{
+    struct name
+        : boost::phoenix::expr<
+            child_grammar0
+          , child_grammar1
+            ...
+          , child_grammarN
+        >
+    {};
+}
+
+namespace functional
+{
+    struct make_name; // A polymorphic function object that can be called to create the expression node
+}
+
+namespace result_of
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct make_name; // The result type of the expression node
+}
+
+// convenience polymorphic function to create an expression node
+template <typename A0, typename A1 ... typename AN>
+result_of::make_name<A0, A1 ... AN>
+make_name(A0 const & a0, A1 const & a1 ... AN const & an);
+
+

+ This macros also adds a specialization for meta_grammar::case_<tag::name> to enable the rule for further use + in actions. +

+
+ + Header +
+
#include <boost/phoenix/core/expression.hpp>
+
+
+ + Example +
+
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT(
+    if_actor
+  , (boost)(phoenix)(if_)
+  , (meta_grammar) // Cond
+    (meta_grammar) // Then
+)
+
+

+ This defines the if_ expression. The custom actor defines else_ as a member. +

+
+
+ +
+ + Description +
+

+ BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG + is a macro that can be used to generate all the necessary boilerplate + to create Phoenix Expressions +

+
+ + Synopsis +
+
BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG(
+    actor
+  , (namespace_seq)(name)
+  , (child_grammar0)
+    (child_grammar1)
+    ...
+    (child_grammarN)
+  , N
+)
+
+
+ + Semantics +
+

+ The above macro generates the necessary code for an expression name in namespace namespace_seq. + N is the maximum number + of variable children. All but the last elements in the grammar sequence + are required children of the expression, and the last denotes a variable + number of children. The number of children an expression of this kind + can hold is therefor N-1 plus + the size of the sequence +

+

+ The macro should be used at global scope. namespace_seq + shall be the sequence of namespaces under which the following symbols + will be defined: +

+
namespace tag
+{
+    struct name;
+}
+
+namespace expression
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct name
+        : boost::phoenix::expr_ext<
+            actor
+          , tag::name
+          , A0
+          , A1
+            ...
+          , AN
+        >
+    {};
+}
+
+namespace rule
+{
+    struct name
+        : expression::name<
+            child_grammar0
+          , child_grammar1
+            ...
+          , proto::vararg<child_grammarN>
+        >
+    {};
+}
+
+namespace functional
+{
+    struct make_name; // A polymorphic function object that can be called to create the expression node
+}
+
+namespace result_of
+{
+    template <typename A0, typename A1 ... typename AN>
+    struct make_name; // The result type of the expression node
+}
+
+// convenience polymorphic function to create an expression node
+template <typename A0, typename A1 ... typename AN>
+result_of::make_name<A0, A1 ... AN>
+make_name(A0 const & a0, A1 const & a1 ... AN const & an);
+
+

+ This macros also adds a specialization for meta_grammar::case_<tag::name> to enable the rule for further use + in actions. +

+
+ + Header +
+
#include <boost/phoenix/core/expression.hpp>
+
+
+ + Example +
+

+ TBD +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside/placeholder_unification.html b/doc/html/phoenix/inside/placeholder_unification.html new file mode 100644 index 0000000..6321ccf --- /dev/null +++ b/doc/html/phoenix/inside/placeholder_unification.html @@ -0,0 +1,57 @@ + + + +Placeholder Unification + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Phoenix uses boost::is_placeholder for recognizing placeholders: +

+
template <typename T>
+struct is_placeholder
+{
+    static const int value = 0;
+};
+
+

+ To adapt your own placeholder, the nested value needs to be greater than + 0 for your types. This is done by specializing this trait. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/inside/rules.html b/doc/html/phoenix/inside/rules.html new file mode 100644 index 0000000..df7f779 --- /dev/null +++ b/doc/html/phoenix/inside/rules.html @@ -0,0 +1,1031 @@ + + + +Predefined Expressions and Rules + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This section is the "behind the scenes" counter part of the Modules section. A listing of all the predefined + expressions and rules: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Rule +

+
+
+

+ expression::value<T> +

+
+
rule::value
+    : expression::value<proto::_>
+
+
+

+ expression::reference<T> +

+
+
rule::custom_terminal
+
+
+

+ expression::argument<N> +

+
+
rule::argument
+
+

+ expression::null +

+
+
rule::custom_terminal
+
+

+ expression::function<F, + A0, + ..., AN> +

+
+
rule::function
+    : expression::function<vararg<meta_grammar> >
+
+
+

+ expression::negate<A0> +

+
+
rule::negate
+    : expression::negate<meta_grammar>
+
+
+

+ expression::unary_plus<A0> +

+
+
rule::negate
+    : expression::unary_plus<meta_grammar>
+
+
+

+ expression::pre_inc<A0> +

+
+
rule::negate
+    : expression::pre_inc<meta_grammar>
+
+
+

+ expression::pre_dec<A0> +

+
+
rule::negate
+    : expression::pre_dec<meta_grammar>
+
+
+

+ expression::post_inc<A0> +

+
+
rule::negate
+    : expression::post_inc<meta_grammar>
+
+
+

+ expression::post_dec<A0> +

+
+
rule::negate
+    : expression::post_dec<meta_grammar>
+
+
+

+ expression::plus_assign<Lhs, + Rhs> +

+
+
rule::plus_assign
+    : expression::plus_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::minus_assign<Lhs, + Rhs> +

+
+
rule::minus_assign
+    : expression::minus_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::multiplies_assign<Lhs, + Rhs> +

+
+
rule::multiplies_assign
+    : expression::multiplies_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::divides_assign<Lhs, + Rhs> +

+
+
rule::divides_assign
+    : expression::divides_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::modules_assign<Lhs, + Rhs> +

+
+
rule::modules_assign
+    : expression::modules_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::plus<Lhs, + Rhs> +

+
+
rule::plus
+    : expression::plus<meta_grammar, meta_grammar>
+
+
+

+ expression::minus<Lhs, + Rhs> +

+
+
rule::minus
+    : expression::minus<meta_grammar, meta_grammar>
+
+
+

+ expression::multiplies<Lhs, + Rhs> +

+
+
rule::multiplies
+    : expression::multiplies<meta_grammar, meta_grammar>
+
+
+

+ expression::divides<Lhs, + Rhs> +

+
+
rule::divides
+    : expression::divides<meta_grammar, meta_grammar>
+
+
+

+ expression::modulus<Lhs, + Rhs> +

+
+
rule::modulus
+    : expression::modulus<meta_grammar, meta_grammar>
+
+
+

+ expression::complement<A0> +

+
+
rule::complement
+    : expression::complement<A0>
+
+
+

+ expression::bitwise_and_assign<Lhs, + Rhs> +

+
+
rule::bitwise_and_assign
+    : expression::bitwise_and_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::bitwise_or_assign<Lhs, + Rhs> +

+
+
rule::bitwise_or_assign
+    : expression::bitwise_or_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::bitwise_xor_assign<Lhs, + Rhs> +

+
+
rule::bitwise_xor_assign
+    : expression::bitwise_xor_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::shift_left_assign<Lhs, + Rhs> +

+
+
rule::shift_left_assign
+    : expression::shift_left_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::shift_right_assign<Lhs, + Rhs> +

+
+
rule::shift_right_assign
+    : expression::shift_right_assign<meta_grammar, meta_grammar>
+
+
+

+ expression::bitwise_and<Lhs, + Rhs> +

+
+
rule::bitwise_and
+    : expression::bitwise_and<meta_grammar, meta_grammar>
+
+
+

+ expression::bitwise_or<Lhs, + Rhs> +

+
+
rule::bitwise_or
+    : expression::bitwise_or<meta_grammar, meta_grammar>
+
+
+

+ expression::bitwise_xor<Lhs, + Rhs> +

+
+
rule::bitwise_xor
+    : expression::bitwise_xor<meta_grammar, meta_grammar>
+
+
+

+ expression::shift_left<Lhs, + Rhs> +

+
+
rule::shift_left
+    : expression::shift_left<meta_grammar, meta_grammar>
+
+
+

+ expression::shift_right<Lhs, + Rhs> +

+
+
rule::shift_right
+    : expression::shift_right<meta_grammar, meta_grammar>
+
+
+

+ expression::equal_to<Lhs, + Rhs> +

+
+
rule::equal_to
+    : expression::equal_to<meta_grammar, meta_grammar>
+
+
+

+ expression::not_equal_to<Lhs, + Rhs> +

+
+
rule::not_equal_to
+    : expression::not_equal_to<meta_grammar, meta_grammar>
+
+
+

+ expression::less_equal_to<Lhs, + Rhs> +

+
+
rule::less_equal_to
+    : expression::less_equal_to<meta_grammar, meta_grammar>
+
+
+

+ expression::greater_equal<Lhs, + Rhs> +

+
+
rule::greater_equal
+    : expression::greater_equal<meta_grammar, meta_grammar>
+
+
+

+ expression::less<Lhs, + Rhs> +

+
+
rule::less
+    : expression::less<meta_grammar, meta_grammar>
+
+
+

+ expression::greater<Lhs, + Rhs> +

+
+
rule::greater
+    : expression::greater<meta_grammar, meta_grammar>
+
+
+

+ expression::if_else_operator<Cond, + Then, + Else> +

+
+
rule::if_else
+    : expression::if_else<meta_grammar, meta_grammar, meta_grammar>
+
+
+

+ expression::logical_not<A0> +

+
+
rule::logical_not
+    : expression::logical_not<meta_grammar>
+
+
+

+ expression::logical_and<Lhs, + Rhs> +

+
+
rule::logical_and
+    : expression::logical_and<meta_grammar, meta_grammar>
+
+
+

+ expression::logical_or<Lhs, + Rhs> +

+
+
rule::logical_or
+    : expression::logical_or<meta_grammar, meta_grammar>
+
+
+

+ expression::mem_fun_ptr<Object, + MemPtr, + A0, + ..., AN> +

+
+
rule::mem_fun_ptr
+    : expression::mem_fun_ptr<meta_grammar, meta_grammar, vararg<meta_grammar> >
+
+
+

+ expression::address_of<A0> +

+
+
rule::address_of
+    : expression::address_of<meta_grammar>
+
+
+

+ expression::dereference<A0> +

+
+
rule::dereference
+    : expression::dereference<meta_grammar>
+
+
+

+ expression::assign<Lhs, + Rhs> +

+
+
rule::assign
+    : expression::assign<meta_grammar, meta_grammar>
+
+
+

+ expression::subscript<Lhs, + Rhs> +

+
+
rule::subscript
+    : expression::subscript<meta_grammar, meta_grammar>
+
+
+

+ expression::sequence<A0, + A1> +

+
+
rule::sequence
+    : expression::sequence<meta_grammar, meta_grammar>
+
+
+

+ expression::if_<Cond, + Then> +

+
+
rule::if_
+    : expression::if_<meta_grammar, meta_grammar>
+
+
+

+ expression::if_else_statement<Cond, + Then, + Else> +

+
+
rule::if_else_statement
+    : expression::if_else_statement<meta_grammar, meta_grammar, meta_grammar>
+
+
+

+ expression::switch_case<Label, + Statement> +

+
+
rule::switch_case
+    : expression::switch_case< terminal<mpl::int_<N> >, meta_grammar>
+
+
+

+ expression::switch_default_case<Statement> +

+
+
rule::switch_default_case
+    : expression::switch_default_case<meta_grammar>
+
+
+

+ expression::switch_<Cond, + Cases> +

+
+
rule::switch_
+    : expression::switch_<
+        meta_grammar
+      , switch_grammar
+    >
+
+
+

+ expression::while_<Cond, + Do> +

+
+
rule::while_
+    : expression::while_<
+        meta_grammar
+      , meta_grammar
+    >
+
+
+

+ expression::do_while<Cond, + Do> +

+
+
rule::do_while
+    : expression::do_while<
+        meta_grammar
+      , meta_grammar
+    >
+
+
+

+ expression::for_<Init, + Cond, + Step, + Do> +

+
+
rule::for_
+    : expression::for_<
+        meta_grammar
+      , meta_grammar
+      , meta_grammar
+      , meta_grammar
+    >
+
+
+

+ expression::catch_<Exception, + Statement> +

+
+
rule::catch_
+    : expression::catch_<
+        catch_exception<proto::_>
+      , meta_grammar
+    >
+
+
+

+ expression::catch_all<Statement> +

+
+
rule::catch_all
+    : expression::catch_<meta_grammar>
+
+
+

+ expression::try_catch<Try, + Catch0, + ..., CatchN> +

+
+
rule::try_catch
+    : proto::or_<
+        expression::try_catch<
+            meta_grammar
+          , vararg<rule::catch_>
+        >
+      , expression::try_catch<
+            meta_grammar
+          , vararg<rule::catch_>
+          , rule::catch_all
+        >
+      , expression::try_catch<
+            meta_grammar
+          , catch_all
+        >
+    >
+
+
+

+ expression::throw_<A0> +

+
+
rule::throw_
+    : expression::throw_<meta_grammar>
+
+
+

+ expression::construct<Target, + A0, + ..., AN> +

+
+
rule::construct
+   : expression::construct<
+       terminal<detail::target<proto::_> >
+     , A0
+       ...
+     , AN
+   >
+
+
+

+ expression::new_<Target, + A0, + ..., AN> +

+
+
rule::new_
+   : expression::new_<
+       terminal<detail::target<proto::_> >
+     , A0
+       ...
+     , AN
+   >
+
+
+

+ expression::delete_<A0> +

+
+
rule::delete_
+      : expression::delete_<meta_grammar>
+
+
+

+ expression::static_cast_<Target, + A> +

+
+
rule::static_cast_
+   : expression::static_cast_<
+       terminal<detail::target<proto::_> >
+     , A
+   >
+
+
+

+ expression::dynamic_cast_<Target, + A> +

+
+
rule::dynamic_cast_
+   : expression::dynamic_cast_<
+       terminal<detail::target<proto::_> >
+     , A
+   >
+
+
+

+ expression::reinterpret_cast_<Target, + A> +

+
+
rule::reinterpret_cast_
+   : expression::reinterpret_cast_<
+       terminal<detail::target<proto::_> >
+     , A
+   >
+
+
+

+ expression::const_cast_<Target, + A> +

+
+
rule::const_cast_
+   : expression::const_cast_<
+       terminal<detail::target<proto::_> >
+     , A
+   >
+
+
+

+ expression::local_variable<Key> +

+
+
rule::custom_terminal
+
+

+ expression::let<Locals, + Statement> +

+
+
rule::let
+    : expression::let<terminal<proto::_>, meta_grammar>
+
+
+

+ expression::lambda<OuterEnv, + Locals, + Statement> +

+
+
rule::lambda
+    : expression::lambda<terminal<proto::_>, terminal<proto::_>, meta_grammar>
+
+
+

+ expression::lambda_actor<Locals, + Statement> +

+
+
rule::lambda_actor
+    : expression::lambda_actor<terminal<proto::_>, meta_grammar>
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/introduction.html b/doc/html/phoenix/introduction.html new file mode 100644 index 0000000..71df470 --- /dev/null +++ b/doc/html/phoenix/introduction.html @@ -0,0 +1,71 @@ + + + +Introduction + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ +

+

+ The Phoenix library enables FP techniques such as higher order functions, + lambda (unnamed functions), currying + (partial function application) and lazy evaluation in C++. The focus is more + on usefulness and practicality than purity, elegance and strict adherence to + FP principles. +

+

+ FP is a programming discipline that is not at all tied to a specific language. + FP as a programming discipline can, in fact, be applied to many programming + languages. In the realm of C++ for instance, we are seeing more FP techniques + being applied. C++ is sufficiently rich to support at least some of the most + important facets of FP. C++ is a multiparadigm programming language. It is + not only procedural. It is not only object oriented. Beneath the core of the + standard C++ library, a closer look into STL gives us a glimpse of FP already + in place. It is obvious that the authors of STL know and practice FP. In the + near future, we shall surely see more FP trickle down into the mainstream. +

+

+ The truth is, most of the FP techniques can coexist quite well with the standard + object oriented and imperative programming paradigms. When we are using STL + algorithms and functors (function objects) for example, we are already doing + FP. Phoenix is an evolutionary next step. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list.html b/doc/html/phoenix/lazy_list.html new file mode 100644 index 0000000..3cf0654 --- /dev/null +++ b/doc/html/phoenix/lazy_list.html @@ -0,0 +1,105 @@ + + + +Lazy List + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ + Summary +

+

+ Phoenix now has a lazy list implementation which is very similar but not identical + to the implementation provided by FC++. + This provides a set of objects defined by list<type>, for example this + which defines an empty list of type int. +

+
list<int> l0;
+
+

+ A list can contain zero or more elements of the same type. It can also be declared + using a function returning values of the correct type. Such lists are only + evaluated on demand. A set of functions are defined which enable many ways + of manipulating and using lists. Examples are provided for the features available. +

+

+ + Introduction +

+

+ Boost Phoenix provides many features of functional_programming. One of the + things which has been missing until now is a lazy list implementation. One + is available in the library FC++ + which although not part of Boost has many similarities. It has been possible + to reimplement the strategy of the FC++ + List Implementation using the facilties in Phoenix. This provides something + which has up until now not been available anywhere in Phoenix and probably + not anywhere else in Boost. This new implementation is very well integrated + with other features in Phoenix as it uses the same mechanism. In turn that + is well integrated with Boost Function. +

+

+ There is a great deal of material in FC++ + and it is not proposed to replicate all of it. A great deal has changed since + FC++ was written and + many things are already available in Phoenix or elsewhere. The emphasis here + is to add to Phoenix in a way which will make it easier to implement functional_programming. +

+

+ Progress is being made in implementing both the basic list<T> and the + functions needed to manipulate lists. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/background.html b/doc/html/phoenix/lazy_list/background.html new file mode 100644 index 0000000..b24dc41 --- /dev/null +++ b/doc/html/phoenix/lazy_list/background.html @@ -0,0 +1,82 @@ + + + +Background + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ The original code of FC++ + was developed by Brian McNamara and Yannis Smaragdakis between 2000 and 2003. + One of the aims of their work was to implement as mich as possible of the + Haskell prelude in C++. In the end they achieved a very large part of that + and went on to implement other similar things not in the Haskell prelude. + This was made up of a large amount of code written very carefully in a consistent + style which made it easy to extend it to provide more facilities. +

+

+ At the end of that time, two versions of it existed, FC++ 1.5 and Boost FC++ which + was proposed for inclusion in Boost and rejected. Both are documented on + FC++. +

+

+ After 2003 John Fletcher spent a lot of time developing both these versions + and adding new features to them. One of the reasons intially was that the + existing versions could handle only a small number of function arguments. + He was able to inclrease the limit on the number of arguments and use the + new version to implement a number of new ideas. No new release has ever been + made although a draft release 1.5.2 exists. Much of his activity is documented + by FunctoidsInCpp + where some discussion took place with other people about this work. +

+

+ John discussed with Joel de Guzman how to make FC++ + compatible with Phoenix. Joel suggested using Phoenix as a basis for a new + version of FC++. +

+

+ In 2014 John became the maintainer of Phoenix and after spending time getting + to know it he has now started to fulfil his idea of a new version of FC++. What is emerging + is significantly different from FC++ + in the detail of the implementation. In some ways it will be more powerful + as it is well integrated with the facilities of Phoenix. In other ways it + will lack some features of FC++ + as they can now be implemented in other ways. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/implementation_details.html b/doc/html/phoenix/lazy_list/implementation_details.html new file mode 100644 index 0000000..20d567b --- /dev/null +++ b/doc/html/phoenix/lazy_list/implementation_details.html @@ -0,0 +1,293 @@ + + + +Implementation Details + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ + Introduction +

+

+ The implementation has depended on close study of the existing code of FC++. The FC++ + List Implementation is a carefully crafted code which allows for + efficient processing of a number of different cases. In particular it makes + use of the FC++ + Reuser Implementation for processing of repetitive evaluations. +

+

+ FC++ uses a combination + of polymorphic and single type functions which can be passed as arguments + to other functions. +

+

+ The implementation of list<T> has needed new implementations of the + strategy using the facilities of Boost Phoenix and also Boost Function. It + turns out that a combination of both can be used to meet the needs of list<T>. +

+

+ The fact that the functions are defined by boost::phoenix::function means + that they work with phoenix arguments such as 'arg1'. This is the fact which + ensures the flexibility needed for the user to build new functions as needed. +

+

+ + FC++ legacy +

+

+ The FC++ + List Implementation and the FC++ + Reuser Implementation have been followed very closely in building + this code. The version used as the starting point was the Boost + FC++ version. +

+

+ + Polymorphic + Function Types +

+

+ Functions are implemented as a struct within namespace impl. For an example + funcion 'x' the type is defined like this: +

+
typedef boost::phoenix::function<impl::X> X;
+X x
+
+

+ This alternative will work to provide a function 'x' but it is not then possible + to pass it as an argument. +

+
BOOST_PHOENIX_ADAPT_CALLABLE(x, impl::X, 1)
+
+

+ + Implementation + Example +

+

+ This example implements id() which simply returns its argument: +

+
namespace impl {
+
+  struct Id
+  {
+    template <typename Sig>
+    struct result;
+
+    template <typename This, typename A0>
+    struct result<This(A0)>
+       : boost::remove_reference<A0>
+    {};
+
+    template <typename A0>
+    A0 operator()(A0 const & a0) const
+    {
+        return a0;
+    }
+
+  };
+
+}
+
+typedef boost::phoenix::function<impl::Id> Id;
+Id id;
+
+

+ + Functions + with defined return type +

+

+ Sometimes it is necessary to define a function using a templated struct, + where the template parameter type defines the return type. +

+

+ + Example + with one argument +

+
namespace impl {
+
+  template <typename Result>
+  struct what {
+
+    typedef Result result_type;
+
+    Result operator()(Result const & r) const
+    {
+      return r;
+    }
+  };
+
+}
+
+boost::function1<int, int > what_int = impl::what<int>();
+typedef boost::function1<int,int> fun1_int_int;
+typedef boost::phoenix::function<fun1_int_int> What_arg;
+What_arg what_arg(what_int);
+
+

+ + Example + with zero arguments +

+
namespace impl {
+  template <typename Result>
+  struct what0 {
+
+    typedef Result result_type;
+
+    Result operator()() const
+    {
+      return Result(100);
+    }
+
+  };
+}
+
+typedef boost::function0<int> fun0_int;
+boost::function0<int> what0_int = impl::what0<int>();
+typedef boost::phoenix::function<fun0_int> What0_arg;
+What0_arg what0_arg(what0_int);
+
+

+ + List + Generation Implementation +

+

+ The implementation of the function +

+
enum_from(1)
+
+

+ requires a functor which will evaluate the successive numbers on demand. + The code from FC++ + has been reimplemented using internal functors as follows. +

+

+ This code has to carefully manipulate the input type T to construct the result + type which is a list. +

+

+ The code in EFH is used to build a series of objects which each add one element + to the list and return the function which will add the next element. That + only gets called when it is needed. +

+
template <class T>
+struct EFH
+{
+    typedef typename boost::remove_reference<T> TT;
+    typedef typename boost::remove_const<TT>::type TTT;
+    mutable T x;
+    EFH( const T& xx) : x(xx) {}
+    template <typename Sig> struct result;
+
+    template <typename This>
+    struct result<This(T)>
+    {
+      typedef typename boost::phoenix::UseList::template
+              List<T>::type LType;
+      typedef typename boost::phoenix::result_of::
+              ListType<LType>::delay_result_type type;
+    };
+    typename result<EFH(T)>::type operator()() const {
+      typedef typename UseList::template List<T>::type LType;
+      typedef typename result_of::ListType<LType>::
+              delay_result_type result_type;
+      typedef boost::function0<result_type> fun1_R_TTT;
+      //std::cout << "EFH (" << x << ")" << std::endl;
+      ++x;
+      fun1_R_TTT efh_R_TTT = EFH<T>(x);
+      typedef boost::phoenix::function<fun1_R_TTT> EFH_R_T;
+      EFH_R_T efh_R_T(efh_R_TTT);
+      if (x > MAX_LIST_LENGTH)
+           throw lazy_exception("Running away in EFH!!");
+      return cons( x-1, efh_R_T() );
+    }
+};
+
+struct Enum_from {
+   template <typename Sig> struct result;
+
+   template <typename This, typename T>
+   struct result<This(T)>
+   {
+     typedef typename boost::remove_reference<T>::type TT;
+     typedef typename boost::remove_const<TT>::type TTT;
+     typedef typename UseList::template List<TTT>::type LType;
+     typedef typename result_of::ListType<LType>::
+             delay_result_type type;
+   };
+
+   template <class T>
+   typename result<Enum_from(T)>::type operator()
+      (const T & x) const
+    {
+      typedef typename boost::remove_reference<T>::type TT;
+      typedef typename boost::remove_const<TT>::type TTT;
+      typedef typename UseList::template List<T>::type LType;
+      typedef typename result_of::ListType<LType>::
+              delay_result_type result_type;
+      typedef boost::function0<result_type> fun1_R_TTT;
+      fun1_R_TTT efh_R_TTT = EFH<TTT>(x);
+      typedef boost::phoenix::function<fun1_R_TTT> EFH_R_T;
+      EFH_R_T efh_R_T(efh_R_TTT);
+      //std::cout << "enum_from (" << x << ")" << std::endl;
+      return efh_R_T();
+    }
+};
+
+

+ Similar code is used in the related functors +

+
enum_from_to
+filter
+
+

+ + Conclusion +

+

+ These implementation mechanisms have been carried through consistently in + the implementation. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/testing.html b/doc/html/phoenix/lazy_list/testing.html new file mode 100644 index 0000000..b3bb4bd --- /dev/null +++ b/doc/html/phoenix/lazy_list/testing.html @@ -0,0 +1,53 @@ + + + +Testing + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Several tests are currently on develop with the hope of release to master + in time for Boost 1.58.0. +

+

+ At present all tests pass except for list<T> tests on MSVC + 8.0 and 9.0 which reject a reference of a reference. Corrections for this + have now been sucessfuly made. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/tutorial_with_examples.html b/doc/html/phoenix/lazy_list/tutorial_with_examples.html new file mode 100644 index 0000000..4e58d5a --- /dev/null +++ b/doc/html/phoenix/lazy_list/tutorial_with_examples.html @@ -0,0 +1,66 @@ + + + +Tutorial with examples + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ These examples require the following header: +

+
boost/phoenix/function/lazy_prelude.hpp
+
+

+ The following statements should be in the execution code: +

+
using boost::phoenix::arg_names::arg1;
+using boost::phoenix::arg_names::arg2;
+using namespace boost::phoenix;
+
+

+ To be developed. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/tutorial_with_examples/arithmetic_functions.html b/doc/html/phoenix/lazy_list/tutorial_with_examples/arithmetic_functions.html new file mode 100644 index 0000000..75352db --- /dev/null +++ b/doc/html/phoenix/lazy_list/tutorial_with_examples/arithmetic_functions.html @@ -0,0 +1,80 @@ + + + +Arithmetic functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Assume the values +

+
int a = 123;
+int b = 256;
+
+

+ The following are all valid expressions returning a+b +

+
plus(arg1, arg2)(a, b)
+plus(arg1, b)(a)
+plus(a, arg2)(a,b)
+plus(a, arg1)(b)
+plus(a, b)()
+
+

+ The expressions can be combined like this +

+
plus(minus(a, b),b)()
+plus(minus(arg1, b),b)(a)
+plus(minus(arg1, arg2),b)(a,b)
+plus(minus(arg1, arg2),arg2)(a,b)
+
+

+ Other numerical operators can be used like this +

+
multiplies(arg1,arg2)(3,6)
+divides(arg2,arg1)(3,6)
+modulus(arg2,arg1)(4,6)
+min(arg1,arg2)(4,6)
+max(arg1,arg2)(4,6)
+inc(arg1)(a)
+dec(arg1)(a)
+negate(arg1)(a)
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/tutorial_with_examples/list_generation.html b/doc/html/phoenix/lazy_list/tutorial_with_examples/list_generation.html new file mode 100644 index 0000000..70f06b3 --- /dev/null +++ b/doc/html/phoenix/lazy_list/tutorial_with_examples/list_generation.html @@ -0,0 +1,66 @@ + + + +List Generation + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ One of the most interesting capabilities of FC++ + is the generation of infinite lazy lists which are evaluated only at need. + The most simple example of this is +

+
enum_from(1)
+
+

+ which returns the generator for integers 1,2,3,..... infinity. +

+
take(4,enum_from(1))
+
+

+ returns a list of the first 4 of the list. +

+
at(enum_from(1),3)
+
+

+ returns the fourth member using zero indexed access. Both of the lists + returned are lazy and only evaluated when the list members are accessed. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/what_is_provided.html b/doc/html/phoenix/lazy_list/what_is_provided.html new file mode 100644 index 0000000..dce55d1 --- /dev/null +++ b/doc/html/phoenix/lazy_list/what_is_provided.html @@ -0,0 +1,180 @@ + + + +What is provided + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Functions are provided to build and manipulate objects of the list type +

+
list<T>
+
+

+ + Namespace + and header +

+

+ The functions are in the namespace +

+
boost::phoenix
+
+

+ by the header file +

+
boost/phoenix/function/lazy_prelude.hpp
+
+

+ which includes all other needed headers. It is not currently included in +

+
boost/phoenix/function.hpp
+
+

+ so it must be explicitly included to use these types and functions. +

+

+ + Integration + with Boost Phoenix +

+

+ The functions are defined by boost::phoenix::function which means that they + work with phoenix arguments such as 'arg1'. They have been defined in such + a way that when needed they can be passed as arguments to other functions. +

+

+ + Lazy + List Type +

+
list<T> (where T is the element type)
+
+

+ + Functions +

+

+ The functions are grouped as follows: +

+

+ + Arithmetic + functions +

+
plus
+minus
+multiplies
+divides
+modulus
+negate
+
+

+ + Boolean functions +

+
equal
+not_equal
+greater
+less
+greater_equal
+less_equal
+
+

+ + Logical functions +

+
logical_and
+logical_or
+logical_not
+
+

+ + Operational + functions +

+
apply
+until
+until2
+max
+min
+inc
+dec
+make_pair
+
+

+ + Logical predicates +

+
odd
+even
+
+

+ + List + Functions +

+
cons
+cat
+take
+drop
+last
+all_but_last
+at
+length
+filter
+
+

+ + List + Generation Functions +

+
enum_from
+enum_from_to
+list_with
+
+

+ + Futher + functions +

+

+ Further functions are in development from the resources available in FC++. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/lazy_list/where_next_.html b/doc/html/phoenix/lazy_list/where_next_.html new file mode 100644 index 0000000..b78ed01 --- /dev/null +++ b/doc/html/phoenix/lazy_list/where_next_.html @@ -0,0 +1,47 @@ + + + +Where Next? + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Further functions are going to be implemented and more examples provided. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance.html b/doc/html/phoenix/maintenance.html new file mode 100644 index 0000000..7bbf51f --- /dev/null +++ b/doc/html/phoenix/maintenance.html @@ -0,0 +1,100 @@ + + + +Maintenance + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ The experience of the maintenance of Boost Phoenix during 2014 and 2015. +

+

+ This section is being used to set out the maintenance policy for Boost Phoenix + and how it is being carried out. One reason for doing this is that in January + 2015 there is a lot of discussion within Boost about how best to do this. There + are also a number of issues for which the answers are not clear to me and I + am going to set those out here. +

+

+ Phoenix is a complicated library and the current version 3 is built on two + other libraries Boost.Proto + and Boost.Fusion + which are themselves quite complicated. Version 3 of Phoenix is a rebuilding + of the previous version using Boost.Proto. +

+

+ There are two ways to work with Phoenix. +

+
    +
  • + One is to ignore the previous statement and assume everything works. +
  • +
  • + The second is to understand the relationships between the libraries. +
  • +
+

+ Unfortunately, while most things now work, there are a number of subtle bugs + where things do not work as expected, and that is the challenge which is there + for the maintainer who did not write any version of the library. +

+

+ The remainder of this page is found from the index above. +

+

+ John Fletcher +

+

+ January and February 2015 +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance/background.html b/doc/html/phoenix/maintenance/background.html new file mode 100644 index 0000000..9fab597 --- /dev/null +++ b/doc/html/phoenix/maintenance/background.html @@ -0,0 +1,79 @@ + + + +Background + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Almost exactly a year ago, Joel de Guzman asked me to take on the lead maintenance + of Boost Phoenix and I agreed to do so, not really knowing what I was taking + on. In the first few months I fixed a lot of the things which could be fixed + easily, while at the same time learning how to use git to keep things in + order. Then things got tougher as I started to meet things which are not + so easy to fix. I also found there were things I did not understand well + enough. +

+

+ At the end of 2014 I came back to the task anew. In the meantime I have learned + a lot, particularly about Boost Fusion and Boost Proto which are used a lot + by Boost Phoenix. I have also learned how to edit the QuickBooks files and + regenerate them. +

+

+ I have still not solved all the problems in Boost Phoenix. I think I am closing + in on some of the remaining ones. I now know that some of the problems in + Phoenix V3 were also present in Phoenix V2. This has changed the approach + to how to solve them as I know that the problems cannot be in the use of + Boost Proto as it was not used in V2. +

+

+ I have made further progress during 2015 on understanding what the problems + are and how to avoid them or work around them. That has given me the confidence + to explore further applications of the code, which I expect will develop + a lot in the next few months. +

+

+ I want in this document to share some of what I have been doing and how I + have solved some of the problems. One reason for doing this is that there + may be other people who are considering taking on library maintenance of + a library they did not themselves write. I hope I can make that easier for + people to do. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance/experience.html b/doc/html/phoenix/maintenance/experience.html new file mode 100644 index 0000000..bb653f6 --- /dev/null +++ b/doc/html/phoenix/maintenance/experience.html @@ -0,0 +1,54 @@ + + + +Experience + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ A summary of experience during testing of Boost Phoenix. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance/experience/bugs_to_be_fixed.html b/doc/html/phoenix/maintenance/experience/bugs_to_be_fixed.html new file mode 100644 index 0000000..b4e96b7 --- /dev/null +++ b/doc/html/phoenix/maintenance/experience/bugs_to_be_fixed.html @@ -0,0 +1,55 @@ + + + +Bugs to be fixed + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ The bugs to be fixed have come from several sources. +

+

+ One type of bug which has been very difficult to understand has been that + some test cases failed when compiled with optimisation and not without + it. I now believe that this is related to the use of references in the + arguments passed back, and I have one test where the cure is demonstrated, + lazy_make_pair_tests. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance/experience/compilers.html b/doc/html/phoenix/maintenance/experience/compilers.html new file mode 100644 index 0000000..abfb30c --- /dev/null +++ b/doc/html/phoenix/maintenance/experience/compilers.html @@ -0,0 +1,102 @@ + + + +Compilers + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ I have been attempting to understand the differences between compilers + and environments when running tests on Boost Phoenix. +

+
    +
  • + Some environments are limited in the memory available for testing and + I have broken some large tests into smaller pieces. +
  • +
  • + Some of the problems experienced in testing are specific to particular + compilers being used. +
  • +
  • + Some problems have occurred with more recent several compilers. +
  • +
  • + One problem is that I do not have access to all of the compilers used + in the tests or by users. +
      +
    • + My system is Ubuntu + 12.04 +
    • +
    • + I have expanded the compilers I have available to include the + following +
    • +
    • + gcc 4.6, 4.8.2, 4.9.0 + & 4.9.2 (I will add 5.0 when released) +
    • +
    • + Clang 3.4, 3.5 & + 3.6 (pre-release in the last case) +
    • +
    +
  • +
  • + The most difficult problems to diagnose have been some which occur + when the compilation uses optimization. +
      +
    • + Some of the boost tests use optimization but most do not. +
    • +
    • + It is not usually documented which tests are optimized. +
    • +
    • + This means that a lot of tests run there which fail when optimized. +
    • +
    • + This has made the identification of the cause of the problems + more difficult. [endsect] +
    • +
    +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance/experience/maintenance_tools.html b/doc/html/phoenix/maintenance/experience/maintenance_tools.html new file mode 100644 index 0000000..187cc6c --- /dev/null +++ b/doc/html/phoenix/maintenance/experience/maintenance_tools.html @@ -0,0 +1,53 @@ + + + +Maintenance Tools + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ My experience has been that not all the tools and knowledge to be a maintainer + are available in one place to a new maintainer. A lot of things which are + well known to experienced maintainers are just not readily available. In + some cases they are buried in the detailed manuals of several different + tools. One reason for writing up my experience as a maintainer to help + others. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance/method_in_use.html b/doc/html/phoenix/maintenance/method_in_use.html new file mode 100644 index 0000000..3b30aeb --- /dev/null +++ b/doc/html/phoenix/maintenance/method_in_use.html @@ -0,0 +1,72 @@ + + + +Method in use + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
    +
  • + I have been using the git + branching model to maintain the Boost Phoenix. +
  • +
  • + I have been making most of the changes on branch develop or on branches + from it. +
    • + I test the changes on the develop branch. +
    +
  • +
  • + When I want to move things from develop to master I first branch from + develop a new branch which I give a version number of my own within Phoenix. +
    • + I can then test that before merging it into master. +
    +
  • +
  • + I now also have a separate branch for developing and testing documentation + changes. +
    • + I move selected changes from documentation onto the develop branch + and then onto master branch. +
    +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/maintenance/my_understanding_of_how_maintenance_works.html b/doc/html/phoenix/maintenance/my_understanding_of_how_maintenance_works.html new file mode 100644 index 0000000..c84d54a --- /dev/null +++ b/doc/html/phoenix/maintenance/my_understanding_of_how_maintenance_works.html @@ -0,0 +1,82 @@ + + + +My Understanding of how maintenance works + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ There has been some discussion on the mailing list of how best to get patches + available to users of libraries. This is the understanding I have been using. + I posted this and have had no comments on it. +

+
    +
  • + Maintainers can have write access to the particular library for which + they have responsibility. This includes all the branches and in particular + both develop and master. +
  • +
  • + It is up to the maintainer to put patches and tests onto develop and + see whether there are any remaining problems. +
  • +
  • + It is then up to the maintainer to move the patches and tests from develop + to master. +
      +
    • + This does not have to wait for a release of Boost. +
    • +
    • + It can be done any time and at some point master will then become + the next release. +
    • +
    +
  • +
  • + I do not think that develop is moved to master in any other way. It is + the maintainer who will know when that is the correct action. +
  • +
+

+ If there is more than one maintainer then any of them can do this. Each will + be able to see what has happened from the git log. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules.html b/doc/html/phoenix/modules.html new file mode 100644 index 0000000..74cf3f6 --- /dev/null +++ b/doc/html/phoenix/modules.html @@ -0,0 +1,102 @@ + + + +Modules + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/bind.html b/doc/html/phoenix/modules/bind.html new file mode 100644 index 0000000..b6995f0 --- /dev/null +++ b/doc/html/phoenix/modules/bind.html @@ -0,0 +1,81 @@ + + + +Bind + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Bind +

+ +

+ Binding is the act of tying together a function to some + arguments for deferred (lazy) evaluation. Named lazy + functions require a bit of typing. Unlike (unnamed) lambda expressions, + we need to write a functor somewhere offline, detached from the call site. + If you wish to transform a plain function, member function or member variable + to a lambda expression, bind + is your friend. +

+
+ + + + + +
[Note]Note

+ Take note that binding functions, member functions or member variables + is monomorphic. Rather than binding functions, the preferred way is to + write true generic and polymorphic lazy + functions. +

+

+ There is a set of overloaded bind + template functions. Each bind(x) + function generates a suitable binder object. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/bind/binding_function_objects.html b/doc/html/phoenix/modules/bind/binding_function_objects.html new file mode 100644 index 0000000..67b869d --- /dev/null +++ b/doc/html/phoenix/modules/bind/binding_function_objects.html @@ -0,0 +1,57 @@ + + + +Binding Function Objects + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/bind/bind_function_object.hpp>
+
+

+ Binding function objects serves two purposes: * Partial function application + * Quick adaption of already existing function objects +

+

+ In order to deduce the return type of the function object, it has to implement + the Boost.Result + Of protocol. If the bound function object is polymorphic, the resulting + binding object is polymorphic. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/bind/binding_functions.html b/doc/html/phoenix/modules/bind/binding_functions.html new file mode 100644 index 0000000..899ae06 --- /dev/null +++ b/doc/html/phoenix/modules/bind/binding_functions.html @@ -0,0 +1,70 @@ + + + +Binding Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/bind/bind_function.hpp>
+
+

+ Example, given a function foo: +

+
void foo(int n)
+{
+    std::cout << n << std::endl;
+}
+
+

+ Here's how the function foo + may be bound: +

+
bind(&foo, arg1)
+
+

+ This is now a full-fledged expression that can finally be evaluated by + another function call invocation. A second function call will invoke the + actual foo function. Example: +

+
bind(&foo, arg1)(4);
+
+

+ will print out "4". +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/bind/binding_member_functions.html b/doc/html/phoenix/modules/bind/binding_member_functions.html new file mode 100644 index 0000000..f43992b --- /dev/null +++ b/doc/html/phoenix/modules/bind/binding_member_functions.html @@ -0,0 +1,73 @@ + + + +Binding Member Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/bind/bind_member_function.hpp>
+
+

+ Binding member functions can be done similarly. A bound member function + takes in a pointer or reference to an object as the first argument. For + instance, given: +

+
struct xyz
+{
+    void foo(int) const;
+};
+
+

+ xyz's foo + member function can be bound as: +

+
bind(&xyz::foo, obj, arg1) // obj is an xyz object
+
+

+ Take note that a lazy-member functions expects the first argument to be + a pointer or reference to an object. Both the object (reference or pointer) + and the arguments can be lazily bound. Examples: +

+
xyz obj;
+bind(&xyz::foo, arg1, arg2)     // arg1.foo(arg2)
+bind(&xyz::foo, obj, arg1)      // obj.foo(arg1)
+bind(&xyz::foo, obj, 100)       // obj.foo(100)
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/bind/binding_member_variables.html b/doc/html/phoenix/modules/bind/binding_member_variables.html new file mode 100644 index 0000000..c7dd8d4 --- /dev/null +++ b/doc/html/phoenix/modules/bind/binding_member_variables.html @@ -0,0 +1,75 @@ + + + +Binding Member Variables + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/bind/bind_member_variable.hpp>
+
+

+ Member variables can also be bound much like member functions. Member variables + are not functions. Yet, like the ref(x) + that acts like a nullary function returning a reference to the data, member + variables, when bound, act like a unary function, taking in a pointer or + reference to an object as its argument and returning a reference to the + bound member variable. For instance, given: +

+
struct xyz
+{
+    int v;
+};
+
+

+ xyz::v can be bound as: +

+
bind(&xyz::v, obj) // obj is an xyz object
+
+

+ As noted, just like the bound member function, a bound member variable + also expects the first (and only) argument to be a pointer or reference + to an object. The object (reference or pointer) can be lazily bound. Examples: +

+
xyz obj;
+bind(&xyz::v, arg1)             // arg1.v
+bind(&xyz::v, obj)              // obj.v
+bind(&xyz::v, arg1)(obj) = 4    // obj.v = 4
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/bind/compatibility_with_boost_bind.html b/doc/html/phoenix/modules/bind/compatibility_with_boost_bind.html new file mode 100644 index 0000000..50a7657 --- /dev/null +++ b/doc/html/phoenix/modules/bind/compatibility_with_boost_bind.html @@ -0,0 +1,55 @@ + + + +Compatibility with Boost.Bind + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ phoenix::bind passes the older testcases of the + Boost.Bind library. For those cases it is completely compatible and interchangeable. + Some newer cases have been added to Boost.Bind in 2015 and compatibility + in those cases is not guaranteed. +

+

+ Further tests are needed to check compatibility with std::tr1::bind and + std::bind from the C++11 standard. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/core.html b/doc/html/phoenix/modules/core.html new file mode 100644 index 0000000..cae6b9c --- /dev/null +++ b/doc/html/phoenix/modules/core.html @@ -0,0 +1,60 @@ + + + +Core + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Core +

+ +

+ Actors are composed to create more complex actors in a tree-like hierarchy. + The primitives are atomic entities that are like the leaves in the tree. + Phoenix is extensible. New primitives can be added anytime. Right out of + the box, there are only a few primitives, these are all defined in the Core + module. +

+

+ This section shall deal with these preset primitives. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/core/arguments.html b/doc/html/phoenix/modules/core/arguments.html new file mode 100644 index 0000000..1f0cda0 --- /dev/null +++ b/doc/html/phoenix/modules/core/arguments.html @@ -0,0 +1,195 @@ + + + +Arguments + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/core/argument.hpp>
+
+

+ We use an instance of: +

+
expression::argument<N>::type
+
+

+ to represent the Nth function argument. The argument placeholder acts as + an imaginary data-bin where a function argument will be placed. +

+
+ + Predefined + Arguments +
+

+ There are a few predefined instances of expression::argument<N>::type + named arg1..argN, and its BLL + counterpart _1.._N. (where N is a predefined maximum). +

+

+ Here are some sample preset definitions of arg1..argN +

+
namespace placeholders
+{
+    expression::argument<1>::type const arg1 = {};
+    expression::argument<2>::type const arg2 = {};
+    expression::argument<3>::type const arg3 = {};
+}
+
+

+ and its BLL + _1.._N + style counterparts: +

+
namespace placeholders
+{
+    expression::argument<1>::type const _1 = {};
+    expression::argument<2>::type const _2 = {};
+    expression::argument<3>::type const _3 = {};
+}
+
+
+ + + + + +
[Note]Note

+ You can set BOOST_PHOENIX_ARG_LIMIT, + the predefined maximum placeholder index. By default, BOOST_PHOENIX_ARG_LIMIT + is set to BOOST_PHOENIX_LIMIT + (See Actor). +

+
+ + User Defined + Arguments +
+

+ When appropriate, you can define your own argument + names. For example: +

+
expression::argument<1>::type x; // note one based index
+
+

+ x may now be used as a + parameter to a lazy function: +

+
add(x, 6)
+
+

+ which is equivalent to: +

+
add(arg1, 6)
+
+
+ + Evaluating + an Argument +
+

+ An argument, when evaluated, selects the Nth argument from the those passed + in by the client. +

+

+ For example: +

+
char        c = 'A';
+int         i = 123;
+const char* s = "Hello World";
+
+cout << arg1(c) << endl;        //  Get the 1st argument: c
+cout << arg1(i, s) << endl;     //  Get the 1st argument: i
+cout << arg2(i, s) << endl;     //  Get the 2nd argument: s
+
+

+ will print out: +

+
A
+123
+Hello World
+
+
+ + Extra + Arguments +
+

+ In C and C++, a function can have extra arguments that are not at all used + by the function body itself. These extra arguments are simply ignored. +

+

+ Phoenix also allows extra arguments to be passed. For example, recall our + original add function: +

+
add(arg1, arg2)
+
+

+ We know now that partially applying this function results to a function + that expects 2 arguments. However, the library is a bit more lenient and + allows the caller to supply more arguments than is actually required. Thus, + add actually allows 2 + or more arguments. For instance, with: +

+
add(arg1, arg2)(x, y, z)
+
+

+ the third argument z is + ignored. Taking this further, in-between arguments are also ignored. Example: +

+
add(arg1, arg5)(a, b, c, d, e)
+
+

+ Here, arguments b, c, and d are ignored. The function add + takes in the first argument (arg1) + and the fifth argument (arg5). +

+
+ + + + + +
[Note]Note

+ There are a few reasons why enforcing strict arity is not desirable. + A case in point is the callback function. Typical callback functions + provide more information than is actually needed. Lambda functions are + often used as callbacks. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/core/nothing.html b/doc/html/phoenix/modules/core/nothing.html new file mode 100644 index 0000000..0882e6c --- /dev/null +++ b/doc/html/phoenix/modules/core/nothing.html @@ -0,0 +1,53 @@ + + + +Nothing + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/core/nothing.hpp>
+
+

+ Finally, the expression::null<mpl::void_>::type + does nothing; (a "bum", if you will :-) ). There's a sole expression::null<mpl::void_>::type instance named "nothing". + This actor is actually useful in situations where we don't want to do anything. + (See for_ Statement + for example). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/core/references.html b/doc/html/phoenix/modules/core/references.html new file mode 100644 index 0000000..f46fb44 --- /dev/null +++ b/doc/html/phoenix/modules/core/references.html @@ -0,0 +1,117 @@ + + + +References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/core/reference.hpp>
+
+

+ Values are immutable constants. Attempting to modify a value will result + in a compile time error. When we want the function to modify the parameter, + we use a reference instead. For instance, imagine a lazy function add_assign: +

+
void add_assign(T& x, T y) { x += y; } // pseudo code
+
+

+ Here, we want the first function argument, x, to be mutable. Obviously, + we cannot write: +

+
add_assign(1, 2) // error first argument is immutable
+
+

+ In C++, we can pass in a reference to a variable as the first argument + in our example above. Yet, by default, the library forces arguments passed + to partially applied functions to be immutable values (see Values). + To achieve our intent, we use: +

+
expression::reference<T>::type
+
+

+ This is similar to expression::value<T>::type + before but instead holds a reference to a variable. +

+

+ We normally don't instantiate expression::reference<T>::type + objects directly. Instead we use: +

+
ref(v)
+
+

+ For example (where i is + an int variable): +

+
add_assign(ref(i), 2)
+
+
+ + Evaluating + a Reference +
+

+ References are actors. Hence, references can be evaluated. Such invocation + gives the reference's identity. Example: +

+
int i = 3;
+char const* s = "Hello World";
+cout << ref(i)() << ref(s)();
+
+

+ prints out "3 Hello World" +

+
+ + Constant + References +
+

+ Another free function +

+
cref(cv)
+
+

+ may also be used. cref(cv) + creates an expression::reference<T const>::type + object. This is similar to expression::value<T>::type + but when the data to be passed as argument to a function is heavy and expensive + to copy by value, the cref(cv) + offers a lighter alternative. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/core/values.html b/doc/html/phoenix/modules/core/values.html new file mode 100644 index 0000000..afaac46 --- /dev/null +++ b/doc/html/phoenix/modules/core/values.html @@ -0,0 +1,85 @@ + + + +Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Values +

+
#include <boost/phoenix/core/value.hpp>
+
+

+ Whenever we see a constant in a partially applied function, an +

+
expression::value<T>::type
+
+

+ (where T is the type of the constant) is automatically created for us. + For instance: +

+
add(arg1, 6)
+
+

+ Passing a second argument, 6, + an expression::value<T>::type is implicitly created behind the + scenes. This is also equivalent to add(arg1, val(6)). +

+
val(v)
+
+

+ generates an expression::value<T>::type + where T is the type of + x. In most cases, there's + no need to explicitly use val, + but, as we'll see later on, there are situations where this is unavoidable. +

+

+ + Evaluating + a Value +

+

+ Like arguments, values are also actors. As such, values can be evaluated. + Invoking a value gives the value's identity. Example: +

+
cout << val(3)() << val("Hello World")();
+
+

+ prints out "3 Hello World". +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/function.html b/doc/html/phoenix/modules/function.html new file mode 100644 index 0000000..ebb9810 --- /dev/null +++ b/doc/html/phoenix/modules/function.html @@ -0,0 +1,151 @@ + + + +Function + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ The function class template + provides a mechanism for implementing lazily evaluated functions. Syntactically, + a lazy function looks like an ordinary C/C++ function. The function call + looks familiar and feels the same as ordinary C++ functions. However, unlike + ordinary functions, the actual function execution is deferred. +

+
#include <boost/phoenix/function.hpp>
+
+

+ Unlike ordinary function pointers or functor objects that need to be explicitly + bound through the bind function (see Bind), + the argument types of these functions are automatically lazily bound. +

+

+ In order to create a lazy function, we need to implement a model of the + Polymorphic + Function Object concept. For a function that takes N arguments, a model of Polymorphic + Function Object must provide: +

+
    +
  • + An operator() + that takes N arguments, + and implements the function logic. This is also true for ordinary function + pointers. +
  • +
  • + A nested metafunction result<Signature> or nested typedef result_type, + following the Boost.Result + Of Protocol +
  • +
+

+ For example, the following type implements the FunctionEval concept, in order + to provide a lazy factorial function: +

+
struct factorial_impl
+{
+    template <typename Sig>
+    struct result;
+
+    template <typename This, typename Arg>
+    struct result<This(Arg const &)>
+    {
+        typedef Arg type;
+    };
+
+    template <typename Arg>
+    Arg operator()(Arg const & n) const
+    {
+        return (n <= 0) ? 1 : n * (*this)(n-1);
+    }
+};
+
+

+ (See factorial.cpp) +

+

+ Having implemented the factorial_impl + type, we can declare and instantiate a lazy factorial + function this way: +

+
function<factorial_impl> factorial;
+
+

+ Invoking a lazy function such as factorial + does not immediately execute the function object factorial_impl. + Instead, an actor object is created + and returned to the caller. Example: +

+
factorial(arg1)
+
+

+ does nothing more than return an actor. A second function call will invoke + the actual factorial function. Example: +

+
std::cout << factorial(arg1)(4);
+
+

+ will print out "24". +

+

+ Take note that in certain cases (e.g. for function objects with state), an + instance of the model of Polymorphic + Function Object may be passed on to the constructor. Example: +

+
function<factorial_impl> factorial(ftor);
+
+

+ where ftor is an instance of factorial_impl (this is not necessary in this + case as factorial_impl does + not require any state). +

+
+ + + + + +
[Important]Important

+ Take care though when using function objects with state because they are + often copied repeatedly, and state may change in one of the copies, rather + than the original. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/function/adapting_functions.html b/doc/html/phoenix/modules/function/adapting_functions.html new file mode 100644 index 0000000..75dea7f --- /dev/null +++ b/doc/html/phoenix/modules/function/adapting_functions.html @@ -0,0 +1,371 @@ + + + +Adapting Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ If you want to adapt already existing functions or function objects it + will become a repetetive task. Therefor the following boilerplate macros + are provided to help you adapt already exsiting functions, thus reducing + the need to phoenix.modules.bind + functions. +

+
+ +
+ + Description +
+

+ BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY + is a macro that can be used to generate all the necessary boilerplate + to make an arbitrary nullary function a lazy function. +

+
+ + + + + +
[Note]Note

+ These macros generate no global objects. The resulting lazy functions + are real functions that create the lazy function expression object +

+
+ + Synopsis +
+
BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(
+    RETURN_TYPE
+  , LAZY_FUNCTION
+  , FUNCTION
+)
+
+
+ + Semantics +
+

+ The above macro generates all necessary code to have a nullary lazy function + LAZY_FUNCTION which calls + the nullary FUNCTION + that has the return type RETURN_TYPE +

+
+ + Header +
+
#include <boost/phoenix/function/adapt_function.hpp>
+
+
+ + Example +
+
namespace demo
+{
+    int foo()
+    {
+        return 42;
+    }
+}
+
+BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(int, foo, demo::foo)
+
+int main()
+{
+    using boost::phoenix::placeholders::_1;
+
+    assert((_1 + foo())(1) == 43);
+}
+
+
+
+ +
+ + Description +
+

+ BOOST_PHOENIX_ADAPT_FUNCTION + is a macro that can be used to generate all the necessary boilerplate + to make an arbitrary function a lazy function. +

+
+ + Synopsis +
+
BOOST_PHOENIX_ADAPT_FUNCTION(
+    RETURN_TYPE
+  , LAZY_FUNCTION
+  , FUNCTION
+  , FUNCTION_ARITY
+)
+
+
+ + Semantics +
+

+ The above macro generates all necessary code to have a lazy function + LAZY_FUNCTION which calls + FUNCTION that has the + return type RETURN_TYPE + with FUNCTION_ARITY number + of arguments. +

+
+ + Header +
+
#include <boost/phoenix/function/adapt_function.hpp>
+
+
+ + Example +
+
namespace demo
+{
+    int plus(int a, int b)
+    {
+        return a + b;
+    }
+
+    template <typename T>
+    T
+    plus(T a, T b, T c)
+    {
+        return a + b + c;
+    }
+}
+
+BOOST_PHOENIX_ADAPT_FUNCTION(int, plus, demo::plus, 2)
+
+BOOST_PHOENIX_ADAPT_FUNCTION(
+    typename remove_reference<A0>::type
+  , plus
+  , demo::plus
+  , 3
+)
+
+int main()
+{
+    using boost::phoenix::arg_names::arg1;
+    using boost::phoenix::arg_names::arg2;
+
+    int a = 123;
+    int b = 256;
+
+    assert(plus(arg1, arg2)(a, b) == a+b);
+    assert(plus(arg1, arg2, 3)(a, b) == a+b+3);
+}
+
+
+
+ +
+ + Description +
+

+ BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY + is a macro that can be used to generate all the necessary boilerplate + to make an arbitrary nullary function object a lazy function. +

+
+ + Synopsis +
+
BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(
+    LAZY_FUNCTION
+  , CALLABLE
+)
+
+
+ + Semantics +
+

+ The above macro generates all necessary code to create LAZY_FUNCTION which creates a lazy + function object that represents a nullary call to CALLABLE. + The return type is specified by CALLABLE + conforming to the Boost.Result + Of protocol. +

+
+ + Header +
+
#include <boost/phoenix/function/adapt_callable.hpp>
+
+
+ + Example +
+
namespace demo
+{
+    struct foo
+    {
+        typedef int result_type;
+
+        result_type operator()() const
+        {
+            return 42;
+        }
+    }
+}
+
+BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(foo, demo::foo)
+
+int main()
+{
+    using boost::phoenix::placeholders::_1;
+
+    assert((_1 + foo())(1) == 43);
+}
+
+
+
+ +
+ + Description +
+

+ BOOST_PHOENIX_ADAPT_CALLABLE + is a macro that can be used to generate all the necessary boilerplate + to make an arbitrary function object a lazy function. +

+
+ + Synopsis +
+
BOOST_PHOENIX_ADAPT_CALLABLE(
+    LAZY_FUNCTION
+  , FUNCTION_NAME
+  , FUNCTION_ARITY
+)
+
+
+ + Semantics +
+

+ The above macro generates all necessary code to create LAZY_FUNCTION which creates a lazy + function object that represents a call to CALLABLE + with FUNCTION_ARITY arguments. + The return type is specified by CALLABLE + conforming to the Boost.Result + Of protocol. +

+
+ + Header +
+
#include <boost/phoenix/function/adapt_callable.hpp>
+
+
+ + Example +
+
namespace demo
+{
+    struct plus
+    {
+        template <typename Sig>
+        struct result;
+
+        template <typename This, typename A0, typename A1>
+        struct result<This(A0, A1)>
+            : remove_reference<A0>
+        {};
+
+        template <typename This, typename A0, typename A1, typename A2>
+        struct result<This(A0, A1, A2)>
+            : remove_reference<A0>
+        {};
+
+        template <typename A0, typename A1>
+        A0 operator()(A0 const & a0, A1 const & a1) const
+        {
+            return a0 + a1;
+        }
+
+        template <typename A0, typename A1, typename A2>
+        A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const
+        {
+            return a0 + a1 + a2;
+        }
+    };
+}
+
+BOOST_PHOENIX_ADAPT_CALLABLE(plus, demo::plus, 2)
+
+BOOST_PHOENIX_ADAPT_CALLABLE(plus, demo::plus, 3)
+
+int main()
+{
+    using boost::phoenix::arg_names::arg1;
+    using boost::phoenix::arg_names::arg2;
+
+    int a = 123;
+    int b = 256;
+
+    assert(plus(arg1, arg2)(a, b) == a+b);
+    assert(plus(arg1, arg2, 3)(a, b) == a+b+3);
+}
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/object.html b/doc/html/phoenix/modules/object.html new file mode 100644 index 0000000..3643ae7 --- /dev/null +++ b/doc/html/phoenix/modules/object.html @@ -0,0 +1,56 @@ + + + +Object + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Object +

+ +

+ The Object module deals with object construction, destruction and conversion. + The module provides "lazy" versions of C++'s + object constructor, new, delete, static_cast, + dynamic_cast, const_cast and reinterpret_cast. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/object/casts.html b/doc/html/phoenix/modules/object/casts.html new file mode 100644 index 0000000..bc8adaa --- /dev/null +++ b/doc/html/phoenix/modules/object/casts.html @@ -0,0 +1,72 @@ + + + +Casts + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Casts +

+

+ Lazy casts... +

+
#include <boost/phoenix/object/static_cast.hpp>
+#include <boost/phoenix/object/dynamic_cast.hpp>
+#include <boost/phoenix/object/const_cast.hpp>
+#include <boost/phoenix/object/reinterpret_cast.hpp>
+
+

+ The set of lazy C++ cast template functions provide a way of lazily casting + an object of a certain type to another type. The syntax resembles the well + known C++ casts. Take note however that the lazy versions have a trailing + underscore. +

+
static_cast_<T>(lambda_expression)
+dynamic_cast_<T>(lambda_expression)
+const_cast_<T>(lambda_expression)
+reinterpret_cast_<T>(lambda_expression)
+
+

+ Example: +

+
static_cast_<Base*>(&arg1)
+
+

+ Static-casts the address of arg1 + to a Base*. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/object/construction.html b/doc/html/phoenix/modules/object/construction.html new file mode 100644 index 0000000..0c9d103 --- /dev/null +++ b/doc/html/phoenix/modules/object/construction.html @@ -0,0 +1,81 @@ + + + +Construction + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Lazy constructors... +

+
#include <boost/phoenix/object/construct.hpp>
+
+

+ Lazily construct an object from an arbitrary set of arguments: +

+
construct<T>(ctor_arg1, ctor_arg2, ..., ctor_argN);
+
+

+ where the given parameters are the parameters to the constructor of the + object of type T (This implies, that type T is expected to have a constructor + with a corresponding set of parameter types.). +

+

+ Example: +

+
construct<std::string>(arg1, arg2)
+
+

+ Constructs a std::string from arg1 + and arg2. +

+
+ + + + + +
[Note]Note

+ The maximum number of actual parameters is limited by the preprocessor + constant BOOST_PHOENIX_COMPOSITE_LIMIT. Note though, that this limit + should not be greater than BOOST_PHOENIX_LIMIT. By default, BOOST_PHOENIX_COMPOSITE_LIMIT is set + to BOOST_PHOENIX_LIMIT + (See Actor). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/object/delete.html b/doc/html/phoenix/modules/object/delete.html new file mode 100644 index 0000000..4af263c --- /dev/null +++ b/doc/html/phoenix/modules/object/delete.html @@ -0,0 +1,62 @@ + + + +Delete + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Delete +

+

+ Lazy delete... +

+
#include <boost/phoenix/object/delete.hpp>
+
+

+ Lazily delete an object, from the heap: +

+
delete_(arg);
+
+

+ where arg is assumed to be a pointer to an object. +

+

+ Example: +

+
delete_<std::string>(arg1) // note the spelling of delete_ (with trailing underscore)
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/object/new.html b/doc/html/phoenix/modules/object/new.html new file mode 100644 index 0000000..5313272 --- /dev/null +++ b/doc/html/phoenix/modules/object/new.html @@ -0,0 +1,81 @@ + + + +New + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+New +

+

+ Lazy new... +

+
#include <boost/phoenix/object/new.hpp>
+
+

+ Lazily construct an object, on the heap, from an arbitrary set of arguments: +

+
new_<T>(ctor_arg1, ctor_arg2, ..., ctor_argN);
+
+

+ where the given parameters are the parameters to the contractor of the + object of type T (This implies, that type T is expected to have a constructor + with a corresponding set of parameter types.). +

+

+ Example: +

+
new_<std::string>(arg1, arg2) // note the spelling of new_ (with trailing underscore)
+
+

+ Creates a std::string from arg1 + and arg2 on the heap. +

+
+ + + + + +
[Note]Note

+ The maximum number of actual parameters is limited by the preprocessor + constant BOOST_PHOENIX_COMPOSITE_LIMIT. Note though, that this limit + should not be greater than BOOST_PHOENIX_LIMIT. By default, BOOST_PHOENIX_COMPOSITE_LIMIT is set + to BOOST_PHOENIX_LIMIT + (See Actor). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/operator.html b/doc/html/phoenix/modules/operator.html new file mode 100644 index 0000000..560e2e0 --- /dev/null +++ b/doc/html/phoenix/modules/operator.html @@ -0,0 +1,369 @@ + + + +Operator + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/operator.hpp>
+
+

+ This facility provides a mechanism for lazily evaluating operators. Syntactically, + a lazy operator looks and feels like an ordinary C/C++ infix, prefix or postfix + operator. The operator application looks the same. However, unlike ordinary + operators, the actual operator execution is deferred. Samples: +

+
arg1 + arg2
+1 + arg1 * arg2
+1 / -arg1
+arg1 < 150
+
+

+ We have seen the lazy operators in action (see Quick + Start - Lazy Operators). Let's go back and examine them a little bit + further: +

+
std::find_if(c.begin(), c.end(), arg1 % 2 == 1)
+
+

+ Through operator overloading, the expression arg1 + % 2 == 1 actually + generates an actor. This actor object is passed on to STL's find_if function. From the viewpoint of + STL, the expression is simply a function object expecting a single argument + of the containers value_type. For each element in c, + the element is passed on as an argument arg1 + to the actor (function object). The actor checks if this is an odd value + based on the expression arg1 % 2 == + 1 where arg1 is replaced by the container's + element. +

+

+ Like lazy functions (see Function), + lazy operators are not immediately executed when invoked. Instead, an actor + (see Actor) object is created and returned + to the caller. Example: +

+
(arg1 + arg2) * arg3
+
+

+ does nothing more than return an actor. A second function call will evaluate + the actual operators. Example: +

+
std::cout << ((arg1 + arg2) * arg3)(4, 5, 6);
+
+

+ will print out "54". +

+

+ Operator expressions are lazily evaluated following four simple rules: +

+
    +
  1. + A binary operator, except ->* + will be lazily evaluated when at least one of its + operands is an actor object (see Actor). +
  2. +
  3. + Unary operators are lazily evaluated if their argument is an actor object. +
  4. +
  5. + Operator ->* is lazily + evaluated if the left hand argument is an actor object. +
  6. +
  7. + The result of a lazy operator is an actor object that can in turn allow + the applications of rules 1, 2 and 3. +
  8. +
+

+ For example, to check the following expression is lazily evaluated: +

+
-(arg1 + 3 + 6)
+
+
    +
  1. + Following rule 1, arg1 + 3 is + lazily evaluated since arg1 + is an actor (see Arguments). +
  2. +
  3. + The result of this arg1 + 3 expression + is an actor object, following rule 4. +
  4. +
  5. + Continuing, arg1 + + 3 + 6 is again lazily evaluated. Rule 2. +
  6. +
  7. + By rule 4 again, the result of arg1 + + 3 + 6 is + an actor object. +
  8. +
  9. + As arg1 + + 3 + 6 is an actor, -(arg1 + 3 + 6) is lazily evaluated. Rule 2. +
  10. +
+

+ Lazy-operator application is highly contagious. In most cases, a single + argN actor infects all its + immediate neighbors within a group (first level or parenthesized expression). +

+

+ Note that at least one operand of any operator must be a valid actor for + lazy evaluation to take effect. To force lazy evaluation of an ordinary expression, + we can use ref(x), val(x) or cref(x) + to transform an operand into a valid actor object (see Core). + For example: +

+
1 << 3;      // Immediately evaluated
+val(1) << 3; // Lazily evaluated
+
+
+ + Supported + operators +
+
+ + Unary + operators +
+
prefix:   ~, !, -, +, ++, --, & (reference), * (dereference)
+postfix:  ++, --
+
+
+ + Binary + operators +
+
=, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
++, -, *, /, %, &, |, ^, <<, >>
+==, !=, <, >, <=, >=
+&&, ||, ->*
+
+
+ + Ternary + operator +
+
if_else(c, a, b)
+
+

+ The ternary operator deserves special mention. Since C++ does not allow us + to overload the conditional expression: c + ? a : b, the + if_else pseudo function is provided for this purpose. The behavior is identical, + albeit in a lazy manner. +

+
+ + Member + pointer operator +
+
a->*member_object_pointer
+a->*member_function_pointer
+
+

+ The left hand side of the member pointer operator must be an actor returning + a pointer type. The right hand side of the member pointer operator may be + either a pointer to member object or pointer to member function. +

+

+ If the right hand side is a member object pointer, the result is an actor + which, when evaluated, returns a reference to that member. For example: +

+
struct A
+{
+    int member;
+};
+
+A* a = new A;
+...
+
+(arg1->*&A::member)(a); // returns member a->member
+
+

+ If the right hand side is a member function pointer, the result is an actor + which, when invoked, calls the specified member function. For example: +

+
struct A
+{
+    int func(int);
+};
+
+A* a = new A;
+int i = 0;
+
+(arg1->*&A::func)(arg2)(a, i); // returns a->func(i)
+
+
+ + Include + Files +
+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Operators +

+
+

+ File +

+
+

+ -, +, + ++, --, +=, + -=, *=, /=, + %=, *, /, + % +

+
+

+ #include <boost/phoenix/operator/arithmetic.hpp> +

+
+

+ &=, |=, ^=, + <<=, >>=, &, + |, ^, + <<, >> +

+
+

+ #include <boost/phoenix/operator/bitwise.hpp> +

+
+

+ ==, !=, <, + <=, >, >= +

+
+

+ #include <boost/phoenix/operator/comparison.hpp> +

+
+

+ <<, >> +

+
+

+ #include <boost/phoenix/operator/io.hpp> +

+
+

+ !, &&, || +

+
+

+ #include <boost/phoenix/operator/logical.hpp> +

+
+

+ &x, + *p, + =, [] +

+
+

+ #include <boost/phoenix/operator/self.hpp> +

+
+

+ if_else(c, + a, + b) +

+
+

+ #include <boost/phoenix/operator/if_else.hpp> +

+
+

+ ->* +

+
+

+ #include <boost/phoenix/operator/member.hpp> +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/scope.html b/doc/html/phoenix/modules/scope.html new file mode 100644 index 0000000..e95a9c8 --- /dev/null +++ b/doc/html/phoenix/modules/scope.html @@ -0,0 +1,67 @@ + + + +Scope + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Scope +

+ +

+ Up until now, the most basic ingredient is missing: creation of and access + to local variables in the stack. When recursion comes into play, you will + soon realize the need to have true local variables. It may seem that we do + not need this at all since an unnamed lambda function cannot call itself + anyway; at least not directly. With some sort of arrangement, situations + will arise where a lambda function becomes recursive. A typical situation + occurs when we store a lambda function in a Boost.Function, + essentially naming the unnamed lambda. +

+

+ There will also be situations where a lambda function gets passed as an argument + to another function. This is a more common situation. In this case, the lambda + function assumes a new scope; new arguments and possibly new local variables. +

+

+ This section deals with local variables and nested lambda scopes. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/scope/lambda.html b/doc/html/phoenix/modules/scope/lambda.html new file mode 100644 index 0000000..36a440a --- /dev/null +++ b/doc/html/phoenix/modules/scope/lambda.html @@ -0,0 +1,195 @@ + + + +lambda + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+lambda +

+
#include <boost/phoenix/scope/lambda.hpp>
+
+

+ A lot of times, you'd want to write a lazy function that accepts one or + more functions (higher order functions). STL algorithms come to mind, for + example. Consider a lazy version of stl::for_each: +

+
struct for_each_impl
+{
+    template <typename C, typename F>
+    struct result
+    {
+        typedef void type;
+    };
+
+    template <typename C, typename F>
+    void operator()(C& c, F f) const
+    {
+        std::for_each(c.begin(), c.end(), f);
+    }
+};
+
+function<for_each_impl> const for_each = for_each_impl();
+
+

+ Notice that the function accepts another function, f + as an argument. The scope of this function, f, + is limited within the operator(). When f + is called inside std::for_each, it exists in a new scope, along + with new arguments and, possibly, local variables. This new scope is not + at all related to the outer scopes beyond the operator(). +

+

+ Simple syntax: +

+
lambda
+[
+    lambda-body
+]
+
+

+ Like let, local variables + may be declared, allowing 1..N local variable declarations (where N == + BOOST_PHOENIX_LOCAL_LIMIT): +

+
lambda(local-declarations)
+[
+    lambda-body
+]
+
+

+ The same restrictions apply with regard to scope and visibility. The RHS + (right hand side lambda-expression) of each local-declaration cannot refer + to any LHS local-id. The local-ids are not in scope yet; they will be in + scope only in the lambda-body: +

+
lambda(
+    _a = 1
+  , _b = _a // Error: _a is not in scope yet
+)
+
+

+ See let Visibility for more information. +

+

+ Example: Using our lazy for_each + let's print all the elements in a container: +

+
for_each(arg1, lambda[cout << arg1])
+
+

+ As far as the arguments are concerned (arg1..argN), the scope in which + the lambda-body exists is totally new. The left arg1 + refers to the argument passed to for_each + (a container). The right arg1 + refers to the argument passed by std::for_each + when we finally get to call operator() in our for_each_impl + above (a container element). +

+

+ Yet, we may wish to get information from outer scopes. While we do not + have access to arguments in outer scopes, what we still have is access + to local variables from outer scopes. We may only be able to pass argument + related information from outer lambda + scopes through the local variables. +

+
+ + + + + +
[Note]Note

+ This is a crucial difference between let + and lambda: let does not introduce new arguments; + lambda does. +

+

+ Another example: Using our lazy for_each, + and a lazy push_back: +

+
struct push_back_impl
+{
+    template <typename C, typename T>
+    struct result
+    {
+        typedef void type;
+    };
+
+    template <typename C, typename T>
+    void operator()(C& c, T& x) const
+    {
+        c.push_back(x);
+    }
+};
+
+function<push_back_impl> const push_back = push_back_impl();
+
+

+ write a lambda expression that accepts: +

+
    +
  1. + a 2-dimensional container (e.g. vector<vector<int> >) +
  2. +
  3. + a container element (e.g. int) +
  4. +
+

+ and pushes-back the element to each of the vector<int>. +

+

+ Solution: +

+
for_each(arg1,
+    lambda(_a = arg2)
+    [
+        push_back(arg1, _a)
+    ]
+)
+
+

+ Since we do not have access to the arguments of the outer scopes beyond + the lambda-body, we introduce a local variable _a + that captures the second outer argument: arg2. + Hence: _a = arg2. This local variable is visible inside the lambda scope. +

+

+ (See lambda.cpp) +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/scope/let.html b/doc/html/phoenix/modules/scope/let.html new file mode 100644 index 0000000..af50e70 --- /dev/null +++ b/doc/html/phoenix/modules/scope/let.html @@ -0,0 +1,191 @@ + + + +let + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+let +

+
#include <boost/phoenix/scope/let.hpp>
+
+

+ You declare local variables using the syntax: +

+
let(local-declarations)
+[
+    let-body
+]
+
+

+ let allows 1..N local variable + declarations (where N == BOOST_PHOENIX_LOCAL_LIMIT). + Each declaration follows the form: +

+
local-id = lambda-expression
+
+
+ + + + + +
[Note]Note

+ You can set BOOST_PHOENIX_LOCAL_LIMIT, + the predefined maximum local variable declarations in a let expression. + By default, BOOST_PHOENIX_LOCAL_LIMIT + is set to BOOST_PHOENIX_LIMIT. +

+

+ Example: +

+
let(_a = 123, _b = 456)
+[
+    _a + _b
+]
+
+

+ Reference Preservation +

+

+ The type of the local variable assumes the type of the lambda- expression. + Type deduction is reference preserving. For example: +

+
let(_a = arg1, _b = 456)
+
+

+ _a assumes the type of + arg1: a reference to an + argument, while _b has + type int. +

+

+ Consider this: +

+
int i = 1;
+
+let(_a = arg1)
+[
+    cout << --_a << ' '
+]
+(i);
+
+cout << i << endl;
+
+

+ the output of above is : 0 0 +

+

+ While with this: +

+
int i = 1;
+
+let(_a = val(arg1))
+[
+    cout << --_a << ' '
+]
+(i);
+
+cout << i << endl;
+
+

+ the output is : 0 1 +

+

+ Reference preservation is necessary because we need to have L-value access + to outer lambda-scopes (especially the arguments). args + and refs are L-values. + vals are R-values. +

+

+ Visibility +

+

+ The scope and lifetimes of the local variables is limited within the let-body. + let blocks can be nested. + A local variable may hide an outer local variable. For example: +

+
let(_x = _1, _y = _2)
+[
+    // _x here is an int: 1
+
+   let(_x = _3) // hides the outer _x
+   [
+       cout << _x << _y // prints "Hello, World"
+   ]
+](1," World","Hello,");
+
+

+ The actual values of the parameters _1, _2 and _3 are supplied from the + bracketed list at the end of the let. +

+

+ There is currently a limitation that the inner let + cannot be supplied with a constant e.g. let(_x = 1). +

+

+ The RHS (right hand side lambda-expression) of each local-declaration cannot + refer to any LHS local-id. At this point, the local-ids are not in scope + yet; they will only be in scope in the let-body. The code below is in error: +

+
let(
+    _a = 1
+  , _b = _a // Error: _a is not in scope yet
+)
+[
+    // _a and _b's scope starts here
+    /*. body .*/
+]
+
+

+ However, if an outer let scope is available, this will be searched. Since + the scope of the RHS of a local-declaration is the outer scope enclosing + the let, the RHS of a local-declaration can refer to a local variable of + an outer scope: +

+
let(_a = 1)
+[
+    let(
+        _a = _1
+      , _b = _a // Ok. _a refers to the outer _a
+    )
+    [
+        /*. body .*/
+    ]
+](1)
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/scope/local_variables.html b/doc/html/phoenix/modules/scope/local_variables.html new file mode 100644 index 0000000..d004a1a --- /dev/null +++ b/doc/html/phoenix/modules/scope/local_variables.html @@ -0,0 +1,70 @@ + + + +Local Variables + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/scope/local_variable.hpp>
+
+

+ We use an instance of: +

+
expression::local_variable<Key>::type
+
+

+ to represent a local variable. The local variable acts as an imaginary + data-bin where a local, stack based data will be placed. Key is an arbitrary type that is used + to identify the local variable. Example: +

+
struct size_key;
+expression::local_variable<size_key>::type size;
+
+

+ Predefined Local Variables +

+

+ There are a few predefined instances of expression::local_variable<Key>::type + named _a.._z that you can already use. To make + use of them, simply use the namespace + boost::phoenix::local_names: +

+
using namespace boost::phoenix::local_names;
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement.html b/doc/html/phoenix/modules/statement.html new file mode 100644 index 0000000..2e63602 --- /dev/null +++ b/doc/html/phoenix/modules/statement.html @@ -0,0 +1,115 @@ + + + +Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ Lazy statements... +

+

+ The expressions presented so far are sufficiently powerful to construct quite + elaborate structures. We have presented lazy-functions and lazy-operators. + How about lazy-statements? First, an appetizer: +

+

+ Print all odd-numbered contents of an STL container using std::for_each + (all_odds.cpp): +

+
std::for_each(c.begin(), c.end(),
+    if_(arg1 % 2 == 1)
+    [
+        cout << arg1 << ' '
+    ]
+);
+
+

+ Huh? Is that valid C++? Read on... +

+

+ Yes, it is valid C++. The sample code above is as close as you can get to + the syntax of C++. This stylized C++ syntax differs from actual C++ code. + First, the if has a trailing + underscore. Second, the block uses square brackets instead of the familiar + curly braces {}. +

+
+ + + + + +
[Note]Note
+

+ C++ in C++? +

+

+ In as much as Spirit + attempts to mimic EBNF in C++, Phoenix attempts to mimic C++ in C++!!! +

+
+
+ + + + + +
[Note]Note

+ Unlike lazy functions and lazy operators, lazy statements always return + void. +

+

+ Here are more examples with annotations. The code almost speaks for itself. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/___do_while_____statement.html b/doc/html/phoenix/modules/statement/___do_while_____statement.html new file mode 100644 index 0000000..43b7023 --- /dev/null +++ b/doc/html/phoenix/modules/statement/___do_while_____statement.html @@ -0,0 +1,74 @@ + + + +do_while_ Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/statement/do_while.hpp>
+
+

+ The syntax is: +

+
do_
+[
+    sequenced_statements
+]
+.while_(conditional_expression)
+
+

+ Again, take note that while + has a leading dot and a trailing underscore: .while_ +

+

+ Example: This code is almost the same as the previous example above with + a slight twist in logic. +

+
std::for_each(c.begin(), c.end(),
+    (
+        do_
+        [
+            cout << arg1 << ", "
+        ]
+        .while_(arg1--),
+        cout << val("\n")
+    )
+);
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/___if_else_____statement.html b/doc/html/phoenix/modules/statement/___if_else_____statement.html new file mode 100644 index 0000000..4956bfb --- /dev/null +++ b/doc/html/phoenix/modules/statement/___if_else_____statement.html @@ -0,0 +1,89 @@ + + + +if_else_ Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/statement/if.hpp>
+
+

+ The syntax is +

+
if_(conditional_expression)
+[
+    sequenced_statements
+]
+.else_
+[
+    sequenced_statements
+]
+
+

+ Take note that else has a + leading dot and a trailing underscore: .else_ +

+

+ Example: This code prints out all the elements and appends " > 5", " + == 5" or " < 5" + depending on the element's actual value: +

+
std::for_each(c.begin(), c.end(),
+    if_(arg1 > 5)
+    [
+        cout << arg1 << " > 5\n"
+    ]
+    .else_
+    [
+        if_(arg1 == 5)
+        [
+            cout << arg1 << " == 5\n"
+        ]
+        .else_
+        [
+            cout << arg1 << " < 5\n"
+        ]
+    ]
+);
+
+

+ Notice how the if_else_ + statement is nested. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/block_statement.html b/doc/html/phoenix/modules/statement/block_statement.html new file mode 100644 index 0000000..b6429a9 --- /dev/null +++ b/doc/html/phoenix/modules/statement/block_statement.html @@ -0,0 +1,92 @@ + + + +Block Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Syntax: +

+
statement,
+statement,
+....
+statement
+
+

+ Basically, these are comma separated statements. Take note that unlike + the C/C++ semicolon, the comma is a separator put in-between + statements. This is like Pascal's semicolon separator, rather than C/C++'s + semicolon terminator. For example: +

+
statement,
+statement,
+statement, // ERROR!
+
+

+ Is an error. The last statement should not have a comma. Block statements + can be grouped using the parentheses. Again, the last statement in a group + should not have a trailing comma. +

+
statement,
+statement,
+(
+    statement,
+    statement
+),
+statement
+
+

+ Outside the square brackets, block statements should be grouped. For example: +

+
std::for_each(c.begin(), c.end(),
+    (
+        do_this(arg1),
+        do_that(arg1)
+    )
+);
+
+

+ Wrapping a comma operator chain around a parentheses pair blocks the interpretation + as an argument separator. The reason for the exception for the square bracket + operator is that the operator always takes exactly one argument, so it + "transforms" any attempt at multiple arguments with a comma operator + chain (and spits out an error for zero arguments). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/for_statement.html b/doc/html/phoenix/modules/statement/for_statement.html new file mode 100644 index 0000000..62df194 --- /dev/null +++ b/doc/html/phoenix/modules/statement/for_statement.html @@ -0,0 +1,82 @@ + + + +for_ Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/statement/for.hpp>
+
+

+ The syntax is: +

+
for_(init_statement, conditional_expression, step_statement)
+[
+    sequenced_statements
+]
+
+

+ It is again very similar to the C++ for statement. Take note that the init_statement, + conditional_expression and step_statement are separated by the comma instead of the semi-colon + and each must be present (i.e. for_(,,) is invalid). This is a case where the + nothing + actor can be useful. +

+

+ Example: This code prints each element N times where N is the element's + value. A newline terminates the printout of each value. +

+
int iii;
+std::for_each(c.begin(), c.end(),
+    (
+        for_(ref(iii) = 0, ref(iii) < arg1, ++ref(iii))
+        [
+            cout << arg1 << ", "
+        ],
+        cout << val("\n")
+    )
+);
+
+

+ As before, all these are lazily evaluated. The result of such statements + are in fact expressions that are passed on to STL's for_each function. + In the viewpoint of for_each, + what was passed is just a functor, no more, no less. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/if__statement.html b/doc/html/phoenix/modules/statement/if__statement.html new file mode 100644 index 0000000..1fad754 --- /dev/null +++ b/doc/html/phoenix/modules/statement/if__statement.html @@ -0,0 +1,55 @@ + + + +if_ Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/statement/if.hpp>
+
+

+ We have seen the if_ statement. + The syntax is: +

+
if_(conditional_expression)
+[
+    sequenced_statements
+]
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/switch__statement.html b/doc/html/phoenix/modules/statement/switch__statement.html new file mode 100644 index 0000000..dc6bf1a --- /dev/null +++ b/doc/html/phoenix/modules/statement/switch__statement.html @@ -0,0 +1,75 @@ + + + +switch_ Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/statement/switch.hpp>
+
+

+ The syntax is: +

+
switch_(integral_expression)
+[
+    case_<integral_value>(sequenced_statements),
+    ...
+    default_<integral_value>(sequenced_statements)
+]
+
+

+ A comma separated list of cases, and an optional default can be provided. + Note unlike a normal switch statement, cases do not fall through. +

+

+ Example: This code prints out "one", + "two" or "other value" depending on the + element's actual value: +

+
std::for_each(c.begin(), c.end(),
+    switch_(arg1)
+    [
+        case_<1>(std::cout << val("one") << '\n'),
+        case_<2>(std::cout << val("two") << '\n'),
+        default_(std::cout << val("other value") << '\n')
+    ]
+);
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/throw_.html b/doc/html/phoenix/modules/statement/throw_.html new file mode 100644 index 0000000..a752f80 --- /dev/null +++ b/doc/html/phoenix/modules/statement/throw_.html @@ -0,0 +1,85 @@ + + + +throw_ + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+throw_ +

+
#include <boost/phoenix/statement/throw.hpp>
+
+

+ As a natural companion to the try/catch support, the statement module provides + lazy throwing and re-throwing of exceptions. +

+

+ The syntax to throw an exception is: +

+
throw_(exception_expression)
+
+

+ The syntax to re-throw an exception is: +

+
throw_()
+
+

+ Example: This code extends the try/catch example, re-throwing exceptions + derived from runtime_error or exception, and translating other exception + types to runtime_errors. +

+
try_
+[
+    f(arg1)
+]
+.catch_<runtime_error>()
+[
+    cout << val("caught runtime error or derived\n"),
+    throw_()
+]
+.catch_<exception>()
+[
+    cout << val("caught exception or derived\n"),
+    throw_()
+]
+.catch_all
+[
+    cout << val("caught some other type of exception\n"),
+    throw_(runtime_error("translated exception"))
+]
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/try__catch__statement.html b/doc/html/phoenix/modules/statement/try__catch__statement.html new file mode 100644 index 0000000..623f129 --- /dev/null +++ b/doc/html/phoenix/modules/statement/try__catch__statement.html @@ -0,0 +1,90 @@ + + + +try_ catch_ Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/statement/try_catch.hpp>
+
+

+ The syntax is: +

+
try_
+[
+    sequenced_statements
+]
+.catch_<exception_type>()
+[
+    sequenced_statements
+]
+...
+.catch_all
+[
+    sequenced_statement
+]
+
+

+ Note the usual underscore after try and catch, and the extra parentheses + required after the catch. +

+

+ Example: The following code calls the (lazy) function f + for each element, and prints messages about different exception types it + catches. +

+
try_
+[
+    f(arg1)
+]
+.catch_<runtime_error>()
+[
+    cout << val("caught runtime error or derived\n")
+]
+.catch_<exception>()
+[
+    cout << val("caught exception or derived\n")
+]
+.catch_all
+[
+    cout << val("caught some other type of exception\n")
+]
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/statement/while__statement.html b/doc/html/phoenix/modules/statement/while__statement.html new file mode 100644 index 0000000..8e7af1a --- /dev/null +++ b/doc/html/phoenix/modules/statement/while__statement.html @@ -0,0 +1,70 @@ + + + +while_ Statement + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/statement/while.hpp>
+
+

+ The syntax is: +

+
while_(conditional_expression)
+[
+    sequenced_statements
+]
+
+

+ Example: This code decrements each element until it reaches zero and prints + out the number at each step. A newline terminates the printout of each + value. +

+
std::for_each(c.begin(), c.end(),
+    (
+        while_(arg1--)
+        [
+            cout << arg1 << ", "
+        ],
+        cout << val("\n")
+    )
+);
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/stl.html b/doc/html/phoenix/modules/stl.html new file mode 100644 index 0000000..f5f37c9 --- /dev/null +++ b/doc/html/phoenix/modules/stl.html @@ -0,0 +1,53 @@ + + + +STL + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+STL +

+ +
#include <boost/phoenix/stl.hpp>
+
+

+ This section summarizes the lazy equivalents of C++ Standard Library functionality +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/stl/algorithm.html b/doc/html/phoenix/modules/stl/algorithm.html new file mode 100644 index 0000000..220e278 --- /dev/null +++ b/doc/html/phoenix/modules/stl/algorithm.html @@ -0,0 +1,1143 @@ + + + +Algorithm + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/stl/algorithm.hpp>
+
+

+ The algorithm module provides wrappers for the standard algorithms in the + <algorithm> and <numeric> + headers. +

+

+ The algorithms are divided into the categories iteration, transformation + and querying, modeling the Boost.MPL + library. The different algorithm classes can be included using the headers: +

+
#include <boost/phoenix/stl/algorithm/iteration.hpp>
+#include <boost/phoenix/stl/algorithm/transformation.hpp>
+#include <boost/phoenix/stl/algorithm/querying.hpp>
+
+

+ The functions of the algorithm module take ranges as arguments where appropriate. + This is different to the standard library, but easy enough to pick up. + Ranges are described in detail in the Boost.Range + library. +

+

+ For example, using the standard copy algorithm to copy between 2 arrays: +

+
int array[] = {1, 2, 3};
+int output[3];
+std::copy(array, array + 3, output); // We have to provide iterators
+                                     // to both the start and end of array
+
+

+ The analogous code using the phoenix algorithm module is: +

+
int array[] = {1, 2, 3};
+int output[3];
+copy(arg1, arg2)(array, output); // Notice only 2 arguments, the end of
+                                 // array is established automatically
+
+

+ The Boost.Range + library provides support for standard containers, strings and arrays, and + can be extended to support additional types. +

+

+ The following tables describe the different categories of algorithms, and + their semantics. +

+ +
+

Table 1.6. Iteration Algorithms

+
++++ + + + + + + + + + + + + + + +
+

+ Function +

+
+

+ stl Semantics +

+
+

+ for_each(r, + f) +

+
+

+ for_each(begin(r), + end(r), + f) +

+
+

+ accumulate(r, + o[, + f]) +

+
+

+ accumulate(begin(r), + end(r), + o[, + f]) +

+
+
+
+

Table 1.7. Querying Algorithms

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Function +

+
+

+ stl Semantics +

+
+

+ find(r, + a) +

+
+

+ find(begin(r), + end(r), + a) +

+
+

+ find_if(r, + f) +

+
+

+ find_if(begin(r), + end(r), + f) +

+
+

+ find_end(r1, + r2[, + f]) +

+
+

+ find_end(begin(r1), + end(r1), + begin(r2), + end(r2)[, + f]) +

+
+

+ find_first_of(r1, r2[, f]) +

+
+

+ find_first_of(begin(r1), end(r1), begin(r2), end(r2)[, f]) +

+
+

+ adjacent_find(r[, f]) +

+
+

+ adjacent_find(begin(r), end(r)[, f]) +

+
+

+ count(r, + a) +

+
+

+ count(begin(r), + end(r), + a) +

+
+

+ count_if(r, + f) +

+
+

+ count_if(begin(r), + end(r), + f) +

+
+

+ distance(r) +

+
+

+ distance(begin(r), + end(r)) +

+
+

+ mismatch(r, + i[, + f]) +

+
+

+ mismatch(begin(r), + end(r), + i[, + f]) +

+
+

+ equal(r, + i[, + f]) +

+
+

+ equal(begin(r), + end(r), + i[, + f]) +

+
+

+ search(r1, + r2[, + f]) +

+
+

+ search(begin(r1), + end(r1), + begin(r2), + end(r2)[, + f]) +

+
+

+ lower_bound(r, + a[, + f]) +

+
+

+ lower_bound(begin(r), + end(r), + a[, + f]) +

+
+

+ upper_bound(r, + a[, + f]) +

+
+

+ upper_bound(begin(r), + end(r), + a[, + f]) +

+
+

+ equal_range(r, + a[, + f]) +

+
+

+ equal_range(begin(r), + end(r), + a[, + f]) +

+
+

+ binary_search(r, a[, f]) +

+
+

+ binary_search(begin(r), end(r), a[, f]) +

+
+

+ includes(r1, + r2[, + f]) +

+
+

+ includes(begin(r1), + end(r1), + begin(r2), + end(r2)[, + f]) +

+
+

+ min_element(r[, + f]) +

+
+

+ min_element(begin(r), + end(r)[, + f]) +

+
+

+ max_element(r[, + f]) +

+
+

+ max_element(begin(r), + end(r)[, + f]) +

+
+

+ lexicographical_compare(r1, r2[, f]) +

+
+

+ lexicographical_compare(begin(r1), end(r1), begin(r2), end(r2)[, f]) +

+
+
+
+

Table 1.8. Transformation Algorithms

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Function +

+
+

+ stl Semantics +

+
+

+ copy(r, + o) +

+
+

+ copy(begin(r), + end(r), + o) +

+
+

+ copy_backward(r, o) +

+
+

+ copy_backward(begin(r), end(r), o) +

+
+

+ transform(r, + o, + f) +

+
+

+ transform(begin(r), + end(r), + o, + f) +

+
+

+ transform(r, + i, + o, + f) +

+
+

+ transform(begin(r), + end(r), + i, + o, + f) +

+
+

+ replace(r, + a, + b) +

+
+

+ replace(begin(r), + end(r), + a, + b) +

+
+

+ replace_if(r, + f, + a) +

+
+

+ replace(begin(r), + end(r), + f, + a) +

+
+

+ replace_copy(r, o, a, b) +

+
+

+ replace_copy(begin(r), end(r), o, a, b) +

+
+

+ replace_copy_if(r, o, f, a) +

+
+

+ replace_copy_if(begin(r), end(r), o, f, a) +

+
+

+ fill(r, + a) +

+
+

+ fill(begin(r), + end(r), + a) +

+
+

+ fill_n(r, + n, + a) +

+
+

+ fill_n(begin(r), + n, + a) +

+
+

+ generate(r, + f) +

+
+

+ generate(begin(r), + end(r), + f) +

+
+

+ generate_n(r, + n, + f) +

+
+

+ generate_n(begin(r), + n, + f) +

+
+

+ remove(r, + a) +

+
+

+ remove(begin(r), + end(r), + a) +

+
+

+ remove_if(r, + f) +

+
+

+ remove_if(begin(r), + end(r), + f) +

+
+

+ remove_copy(r, + o, + a) +

+
+

+ remove_copy(begin(r), + end(r), + o, + a) +

+
+

+ remove_copy_if(r, o, f) +

+
+

+ remove_copy_if(begin(r), end(r), o, f) +

+
+

+ unique(r[, + f]) +

+
+

+ unique(begin(r), + end(r)[, + f]) +

+
+

+ unique_copy(r, + o[, + f]) +

+
+

+ unique_copy(begin(r), + end(r), + o[, + f]) +

+
+

+ reverse(r) +

+
+

+ reverse(begin(r), + end(r)) +

+
+

+ reverse_copy(r, o) +

+
+

+ reverse_copy(begin(r), end(r), o) +

+
+

+ rotate(r, + m) +

+
+

+ rotate(begin(r), + m, + end(r)) +

+
+

+ rotate_copy(r, + m, + o) +

+
+

+ rotate_copy(begin(r), + m, + end(r), + o) +

+
+

+ random_shuffle(r[, f]) +

+
+

+ random_shuffle(begin(r), end(r), f) +

+
+

+ partition(r, + f) +

+
+

+ partition(begin(r), + end(r), + f) +

+
+

+ stable_partition(r, f) +

+
+

+ stable_partition(begin(r), end(r), f) +

+
+

+ sort(r[, + f]) +

+
+

+ sort(begin(r), + end(r)[, + f]) +

+
+

+ stable_sort(r[, + f]) +

+
+

+ stable_sort(begin(r), + end(r)[, + f]) +

+
+

+ partial_sort(r, m[, f]) +

+
+

+ partial_sort(begin(r), m, end(r)[, f]) +

+
+

+ partial_sort_copy(r1, r2[, f]) +

+
+

+ partial_sort_copy(begin(r1), end(r1), begin(r2), end(r2)[, f]) +

+
+

+ nth_element(r, + n[, + f]) +

+
+

+ nth_element(begin(r), + n, + end(r)[, + f]) +

+
+

+ merge(r1, + r2, + o[, + f]) +

+
+

+ merge(begin(r1), + end(r1), + begin(r2), + end(r2), + o[, + f]) +

+
+

+ inplace_merge(r, m[, f]) +

+
+

+ inplace_merge(begin(r), m, end(r)[, f]) +

+
+

+ set_union(r1, + r2, + o[, + f]) +

+
+

+ set_union(begin(r1), + end(r1), + begin(r2), + end(r2)[, + f]) +

+
+

+ set_intersection(r1, r2, o[, f]) +

+
+

+ set_intersection(begin(r1), end(r1), begin(r2), end(r2)[, f]) +

+
+

+ set_difference(r1, r2, o[, f]) +

+
+

+ set_difference(begin(r1), end(r1), begin(r2), end(r2)[, f]) +

+
+

+ set_symmetric_difference(r1, r2, o[, f]) +

+
+

+ set_symmetric_difference(begin(r1), end(r1), begin(r2), end(r2)[, f]) +

+
+

+ push_heap(r[, + f]) +

+
+

+ push_heap(begin(r), + end(r)[, + f]) +

+
+

+ pop_heap(r[, + f]) +

+
+

+ pop_heap(begin(r), + end(r)[, + f]) +

+
+

+ make_heap(r[, + f]) +

+
+

+ make_heap(begin(r), + end(r)[, + f]) +

+
+

+ sort_heap(r[, + f]) +

+
+

+ sort_heap(begin(r), + end(r)[, + f]) +

+
+

+ next_permutation(r[, f]) +

+
+

+ next_permutation(begin(r), end(r)[, f]) +

+
+

+ prev_permutation(r[, f]) +

+
+

+ prev_permutation(begin(r), end(r)[, f]) +

+
+

+ inner_product(r, o, a[, f1, f2]) +

+
+

+ inner_product(begin(r), end(r), o[, f1, f2]) +

+
+

+ partial_sum(r, + o[, + f]) +

+
+

+ partial_sum(begin(r), + end(r), + o[, + f]) +

+
+

+ adjacent_difference(r, o[, f]) +

+
+

+ adjacent_difference(begin(r), end(r), o[, f]) +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/modules/stl/container.html b/doc/html/phoenix/modules/stl/container.html new file mode 100644 index 0000000..0288fb9 --- /dev/null +++ b/doc/html/phoenix/modules/stl/container.html @@ -0,0 +1,603 @@ + + + +Container + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
#include <boost/phoenix/stl/container.hpp>
+
+

+ The container module predefines a set of lazy functions that work on STL + containers. These functions provide a mechanism for the lazy evaluation + of the public member functions of the STL containers. The lazy functions + are thin wrappers that simply forward to their respective counterparts + in the STL library. +

+

+ Lazy functions are provided for all of the member functions of the following + containers: +

+
    +
  • + deque +
  • +
  • + list +
  • +
  • + map +
  • +
  • + multimap +
  • +
  • + vector +
  • +
+

+ Indeed, should your class have member functions with the same names and + signatures as those listed below, then it will automatically be supported. + To summarize, lazy functions are provided for member functions: +

+
    +
  • + assign +
  • +
  • + at +
  • +
  • + back +
  • +
  • + begin +
  • +
  • + capacity +
  • +
  • + clear +
  • +
  • + empty +
  • +
  • + end +
  • +
  • + erase +
  • +
  • + front +
  • +
  • + get_allocator +
  • +
  • + insert +
  • +
  • + key_comp +
  • +
  • + max_size +
  • +
  • + pop_back +
  • +
  • + pop_front +
  • +
  • + push_back +
  • +
  • + push_front +
  • +
  • + rbegin +
  • +
  • + rend +
  • +
  • + reserve +
  • +
  • + resize +
  • +
  • + size +
  • +
  • + splice +
  • +
  • + value_comp +
  • +
+

+ The lazy functions' names are the same as the corresponding member function. + The difference is that the lazy functions are free functions and therefore + does not use the member "dot" syntax. +

+
+

Table 1.4. Sample usage

+
++++ + + + + + + + + + + + + + + + + + + +
+

+ "Normal" version +

+
+

+ "Lazy" version +

+
+

+ my_vector.at(5) +

+
+

+ at(arg1, + 5) +

+
+

+ my_list.size() +

+
+

+ size(arg1) +

+
+

+ my_vector1.swap(my_vector2) +

+
+

+ swap(arg1, + arg2) +

+
+
+

+ Notice that member functions with names that clash with stl algorithms + are absent. This will be provided in Phoenix's algorithm module. +

+

+ No support is provided here for lazy versions of operator+=, operator[] etc. Such operators are not specific + to STL containers and lazy versions can therefore be found in operators. +

+

+ The following table describes the container functions and their semantics. +

+ +
+

Table 1.5. Lazy STL Container Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Function +

+
+

+ Semantics +

+
+

+ assign(c, + a[, + b, + c]) +

+
+

+ c.assign(a[, + b, + c]) +

+
+

+ at(c, + i) +

+
+

+ c.at(i) +

+
+

+ back(c) +

+
+

+ c.back() +

+
+

+ begin(c) +

+
+

+ c.begin() +

+
+

+ capacity(c) +

+
+

+ c.capacity() +

+
+

+ clear(c) +

+
+

+ c.clear() +

+
+

+ empty(c) +

+
+

+ c.empty() +

+
+

+ end(c) +

+
+

+ c.end() +

+
+

+ erase(c, + a[, + b]) +

+
+

+ c.erase(a[, + b]) +

+
+

+ front(c) +

+
+

+ c.front() +

+
+

+ get_allocator(c) +

+
+

+ c.get_allocator() +

+
+

+ insert(c, + a[, + b, + c]) +

+
+

+ c.insert(a[, + b, + c]) +

+
+

+ key_comp(c) +

+
+

+ c.key_comp() +

+
+

+ max_size(c) +

+
+

+ c.max_size() +

+
+

+ pop_back(c) +

+
+

+ c.pop_back() +

+
+

+ pop_front(c) +

+
+

+ c.pop_front() +

+
+

+ push_back(c, + d) +

+
+

+ c.push_back(d) +

+
+

+ push_front(c, + d) +

+
+

+ c.push_front(d) +

+
+

+ pop_front(c) +

+
+

+ c.pop_front() +

+
+

+ rbegin(c) +

+
+

+ c.rbegin() +

+
+

+ rend(c) +

+
+

+ c.rend() +

+
+

+ reserve(c, + n) +

+
+

+ c.reserve(n) +

+
+

+ resize(c, + a[, + b]) +

+
+

+ c.resize(a[, + b]) +

+
+

+ size(c) +

+
+

+ c.size() +

+
+

+ splice(c, + a[, + b, + c, + d]) +

+
+

+ c.splice(a[, + b, + c, + d]) +

+
+

+ value_comp(c) +

+
+

+ c.value_comp() +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/organization.html b/doc/html/phoenix/organization.html new file mode 100644 index 0000000..7114b7f --- /dev/null +++ b/doc/html/phoenix/organization.html @@ -0,0 +1,362 @@ + + + +Organization + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Care and attention to detail was given, painstakingly, to the design and implementation + of Phoenix. +

+

+ The library is organized in four layers: +

+
    +
  1. + Actor +
  2. +
  3. + Value, Reference, Arguments +
  4. +
  5. + Function, Operator, Object, Statement, Scope +
  6. +
  7. + STL, Fusion, Bind +
  8. +
+

+ The modules are orthogonal, with no cyclic dependencies. Lower layers do not + depend on higher layers. Modules in a layer do not depend on other modules + in the same layer. This means, for example, that Bind can be completely discarded + if it is not required; or one could perhaps take out Operator and Statement + and just use Function, which may be desirable in a pure FP application. +

+

+ The library has grown from the original Phoenix but still comprises only header + files. There are no object files to link against. +

+

+ + Core +

+

+ The lowest two layers comprise the core. +

+

+ The Actor + is the main concept behind the library. Lazy functions are abstracted as actors. +

+

+ Terminals provide the basic building blocks of functionality within Phoenix. + Expressions are used to combine these terminals together to provide more powerful + functionality. +

+

+ Expressions are composed of zero or more actors. Each actor in a composite + can again be another expression. +

+
+

Table 1.2. Modules

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Module +

+
+

+ Description +

+
+

+ Function +

+
+

+ Lazy functions support (e.g. add) +

+
+

+ Operator +

+
+

+ Lazy operators support (e.g. +) +

+
+

+ Statement +

+
+

+ Lazy statements (e.g. if_, + while_) +

+
+

+ Object +

+
+

+ Lazy casts (e.g. static_cast_), + object creation destruction (e.g. new_, + delete_) +

+
+

+ Scope +

+
+

+ Support for scopes, local variables and lambda-lambda +

+
+

+ Bind +

+
+

+ Lazy functions from free functions, member functions or member variables. +

+
+

+ STL Container +

+
+

+ Set of predefined "lazy" functions that work on STL containers + and sequences (e.g. push_back). +

+
+

+ STL Algorithm +

+
+

+ Set of predefined "lazy" versions of the STL algorithms + (e.g. find_if). +

+
+
+

+ Each module is defined in a header file with the same name. For example, the + core module is defined in <boost/phoenix/core.hpp>. +

+
+

Table 1.3. Includes

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Module +

+
+

+ File +

+
+

+ Core +

+
+

+ #include <boost/phoenix/core.hpp> +

+
+

+ Function +

+
+

+ #include <boost/phoenix/function.hpp> +

+
+

+ Operator +

+
+

+ #include <boost/phoenix/operator.hpp> +

+
+

+ Statement +

+
+

+ #include <boost/phoenix/statement.hpp> +

+
+

+ Object +

+
+

+ #include <boost/phoenix/object.hpp> +

+
+

+ Scope +

+
+

+ #include <boost/phoenix/scope.hpp> +

+
+

+ Bind +

+
+

+ #include <boost/phoenix/bind.hpp> +

+
+

+ Container +

+
+

+ #include <boost/phoenix/stl/container.hpp> +

+
+

+ Algorithm +

+
+

+ #include <boost/phoenix/stl/algorithm.hpp> +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/references.html b/doc/html/phoenix/references.html new file mode 100644 index 0000000..7644901 --- /dev/null +++ b/doc/html/phoenix/references.html @@ -0,0 +1,91 @@ + + + +References + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHome +
+
+ +
    +
  1. + Why Functional Programming Matters, John Hughes, 1989. Available online + at http://www.math.chalmers.se/~rjmh/Papers/whyfp.html. +
  2. +
  3. + Boost.Lambda library, Jaakko Jarvi, 1999-2004 Jaakko Jarvi, Gary Powell. + Available online at http://www.boost.org/libs/lambda/. +
  4. +
  5. + Functional Programming in C++ using the FC++ Library: a short article introducing + FC++, Brian McNamara and Yannis Smaragdakis, August 2003. Available online + at http://cgi.di.uoa.gr/~smaragd/fc++/. +
  6. +
  7. + Side-effects and partial function application in C++, Jaakko Jarvi and + Gary Powell, 2001. Available online at http://osl.iu.edu/~jajarvi/publications/papers/mpool01.pdf. +
  8. +
  9. + Spirit Version 1.8.1, Joel de Guzman, Nov 2004. Available online at http://www.boost.org/libs/spirit/. +
  10. +
  11. + The Boost MPL Library, Aleksey Gurtovoy and David Abrahams, 2002-2004. + Available online at http://www.boost.org/libs/mpl/. +
  12. +
  13. + Generic Programming Redesign of Patterns, Proceedings of the 5th European + Conference on Pattern Languages of Programs, (EuroPLoP'2000) Irsee, Germany, + July 2000. Available online at http://www.coldewey.com/europlop2000/papers/geraud%2Bduret.zip. +
  14. +
  15. + A Gentle Introduction to Haskell, Paul Hudak, John Peterson and Joseph + Fasel, 1999. Available online at http://www.haskell.org/tutorial/. +
  16. +
  17. + Large scale software design, John Lackos, ISBN 0201633620, Addison-Wesley, + July 1996. +
  18. +
  19. + Design Patterns, Elements of Reusable Object-Oriented Software, Erich Gamma, + Richard Helm, Ralph Jhonson, and John Vlissides, Addison-Wesley, 1995. +
  20. +
  21. + The Forwarding Problem: Arguments Peter Dimov, Howard E. Hinnant, Dave + Abrahams, September 09, 2002. Available online: Forwarding + Function Problem. +
  22. +
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/doc/html/phoenix/starter_kit.html b/doc/html/phoenix/starter_kit.html new file mode 100644 index 0000000..486502a --- /dev/null +++ b/doc/html/phoenix/starter_kit.html @@ -0,0 +1,105 @@ + + + +Starter Kit + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ Most "quick starts" only get you a few blocks from where you are. + From there, you are on your own. Yet, typically, you'd want to get to the next + city. This starter kit shall be as minimal as possible, yet packed as much + power as possible. +

+

+ So you are busy and always on the go. You do not wish to spend a lot of time + studying the library. You wish to be spared the details for later when you + need it. For now, all you need to do is to get up to speed as quickly as possible + and start using the library. If this is the case, this is the right place to + start. +

+

+ This section is by no means a thorough discourse of the library. For more information + on Phoenix, please take some time to read the rest of the Documentation. Yet, + if you just want to use the library quickly, now, this chapter will probably + suffice. Rather than taking you to the details of the library, we shall try + to provide you with annotated examples instead. Hopefully, this will get you + into high gear quickly. +

+

+ + Functors + everywhere +

+

+ Phoenix is built on function objects (functors). The functor is the main building + block. We compose functors to build more complex functors... to build more + complex functors... and so on. Almost everything is a functor. +

+
+ + + + + +
[Note]Note

+ Functors are so ubiquitous in Phoenix that, in the manual, the words "functor" + and "function" are used interchangeably. +

+

+ We start with some core functions that are called primitives. + You can think of primitives (such as values, references and arguments) as atoms. +

+

+ Things start to get interesting when we start composing + primitives to form expressions. The expressions + can, in turn, be composed to form even more complex expressions. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/arguments.html b/doc/html/phoenix/starter_kit/arguments.html new file mode 100644 index 0000000..e18cb5e --- /dev/null +++ b/doc/html/phoenix/starter_kit/arguments.html @@ -0,0 +1,77 @@ + + + +Arguments + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Arguments are also functions? You bet! +

+

+ Until now, we have been dealing with expressions returning a nullary function. + Arguments, on the other hand, evaluate to an N-ary function. An argument + represents the Nth argument. There are a few predefined arguments arg1, arg2, + arg3, arg4 and so on (and it's BLL + counterparts: _1, _2, _3, _4 and so on). Examples: +

+
arg1 // one-or-more argument function that returns its first argument
+arg2 // two-or-more argument function that returns its second argument
+arg3 // three-or-more argument function that returns its third argument
+
+

+ argN returns the Nth argument. + Examples: +

+
int i = 3;
+char const* s = "Hello World";
+std::cout << arg1(i) << std::endl;        // prints 3
+std::cout << arg2(i, s) << std::endl;     // prints "Hello World"
+
+

+ (See arguments.cpp) +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/construct__new__delete__casts.html b/doc/html/phoenix/starter_kit/construct__new__delete__casts.html new file mode 100644 index 0000000..2219a60 --- /dev/null +++ b/doc/html/phoenix/starter_kit/construct__new__delete__casts.html @@ -0,0 +1,72 @@ + + + +Construct, New, Delete, Casts + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ You'll probably want to work with objects. There are lazy versions of constructor + calls, new, delete + and the suite of C++ casts. Examples: +

+
construct<std::string>(arg1, arg2)  // constructs a std::string from arg1, arg2
+new_<std::string>(arg1, arg2)       // makes a new std::string from arg1, arg2
+delete_(arg1)                       // deletes arg1 (assumed to be a pointer)
+static_cast_<int*>(arg1)            // static_cast's arg1 to an int*
+
+
+ + + + + +
[Note]Note

+ Take note that, by convention, names that conflict with C++ reserved words + are appended with a single trailing underscore '_' +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/lazy_functions.html b/doc/html/phoenix/starter_kit/lazy_functions.html new file mode 100644 index 0000000..1cf1f09 --- /dev/null +++ b/doc/html/phoenix/starter_kit/lazy_functions.html @@ -0,0 +1,110 @@ + + + +Lazy Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ As you write more lambda functions, you'll notice certain patterns that you + wish to refactor as reusable functions. When you reach that point, you'll + wish that ordinary functions can co-exist with phoenix functions. Unfortunately, + the immediate nature of plain C++ functions make them + incompatible. +

+

+ Lazy functions are your friends. The library provides a facility to make + lazy functions. The code below is a rewrite of the is_odd + function using the facility: +

+
struct is_odd_impl
+{
+    typedef bool result_type;
+
+    template <typename Arg>
+    bool operator()(Arg arg1) const
+    {
+        return arg1 % 2 == 1;
+    }
+};
+
+function<is_odd_impl> is_odd;
+
+
+ + Things + to note: +
+
    +
  • + Result type deduction is implemented with the help of the result_of protocol. + For more information see Boost.Result + Of +
  • +
  • + is_odd_impl implements + the function. +
  • +
  • + is_odd, an instance of + function<is_odd_impl>, + is the lazy function. +
  • +
+

+ Now, is_odd is a truly lazy + function that we can use in conjunction with the rest of phoenix. Example: +

+
std::find_if(c.begin(), c.end(), is_odd(arg1));
+
+

+ (See function.cpp) +

+
+ + Predefined + Lazy Functions +
+

+ The library is chock full of STL savvy, predefined lazy functions covering + the whole of the STL containers, iterators and algorithms. For example, there + are lazy versions of container related operations such as assign, at, back, + begin, pop_back, pop_front, push_back, push_front, etc. (See STL). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/lazy_operators.html b/doc/html/phoenix/starter_kit/lazy_operators.html new file mode 100644 index 0000000..eff868f --- /dev/null +++ b/doc/html/phoenix/starter_kit/lazy_operators.html @@ -0,0 +1,152 @@ + + + +Lazy Operators + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ You can use the usual set of operators to form expressions. Examples: +

+
arg1 * arg1
+ref(x) = arg1 + ref(z)
+arg1 = arg2 + (3 * arg3)
+ref(x) = arg1[arg2] // assuming arg1 is indexable and arg2 is a valid index
+
+

+ Note the expression: 3 * + arg3. This expression is actually + a short-hand equivalent to: val(3) + * arg3. + In most cases, like above, you can get away with it. But in some cases, you + will have to explicitly wrap your values in val. + Rules of thumb: +

+
    +
  • + In a binary expression (e.g. 3 + * arg3), + at least one of the operands must be a phoenix primitive or expression. +
  • +
  • + In a unary expression (e.g. arg1++), the single operand must be a phoenix + primitive or expression. +
  • +
+

+ If these basic rules are not followed, the result is either an error, or + is immediately evaluated. Some examples: +

+
ref(x) = 123    // lazy
+x = 123         // immediate
+
+ref(x)[0]       // lazy
+x[0]            // immediate
+
+ref(x)[ref(i)]  // lazy
+ref(x)[i]       // lazy (equivalent to ref(x)[val(i)])
+x[ref(i)]       // illegal (x is not a phoenix primitive or expression)
+ref(x[ref(i)])  // illegal (x is not a phoenix primitive or expression)
+
+

+ Why are the last two expression illegal? Although operator[] looks as much like a binary operator as + operator= + above it; the difference is that the former must be a member (i.e. x must have an operator[] that takes a phoenix primitive or expression + as its argument). This will most likely not be the case. +

+ +
+ + First + Practical Example +
+

+ We've covered enough ground to present a real world example. We want to find + the first odd number in an STL container. Normally we use a functor (function + object) or a function pointer and pass that in to STL's find_if + generic function: +

+

+ Write a function: +

+
bool
+is_odd(int arg1)
+{
+    return arg1 % 2 == 1;
+}
+
+

+ Pass a pointer to the function to STL's find_if + algorithm: +

+
std::find_if(c.begin(), c.end(), &is_odd)
+
+

+ Using Phoenix, the same can be achieved directly with a one-liner: +

+
std::find_if(c.begin(), c.end(), arg1 % 2 == 1)
+
+

+ The expression arg1 % + 2 == 1 automagically creates a functor with the + expected behavior. In FP, this unnamed function is called a lambda function. + Unlike the function pointer version, which is monomorphic (expects and works + only with a fixed type int argument), the Phoenix version is fully polymorphic + and works with any container (of ints, of longs, of bignum, etc.) as long + as its elements can handle the arg1 + % 2 == 1 expression. +

+

+ (See find_if.cpp) +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/lazy_statements.html b/doc/html/phoenix/starter_kit/lazy_statements.html new file mode 100644 index 0000000..4625eee --- /dev/null +++ b/doc/html/phoenix/starter_kit/lazy_statements.html @@ -0,0 +1,74 @@ + + + +Lazy Statements + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Lazy statements? Sure. There are lazy versions of the C++ statements we all + know and love. For example: +

+
if_(arg1 > 5)
+[
+    std::cout << arg1
+]
+
+

+ Say, for example, we wish to print all the elements that are greater than + 5 (separated by a comma) in a vector. Here's how we write it: +

+
std::for_each(v.begin(), v.end(),
+    if_(arg1 > 5)
+    [
+        std::cout << arg1 << ", "
+    ]
+);
+
+

+ (See if.cpp) +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/more.html b/doc/html/phoenix/starter_kit/more.html new file mode 100644 index 0000000..fa2620b --- /dev/null +++ b/doc/html/phoenix/starter_kit/more.html @@ -0,0 +1,59 @@ + + + +More + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+More +

+

+ As mentioned earlier, this chapter is not a thorough discourse of the library. + It is meant only to cover enough ground to get you into high gear as quickly + as possible. Some advanced stuff is not discussed here (e.g. Scopes); + nor are features that provide alternative (short-hand) ways to do the same + things (e.g. Bind vs. Lazy + Functions). +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/references.html b/doc/html/phoenix/starter_kit/references.html new file mode 100644 index 0000000..941d9d3 --- /dev/null +++ b/doc/html/phoenix/starter_kit/references.html @@ -0,0 +1,75 @@ + + + +References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ References are functions. They hold a reference to a value stored somewhere. + For example, given: +

+
int i = 3;
+char const* s = "Hello World";
+
+

+ we create references to + i and s + this way: +

+
ref(i)
+ref(s)
+
+

+ Like val, the expressions + above evaluates to a nullary function; the first one returning an int&, + and the second one returning a char + const*&. +

+

+ (See references.cpp) +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/starter_kit/values.html b/doc/html/phoenix/starter_kit/values.html new file mode 100644 index 0000000..1dde871 --- /dev/null +++ b/doc/html/phoenix/starter_kit/values.html @@ -0,0 +1,118 @@ + + + +Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Values +

+

+ Values are functions! Examples: +

+
val(3)
+val("Hello, World")
+
+

+ The first evaluates to a nullary function (a function taking no arguments) + that returns an int, 3. The second evaluates to a nullary function + that returns a char const(&)[13], "Hello, + World". +

+
+ + Lazy + Evaluation +
+

+ Confused? val is a unary + function and val(3) invokes + it, you say? Yes. However, read carefully: "evaluates to a + nullary function". val(3) + evaluates to (returns) a nullary function. Aha! val(3) + returns a function! So, since val(3) + returns a function, you can invoke it. Example: +

+
std::cout << val(3)() << std::endl;
+
+

+ (See values.cpp) +

+ +

+ The second function call (the one with no arguments) calls the nullary function + which then returns 3. The need + for a second function call is the reason why the function is said to be + Lazily Evaluated. The + first call doesn't do anything. You need a second call to finally evaluate + the thing. The first call lazily evaluates the function; i.e. doesn't do + anything and defers the evaluation for later. +

+
+ + Callbacks +
+

+ It may not be immediately apparent how lazy evaluation can be useful by just + looking at the example above. Putting the first and second function call + in a single line is really not very useful. However, thinking of val(3) as a callback function (and in most cases + they are actually used that way), will make it clear. Example: +

+
template <typename F>
+void print(F f)
+{
+    cout << f() << endl;
+}
+
+int
+main()
+{
+    print(val(3));
+    print(val("Hello World"));
+    return 0;
+}
+
+

+ (See callback.cpp) +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new.html b/doc/html/phoenix/what_s_new.html new file mode 100644 index 0000000..5f4fd36 --- /dev/null +++ b/doc/html/phoenix/what_s_new.html @@ -0,0 +1,55 @@ + + + +What's New + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new/phoenix_3_0.html b/doc/html/phoenix/what_s_new/phoenix_3_0.html new file mode 100644 index 0000000..84d1a58 --- /dev/null +++ b/doc/html/phoenix/what_s_new/phoenix_3_0.html @@ -0,0 +1,68 @@ + + + +Phoenix 3.0 + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This was the first official release of Phoenix as first class Boost citizen. + As a consequence of the review of Phoenix V2 the internals got completely + rewritten. Therefore the internal extension mechanism is different. +

+
    +
  • + composite<...>, as_composite<...> and compose are gone and + have been replaced. For an in depth discussion see the section Inside Phoenix +
  • +
  • + phoenix.modules.function + phoenix::function now supports function objects that implement the Boost.Result + Of protocol. This is a breaking change +
  • +
  • + Boilerplate macros to easily adapt already existing functions and function + objects +
  • +
  • + Bind is not completely compatible + with Boost.Bind. The limitations will be documented as soon as possible. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new/phoenix_3_0_5.html b/doc/html/phoenix/what_s_new/phoenix_3_0_5.html new file mode 100644 index 0000000..14778e8 --- /dev/null +++ b/doc/html/phoenix/what_s_new/phoenix_3_0_5.html @@ -0,0 +1,61 @@ + + + +Phoenix 3.0.5 + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
    +
  • + Introduction of ChangeLog + and release number increments. +
  • +
  • + Added BOOST_PHOENIX_VERSION_NUMBER using boost/predef style. +
  • +
  • + Fixes to bugs #5714 and #5824 are particularly important as they fixed + silent errors in the processing of some compound expressions with commas. +
  • +
  • + This could cause output from some user codes to + change unexpectedly. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new/phoenix_3_0_6__boost_1_57_0_.html b/doc/html/phoenix/what_s_new/phoenix_3_0_6__boost_1_57_0_.html new file mode 100644 index 0000000..f432cd7 --- /dev/null +++ b/doc/html/phoenix/what_s_new/phoenix_3_0_6__boost_1_57_0_.html @@ -0,0 +1,56 @@ + + + +Phoenix 3.0.6 (Boost 1.57.0) + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
    +
  • + Fixed bug in example/container_actor.cpp in end() function. +
  • +
  • + Fixed bug4853 and 5626 - added header <utility> for std::forward. +
  • +
  • + Fixed bug4853 - added header <iostream> for gcc 4.9 test +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new/phoenix_3_1_0.html b/doc/html/phoenix/what_s_new/phoenix_3_1_0.html new file mode 100644 index 0000000..0df2f94 --- /dev/null +++ b/doc/html/phoenix/what_s_new/phoenix_3_1_0.html @@ -0,0 +1,62 @@ + + + +Phoenix 3.1.0 + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This contains a series of updates to Phoenix to fix some bugs and to extend + the examples. Details of the changes will be found in the ChangeLog + and the release number will be increased for each set of changes released. +

+
    +
  • + A start is being made on updating the documentation. +
  • +
  • + A bug has been fixed which was causing a lot of test examples of bind to fail. This was particularly the case with + more recent compilers which are stricter. +
  • +
  • + TODO There is still a lot of work to be done on fixes, documentation + and examples. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new/phoenix_3_1_1.html b/doc/html/phoenix/what_s_new/phoenix_3_1_1.html new file mode 100644 index 0000000..8e543ae --- /dev/null +++ b/doc/html/phoenix/what_s_new/phoenix_3_1_1.html @@ -0,0 +1,61 @@ + + + +Phoenix 3.1.1 + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
    +
  • + This is the start of a series of changes which continue the fixing of + the bugs. +
  • +
  • + There are new examples and tests which show the capability of phoenix. +
  • +
  • + A new example bind_goose shows the compatibility between boost bind and + boost phoenix bind. +
  • +
  • + New tests lazy_argument_tests, lazy_make_pair_tests, lazy_templated_struct_tests + show different possible uses of boost phoenix function objects. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new/phoenix_3_2_0.html b/doc/html/phoenix/what_s_new/phoenix_3_2_0.html new file mode 100644 index 0000000..e085c65 --- /dev/null +++ b/doc/html/phoenix/what_s_new/phoenix_3_2_0.html @@ -0,0 +1,50 @@ + + + +Phoenix 3.2.0 + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
  • + Phoenix now has a lazy list implementation which is very similar but + not identical to the implementation provided by FC++. + Details can be found in Lazy List. + Tests have been added for the new features provided. +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/what_s_new/phoenix___warning_on__lambda_and_let_.html b/doc/html/phoenix/what_s_new/phoenix___warning_on__lambda_and_let_.html new file mode 100644 index 0000000..fc69397 --- /dev/null +++ b/doc/html/phoenix/what_s_new/phoenix___warning_on__lambda_and_let_.html @@ -0,0 +1,72 @@ + + + +Phoenix - warning on lambda and let + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
    +
  • + There are a number of bugs in the implementation of lambda + and let constructs in the current version + of Boost Phoenix (Boost release 1.57.0). +
  • +
  • + These are currently being investigated in the hope of providing a better + version for the next Boost release. +
  • +
  • + The constructs are not completely unusable and many of the tests run. +
  • +
  • + Some usage may work with some compilers but not others. +
  • +
  • + More information will be made available as soon as possible. +
  • +
  • + Workarounds for different compilers are being made available. +
  • +
  • + These are currently on test in develop and are moving to master in version + 3.1.1. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/phoenix/wrap_up.html b/doc/html/phoenix/wrap_up.html new file mode 100644 index 0000000..ec8619e --- /dev/null +++ b/doc/html/phoenix/wrap_up.html @@ -0,0 +1,77 @@ + + + +Wrap Up + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Sooner or later more FP techniques become standard practice as people find + the true value of this programming discipline outside the academe and into + the mainstream. In as much as structured programming of the 70s and object + oriented programming in the 80s and generic programming in the 90s shaped our + thoughts towards a more robust sense of software engineering, FP will certainly + be a paradigm that will catapult us towards more powerful software design and + engineering onward into the new millennium. +

+

+ Let me quote Doug Gregor of Boost.org. About functional style programming libraries: +

+

+ They're gaining acceptance, but are somewhat stunted by the ubiquitousness + of broken compilers. The C++ community is moving deeper into the so-called + "STL- style" programming paradigm, which brings many aspects of + functional programming into the fold. Look at, for instance, the Spirit parser + to see how such function objects can be used to build Yacc-like grammars + with semantic actions that can build abstract syntax trees on the fly. This + type of functional composition is gaining momentum. +

+

+ Indeed. Phoenix is another attempt to introduce more FP techniques into the + mainstream. Not only is it a tool that will make life easier for the programmer. + In its own right, the actual design of the library itself is a model of true + C++ FP in action. The library is designed and structured in a strict but clear + and well mannered FP sense. By all means, use the library as a tool. But for + those who want to learn more about FP in C++, don't stop there, I invite you + to take a closer look at the design of the library itself. +

+

+ So there you have it. Have fun! See you in the FP world. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/lazy_list.qbk b/doc/lazy_list.qbk new file mode 100644 index 0000000..36e718e --- /dev/null +++ b/doc/lazy_list.qbk @@ -0,0 +1,419 @@ +[/============================================================================== + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (C) 2001-2010 Joel de Guzman + Copyright (C) 2001-2005 Dan Marsden + Copyright (C) 2001-2010 Thomas Heller + Copyright (C) 2014-2015 John Fletcher + + 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 Lazy List] + +[h1 Summary] +Phoenix now has a lazy list implementation which is very similar but not identical to the implementation provided by __fcpp__. This provides a set of objects defined by list, for example this which defines an empty list of type int. + + list l0; + +A list can contain zero or more elements of the same type. It can also be declared using a function returning values of the correct type. Such lists are only evaluated on demand. A set of functions are defined which enable many ways of manipulating and using lists. Examples are provided for the features available. + +[/section Introduction] +[h1 Introduction] + +Boost Phoenix provides many features of functional_programming. One of the things which has been missing until now is a lazy list implementation. One is available in the library __fcpp__ which although not part of Boost has many similarities. It has been possible to reimplement the strategy of the __fcpp_list__ using the facilties in Phoenix. This provides something which has up until now not been available anywhere in Phoenix and probably not anywhere else in Boost. This new implementation is very well integrated with other features in Phoenix as it uses the same mechanism. In turn that is well integrated with Boost Function. + +There is a great deal of material in __fcpp__ and it is not proposed to replicate all of it. A great deal has changed since __fcpp__ was written and many things are already available in Phoenix or elsewhere. The emphasis here is to add to Phoenix in a way which will make it easier to implement functional_programming. + +Progress is being made in implementing both the basic list and the functions needed to manipulate lists. + +[/endsect] + +[section Background] + +The original code of __fcpp__ was developed by Brian McNamara and Yannis Smaragdakis between 2000 and 2003. One of the aims of their work was to implement as mich as possible of the Haskell prelude in C++. In the end they achieved a very large part of that and went on to implement other similar things not in the Haskell prelude. This was made up of a large amount of code written very carefully in a consistent style which made it easy to extend it to provide more facilities. + +At the end of that time, two versions of it existed, FC++ 1.5 and __boost_fcpp__ which was proposed for inclusion in Boost and rejected. Both are documented on __fcpp__. + +After 2003 John Fletcher spent a lot of time developing both these versions and adding new features to them. One of the reasons intially was that the existing versions could handle only a small number of function arguments. He was able to inclrease the limit on the number of arguments and use the new version to implement a number of new ideas. No new release has ever been made although a draft release 1.5.2 exists. Much of his activity is documented by __functoids_in_cpp__ where some discussion took place with other people about this work. + +John discussed with Joel de Guzman how to make __fcpp__ compatible with Phoenix. Joel suggested using Phoenix as a basis for a new version of __fcpp__. + +In 2014 John became the maintainer of Phoenix and after spending time getting to know it he has now started to fulfil his idea of a new version of __fcpp__. What is emerging is significantly different from __fcpp__ in the detail of the implementation. In some ways it will be more powerful as it is well integrated with the facilities of Phoenix. In other ways it will lack some features of __fcpp__ as they can now be implemented in other ways. + +[endsect] + +[section What is provided] + +Functions are provided to build and manipulate objects of the list type + + list + +[h2 Namespace and header] + +The functions are in the namespace + + boost::phoenix + +by the header file + + boost/phoenix/function/lazy_prelude.hpp + +which includes all other needed headers. It is not currently included in + + boost/phoenix/function.hpp + +so it must be explicitly included to use these types and functions. + +[h2 Integration with Boost Phoenix] + +The functions are defined by boost::phoenix::function which means that they work with phoenix arguments such as 'arg1'. They have been defined in such a way that when needed they can be passed as arguments to other functions. + +[h1 Lazy List Type] + + list (where T is the element type) + +[h1 Functions] + +The functions are grouped as follows: + +[h2 Arithmetic functions] + + plus + minus + multiplies + divides + modulus + negate + +[h2 Boolean functions] + + equal + not_equal + greater + less + greater_equal + less_equal + +[h2 Logical functions] + + logical_and + logical_or + logical_not + +[h2 Operational functions] + + apply + until + until2 + max + min + inc + dec + make_pair + +[h2 Logical predicates] + + odd + even + +[h2 List Functions] + + cons + cat + take + drop + last + all_but_last + at + length + filter + +[h3 List Generation Functions] + + enum_from + enum_from_to + list_with + +[h2 Futher functions] + +Further functions are in development from the resources available in __fcpp__. + +[endsect] + +[section Tutorial with examples] + +These examples require the following header: + + boost/phoenix/function/lazy_prelude.hpp + +The following statements should be in the execution code: + + using boost::phoenix::arg_names::arg1; + using boost::phoenix::arg_names::arg2; + using namespace boost::phoenix; + + +[section Arithmetic functions] + +Assume the values + + int a = 123; + int b = 256; + +The following are all valid expressions returning a+b + + plus(arg1, arg2)(a, b) + plus(arg1, b)(a) + plus(a, arg2)(a,b) + plus(a, arg1)(b) + plus(a, b)() + +The expressions can be combined like this + + plus(minus(a, b),b)() + plus(minus(arg1, b),b)(a) + plus(minus(arg1, arg2),b)(a,b) + plus(minus(arg1, arg2),arg2)(a,b) + +Other numerical operators can be used like this + + multiplies(arg1,arg2)(3,6) + divides(arg2,arg1)(3,6) + modulus(arg2,arg1)(4,6) + min(arg1,arg2)(4,6) + max(arg1,arg2)(4,6) + inc(arg1)(a) + dec(arg1)(a) + negate(arg1)(a) + +[endsect] + +[section List Generation] + +One of the most interesting capabilities of __fcpp__ is the generation of infinite lazy lists which are evaluated only at need. The most simple example of this is + + enum_from(1) + +which returns the generator for integers 1,2,3,..... infinity. + + take(4,enum_from(1)) + +returns a list of the first 4 of the list. + + at(enum_from(1),3) + +returns the fourth member using zero indexed access. Both of the lists returned are lazy and only evaluated when the list members are accessed. + +[endsect] + +To be developed. + +[endsect] + +[section Implementation Details] + +[h2 Introduction] +The implementation has depended on close study of the existing code of __fcpp__. The __fcpp_list__ is a carefully crafted code which allows for efficient processing of a number of different cases. In particular it makes use of the __fcpp_reusers__ for processing of repetitive evaluations. + +__fcpp__ uses a combination of polymorphic and single type functions which can be passed as arguments to other functions. + +The implementation of list has needed new implementations of the strategy using the facilities of Boost Phoenix and also Boost Function. It turns out that a combination of both can be used to meet the needs of list. + +The fact that the functions are defined by boost::phoenix::function means that they work with phoenix arguments such as 'arg1'. This is the fact which ensures the flexibility needed for the user to build new functions as needed. + +[h2 FC++ legacy] + +The __fcpp_list__ and the __fcpp_reusers__ have been followed very closely in building this code. The version used as the starting point was the __boost_fcpp__ version. + +[h2 Polymorphic Function Types] + +Functions are implemented as a struct within namespace impl. For an example funcion 'x' the type is defined like this: + + typedef boost::phoenix::function X; + X x + +This alternative will work to provide a function 'x' but it is not then possible to pass it as an argument. + + BOOST_PHOENIX_ADAPT_CALLABLE(x, impl::X, 1) + +[h3 Implementation Example] + +This example implements id() which simply returns its argument: + + namespace impl { + + struct Id + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0) const + { + return a0; + } + + }; + + } + + typedef boost::phoenix::function Id; + Id id; + +[h2 Functions with defined return type] + +Sometimes it is necessary to define a function using a templated struct, where the template parameter type defines the return type. + +[h3 Example with one argument] + + namespace impl { + + template + struct what { + + typedef Result result_type; + + Result operator()(Result const & r) const + { + return r; + } + }; + + } + + boost::function1 what_int = impl::what(); + typedef boost::function1 fun1_int_int; + typedef boost::phoenix::function What_arg; + What_arg what_arg(what_int); + +[h3 Example with zero arguments] + + namespace impl { + template + struct what0 { + + typedef Result result_type; + + Result operator()() const + { + return Result(100); + } + + }; + } + + typedef boost::function0 fun0_int; + boost::function0 what0_int = impl::what0(); + typedef boost::phoenix::function What0_arg; + What0_arg what0_arg(what0_int); + +[h2 List Generation Implementation] + +The implementation of the function + + enum_from(1) + +requires a functor which will evaluate the successive numbers on demand. The code from __fcpp__ has been reimplemented using internal functors as follows. + +This code has to carefully manipulate the input type T to construct the result type which is a list. + +The code in EFH is used to build a series of objects which each add one element to the list and return the function which will add the next element. That only gets called when it is needed. + + template + struct EFH + { + typedef typename boost::remove_reference TT; + typedef typename boost::remove_const::type TTT; + mutable T x; + EFH( const T& xx) : x(xx) {} + template struct result; + + template + struct result + { + typedef typename boost::phoenix::UseList::template + List::type LType; + typedef typename boost::phoenix::result_of:: + ListType::delay_result_type type; + }; + typename result::type operator()() const { + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 fun1_R_TTT; + //std::cout << "EFH (" << x << ")" << std::endl; + ++x; + fun1_R_TTT efh_R_TTT = EFH(x); + typedef boost::phoenix::function EFH_R_T; + EFH_R_T efh_R_T(efh_R_TTT); + if (x > MAX_LIST_LENGTH) + throw lazy_exception("Running away in EFH!!"); + return cons( x-1, efh_R_T() ); + } + }; + + struct Enum_from { + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type type; + }; + + template + typename result::type operator() + (const T & x) const + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 fun1_R_TTT; + fun1_R_TTT efh_R_TTT = EFH(x); + typedef boost::phoenix::function EFH_R_T; + EFH_R_T efh_R_T(efh_R_TTT); + //std::cout << "enum_from (" << x << ")" << std::endl; + return efh_R_T(); + } + }; + +Similar code is used in the related functors + + enum_from_to + filter + +[h2 Conclusion] + +These implementation mechanisms have been carried through consistently in the implementation. + +[endsect] + +[section Testing] + +Several tests are currently on develop with the hope of release to master in time for Boost 1.58.0. + +At present all tests pass except for list tests on __msvc__ 8.0 and 9.0 which reject a reference of a reference. Corrections for this have now been sucessfuly made. + +[endsect] + +[section Where Next?] + +Further functions are going to be implemented and more examples provided. + +[endsect] + + +[endsect] + diff --git a/doc/maintenance.qbk b/doc/maintenance.qbk index f76de0f..c51267e 100644 --- a/doc/maintenance.qbk +++ b/doc/maintenance.qbk @@ -8,7 +8,6 @@ [/ January 2015] [/ February 2015] - [section Maintenance] The experience of the maintenance of Boost Phoenix during 2014 and 2015. @@ -43,7 +42,6 @@ At the end of 2014 I came back to the task anew. In the meantime I have learned I have still not solved all the problems in Boost Phoenix. I think I am closing in on some of the remaining ones. I now know that some of the problems in Phoenix V3 were also present in Phoenix V2. This has changed the approach to how to solve them as I know that the problems cannot be in the use of Boost Proto as it was not used in V2. - I have made further progress during 2015 on understanding what the problems are and how to avoid them or work around them. That has given me the confidence to explore further applications of the code, which I expect will develop a lot in the next few months. I want in this document to share some of what I have been doing and how I have solved some of the problems. One reason for doing this is that there may be other people who are considering taking on library maintenance of a library they did not themselves write. I hope I can make that easier for people to do. @@ -118,7 +116,6 @@ I have been attempting to understand the differences between compilers and envir [endsect] - [endsect] [endsect] diff --git a/doc/phoenix3.qbk b/doc/phoenix3.qbk index 8051a48..1dc05be 100644 --- a/doc/phoenix3.qbk +++ b/doc/phoenix3.qbk @@ -1,7 +1,11 @@ [library Phoenix [quickbook 1.6] [compatibility-mode 1.3] +<<<<<<< HEAD [version 3.1.1] +======= + [version 3.2.0] +>>>>>>> release-3.2.0 [authors [de Guzman, Joel], [Marsden, Dan], [Heller, Thomas], [Fletcher, John] ] [copyright 2002 2003 2004 2005 2010 2014 2015 Joel de Guzman, Dan Marsden, Thomas Heller, John Fletcher] [category string-text] @@ -44,6 +48,13 @@ [def __mpl__ [@http://www.boost.org/libs/mpl/index.html MPL]] [def __bll__ [@http://www.boost.org/libs/lambda/doc/index.html BLL]] [def __fcpp__ [@http://cgi.di.uoa.gr/~smaragd/fc++/ FC++]] +<<<<<<< HEAD +======= +[def __fcpp_list__ [@http://people.cs.umass.edu/~yannis/fc++/New/new_list_implementation.html FC++ List Implementation]] +[def __fcpp_reusers__ [@http://people.cs.umass.edu/~yannis/fc++/New/reusers.html FC++ Reuser Implementation]] +[def __functoids_in_cpp__ [@http://c2.com/cgi/wiki?FunctoidsInCpp FunctoidsInCpp]] +[def __boost_fcpp__ [@http://cgi.di.uoa.gr/~smaragd/fc++/boostpaper/ Boost FC++]] +>>>>>>> release-3.2.0 [def __spirit_repo__ [@http://spirit.sourceforge.net/repository/applications/show_contents.php Spirit Repository]] [def __spirit_list__ [@https://lists.sourceforge.net/lists/listinfo/spirit-general Spirit Mailing List]] [def __spirit_general__ [@news://news.gmane.org/gmane.comp.spirit.general Spirit General NNTP news portal]] @@ -60,6 +71,7 @@ [def __phoenix_actions__ [link phoenix.inside.actions Actions]] [def __phoenix_custom_terminals__ [link phoenix.inside.custom_terminals Custom Terminals]] [def __phoenix_placeholder_unification__ [link phoenix.inside.placeholder_unification Placeholder Unification]] +[def __phoenix_lazy_list__ [link phoenix.lazy_list Lazy List]] [def __unspecified__ /unspecified/] [/ Defines for maintenance tools ] @@ -72,6 +84,10 @@ [/ Defines for compilers.] [def __clang__ [@http://clang.llvm.org Clang ]] [def __gcc__ [@https://gcc.gnu.org gcc ]] +<<<<<<< HEAD +======= +[def __msvc__ [@https://msdn.microsoft.com/en-us/vstudio/hh386302.aspx MSVC]] +>>>>>>> release-3.2.0 [include preface.qbk] [include what_s_new.qbk] @@ -83,6 +99,7 @@ [include modules.qbk] [include inside.qbk] [include examples.qbk] +[include lazy_list.qbk] [include maintenance.qbk] [include wrap_up.qbk] @@ -90,4 +107,7 @@ [include references.qbk] [/endsect] [/added because it was complaining!] +<<<<<<< HEAD +======= +>>>>>>> release-3.2.0 diff --git a/doc/what_s_new.qbk b/doc/what_s_new.qbk index 855f87e..463a579 100644 --- a/doc/what_s_new.qbk +++ b/doc/what_s_new.qbk @@ -9,7 +9,6 @@ [section What's New] - [section Phoenix - warning on *lambda and let*] * There are a number of bugs in the implementation of *lambda* and *let* constructs in the current version of Boost Phoenix (Boost release 1.57.0). @@ -22,6 +21,12 @@ [endsect] +[section Phoenix 3.2.0] + +* Phoenix now has a lazy list implementation which is very similar but not identical to the implementation provided by __fcpp__. Details can be found in __phoenix_lazy_list__. Tests have been added for the new features provided. + +[endsect] + [section Phoenix 3.1.1] * This is the start of a series of changes which continue the fixing of the bugs. diff --git a/include/boost/phoenix/function/lazy_list.hpp b/include/boost/phoenix/function/lazy_list.hpp new file mode 100644 index 0000000..08f53fe --- /dev/null +++ b/include/boost/phoenix/function/lazy_list.hpp @@ -0,0 +1,1514 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy_list.hpp +// +// Build lazy operations for Phoenix equivalents for FC++ +// +// These are equivalents of the Boost FC++ functoids in list.hpp +// +// Implemented so far: +// +// head tail null +// +// strict_list and associated iterator. +// +// list and odd_list +// +// cons cat +// +// Comparisons between list and odd_list types and separately for strict_list. +// +// NOTES: There is a fix at the moment as I have not yet sorted out +// how to get back the return type of a functor returning a list type. +// For the moment I have fixed this as odd_list at two locations, +// one in list and one in Cons. I am going to leave it like this +// for now as reading the code, odd_list seems to be correct. +// +// I am also not happy at the details needed to detect types in Cons. +// +// I think the structure of this file is now complete. +// John Fletcher February 2015. +// +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + +/////////////////////////////////////////////////////////////////////// +// This is from Boost FC++ list.hpp reimplemented without Fun0 or Full0 +/////////////////////////////////////////////////////////////////////// + +/* +concept ListLike: Given a list representation type L + +L inherits ListLike and has + // typedefs just show typical values + typedef T value_type + typedef L force_result_type + typedef L delay_result_type + typedef L tail_result_type + template struct cons_rebind { + typedef L type; // force type + typedef L delay_type; // delay type + }; + + L() + L( a_unique_type_for_nil ) + template L(F) // F :: ()->L + + constructor: force_result_type( T, L ) + template + constructor: force_result_type( T, F ) // F :: ()->L + + template + L( It, It ) + + // FIX THIS instead of operator bool(), does Boost have something better? + operator bool() const + force_result_type force() const + delay_result_type delay() const + T head() const + tail_result_type tail() const + + static const bool is_lazy; // true if can represent infinite lists + + typedef const_iterator; + typedef const_iterator iterator; // ListLikes are immutable + iterator begin() const + iterator end() const +*/ + +////////////////////////////////////////////////////////////////////// +// End of section from Boost FC++ list.hpp +////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_PHOENIX_FUNCTION_LAZY_LIST +#define BOOST_PHOENIX_FUNCTION_LAZY_LIST + +#include +#include +#include +#include +#include +//#include "lazy_reuse.hpp" + +namespace boost { + + namespace phoenix { + +////////////////////////////////////////////////////////////////////// +// These are the list types being declared. +////////////////////////////////////////////////////////////////////// + + template class strict_list; + namespace impl { + template class list; + template class odd_list; + } + // in ref_count.hpp in BoostFC++ now in lazy_operator.hpp + //typedef unsigned int RefCountType; + +////////////////////////////////////////////////////////////////////// +// a_unique_type_for_nil moved to lazy_operator.hpp. +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////// +// Distinguish lazy lists (list and odd_list) from strict_list. +////////////////////////////////////////////////////////////////////// + + namespace lazy { + // Copied from Boost FC++ list.hpp + template struct ensure_lazy_helper {}; + template struct ensure_lazy_helper { + static void requires_lazy_list_to_prevent_infinite_recursion() {} + }; + template + void ensure_lazy() { + ensure_lazy_helper:: + requires_lazy_list_to_prevent_infinite_recursion(); + } + + } + +////////////////////////////////////////////////////////////////////// +// Provide remove reference for types defined for list types. +////////////////////////////////////////////////////////////////////// + + namespace result_of { + + template < typename L > + class ListType + { + public: + typedef typename boost::remove_reference::type LType; + typedef typename LType::value_type value_type; + typedef typename LType::tail_result_type tail_result_type; + typedef typename LType::force_result_type force_result_type; + typedef typename LType::delay_result_type delay_result_type; + }; + + template <> + class ListType + { + public: + typedef a_unique_type_for_nil LType; + //typedef a_unique_type_for_nil value_type; + }; + + template + struct ResultType { + typedef typename impl::odd_list type; + }; + + } + +////////////////////////////////////////////////////////////////////// +// ListLike is a property inherited by any list type to enable it to +// work with the functions being implemented in this file. +// It provides the check for the structure described above. +////////////////////////////////////////////////////////////////////// + + namespace listlike { + + struct ListLike {}; // This lets us use is_base_and_derived() to see + // (at compile-time) what classes are user-defined lists. + + + template struct ensure_lazy_helper {}; + template struct ensure_lazy_helper { + static void requires_lazy_list_to_prevent_infinite_recursion() {} + }; + template + void ensure_lazy() { + ensure_lazy_helper:: + requires_lazy_list_to_prevent_infinite_recursion(); + } + + template + struct EnsureListLikeHelp { + static void trying_to_call_a_list_function_on_a_non_list() {} + }; + template struct EnsureListLikeHelp { }; + template + void EnsureListLike() { + typedef typename result_of::ListType::LType LType; + EnsureListLikeHelp::value>:: + trying_to_call_a_list_function_on_a_non_list(); + } + + template + bool is_a_unique_type_for_nil(const L& l) { + return false; + } + + template <> + bool is_a_unique_type_for_nil + (const a_unique_type_for_nil& n) { + return true; + } + + template + struct detect_nil { + static const bool is_nil = false; + }; + + template <> + struct detect_nil { + static const bool is_nil = true; + }; + + template <> + struct detect_nil { + static const bool is_nil = true; + }; + + template <> + struct detect_nil { + static const bool is_nil = true; + }; + + } + +////////////////////////////////////////////////////////////////////// +// Implement lazy functions for list types. cat and cons come later. +////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH +#define BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH 1000 +#endif + + namespace impl { + + struct Head + { + template + struct result; + + template + struct result + { + typedef typename result_of::ListType::value_type type; + }; + + template + typename result::type + operator()(const L & l) const + { + listlike::EnsureListLike(); + return l.head(); + } + + }; + + struct Tail + { + template + struct result; + + template + struct result + { + typedef typename result_of::ListType::tail_result_type type; + }; + + template + typename result::type + operator()(const L & l) const + { + listlike::EnsureListLike(); + return l.tail(); + } + + }; + + struct Null + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + typename result::type + //bool + operator()(const L& l) const + { + listlike::EnsureListLike(); + return !l; + } + + }; + + struct Delay { + template + struct result; + + template + struct result + { + typedef typename result_of::ListType::delay_result_type type; + }; + + template + typename result::type + operator()(const L & l) const + { + listlike::EnsureListLike(); + return l.delay(); + } + + }; + + struct Force { + template + struct result; + + template + struct result + { + typedef typename result_of::ListType::force_result_type type; + }; + + template + typename result::type + operator()(const L & l) const + { + listlike::EnsureListLike(); + return l.force(); + } + + }; + + } + //BOOST_PHOENIX_ADAPT_CALLABLE(head, impl::head, 1) + //BOOST_PHOENIX_ADAPT_CALLABLE(tail, impl::tail, 1) + //BOOST_PHOENIX_ADAPT_CALLABLE(null, impl::null, 1) + typedef boost::phoenix::function Head; + typedef boost::phoenix::function Tail; + typedef boost::phoenix::function Null; + typedef boost::phoenix::function Delay; + typedef boost::phoenix::function Force; + Head head; + Tail tail; + Null null; + Delay delay; + Force force; + +////////////////////////////////////////////////////////////////////// +// These definitions used for strict_list are imported from BoostFC++ +// unchanged. +////////////////////////////////////////////////////////////////////// + +namespace impl { +template +struct strict_cons : public boost::noncopyable { + mutable RefCountType refC; + T head; + typedef boost::intrusive_ptr tail_type; + tail_type tail; + strict_cons( const T& h, const tail_type& t ) : refC(0), head(h), tail(t) {} + +}; +template +void intrusive_ptr_add_ref( const strict_cons* p ) { + ++ (p->refC); +} +template +void intrusive_ptr_release( const strict_cons* p ) { + if( !--(p->refC) ) delete p; +} + +template +class strict_list_iterator +: public std::iterator { + typedef boost::intrusive_ptr > rep_type; + rep_type l; + bool is_nil; + void advance() { + l = l->tail; + if( !l ) + is_nil = true; + } + class Proxy { // needed for operator-> + const T x; + friend class strict_list_iterator; + Proxy( const T& xx ) : x(xx) {} + public: + const T* operator->() const { return &x; } + }; +public: + strict_list_iterator() : l(), is_nil(true) {} + explicit strict_list_iterator( const rep_type& ll ) : l(ll), is_nil(!ll) {} + + const T operator*() const { return l->head; } + const Proxy operator->() const { return Proxy(l->head); } + strict_list_iterator& operator++() { + advance(); + return *this; + } + const strict_list_iterator operator++(int) { + strict_list_iterator i( *this ); + advance(); + return i; + } + bool operator==( const strict_list_iterator& i ) const { + return is_nil && i.is_nil; + } + bool operator!=( const strict_list_iterator& i ) const { + return ! this->operator==(i); + } +}; +} + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + + template + class strict_list : public listlike::ListLike + { + typedef boost::intrusive_ptr > rep_type; + rep_type rep; + struct Make {}; + + template + static rep_type help( Iter a, const Iter& b ) { + rep_type r; + while( a != b ) { + T x( *a ); + r = rep_type( new impl::strict_cons( x, r ) ); + ++a; + } + return r; + } + + public: + static const bool is_lazy = false; + + typedef T value_type; + typedef strict_list force_result_type; + typedef strict_list delay_result_type; + typedef strict_list tail_result_type; + template struct cons_rebind { + typedef strict_list type; + typedef strict_list delay_type; + }; + + + strict_list( Make, const rep_type& r ) : rep(r) {} + + strict_list() : rep() {} + + strict_list( a_unique_type_for_nil ) : rep() {} + + template + strict_list( const F& f ) : rep( f().rep ) { + // I cannot do this yet. + //functoid_traits::template ensure_accepts<0>::args(); + } + + strict_list( const T& x, const strict_list& y ) + : rep( new impl::strict_cons(x,y.rep) ) {} + + template + strict_list( const T& x, const F& f ) + : rep( new impl::strict_cons(x,f().rep) ) {} + + operator bool() const { return (bool)rep; } + force_result_type force() const { return *this; } + delay_result_type delay() const { return *this; } + T head() const { +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if( !*this ) + throw lazy_exception("Tried to take head() of empty strict_list"); +#endif + return rep->head; + } + tail_result_type tail() const { +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if( !*this ) + throw lazy_exception("Tried to take tail() of empty strict_list"); +#endif + return strict_list(Make(),rep->tail); + } + + template + strict_list( const Iter& a, const Iter& b ) : rep( rep_type() ) { + // How ironic. We need to reverse the iterator range in order to + // non-recursively build this! + std::vector tmp(a,b); + rep = help( tmp.rbegin(), tmp.rend() ); + } + + // Since the strict_cons destructor can't call the strict_list + // destructor, the "simple" iterative destructor is correct and + // efficient. Hurray. + ~strict_list() { while(rep && (rep->refC == 1)) rep = rep->tail; } + + // The following helps makes strict_list almost an STL "container" + typedef impl::strict_list_iterator const_iterator; + typedef const_iterator iterator; // strict_list is immutable + iterator begin() const { return impl::strict_list_iterator( rep ); } + iterator end() const { return impl::strict_list_iterator(); } + + }; + + // All of these null head and tail are now non lazy using e.g. null(a)(). + // They need an extra () e.g. null(a)(). + template + bool operator==( const strict_list& a, a_unique_type_for_nil ) { + return null(a)(); + } + template + bool operator==( a_unique_type_for_nil, const strict_list& a ) { + return null(a)(); + } + template + bool operator==( const strict_list& a, const strict_list& b ) { + if( null(a)() && null(b)() ) + return true; + if( null(a)() || null(b)() ) + return false; + return (head(a)()==head(b)()) && + (tail(a)()==tail(b)()); + } + + template + bool operator<( const strict_list& a, const strict_list& b ) { + if( null(a)() && !null(b)() ) return true; + if( null(b)() ) return false; + if( head(b)() < head(a)() ) return false; + if( head(a)() < head(b)() ) return true; + return (tail(a)() < tail(b)()); + } + template + bool operator<( const strict_list&, a_unique_type_for_nil ) { + return false; + } + template + bool operator<( a_unique_type_for_nil, const strict_list& b ) { + return !(null(b)()); + } + +////////////////////////////////////////////////////////////////////// +// Class list is the primary interface to the user for lazy lists. +//////////////////////////////////////////////////////////////////////{ + namespace impl { + using fcpp::INV; + using fcpp::VAR; + using fcpp::reuser2; + + struct CacheEmpty {}; + + template class Cache; + template class odd_list; + template class list_iterator; + template + struct ListItHelp2 /*: public c_fun_type >*/ { + // This will need a return type. + typedef odd_list return_type; + odd_list operator()( It begin, const It& end, + reuser2,It,It> r = NIL ) const; + }; + template struct cvt; + template struct ListHelp; + template Cache* xempty_helper(); + template struct ConsHelp2; + + struct ListRaw {}; + + template + class list : public listlike::ListLike + { + // never NIL, unless an empty odd_list + boost::intrusive_ptr > rep; + + template friend class Cache; + template friend class odd_list; + template friend struct ConsHelp2; + template friend struct cvt; + + list( const boost::intrusive_ptr >& p ) : rep(p) { } + list( ListRaw, Cache* p ) : rep(p) { } + + bool priv_isEmpty() const { + return rep->cache().second.rep == Cache::XNIL(); + } + T priv_head() const { +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if( priv_isEmpty() ) + throw lazy_exception("Tried to take head() of empty list"); +#endif + return rep->cache().first(); + } + list priv_tail() const { +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if( priv_isEmpty() ) + throw lazy_exception("Tried to take tail() of empty list"); +#endif + return rep->cache().second; + } + + + public: + static const bool is_lazy = true; + + typedef T value_type; + typedef list tail_result_type; + typedef odd_list force_result_type; + typedef list delay_result_type; + template struct cons_rebind { + typedef odd_list type; + typedef list delay_type; + }; + + list( a_unique_type_for_nil ) : rep( Cache::XEMPTY() ) { } + list() : rep( Cache::XEMPTY() ) { } + + template // works on both ()->odd_list and ()->list + // At the moment this is fixed for odd_list. + // I need to do more work to get the general result. + list( const F& f ) + : rep( ListHelp >()(f) ) { } + //: rep( ListHelp()(f) ) { } + + operator bool() const { return !priv_isEmpty(); } + const force_result_type& force() const { return rep->cache(); } + const delay_result_type& delay() const { return *this; } + // Note: force returns a reference; + // implicit conversion now returns a copy. + operator odd_list() const { return force(); } + + T head() const { return priv_head(); } + tail_result_type tail() const { return priv_tail(); } + + // The following helps makes list almost an STL "container" + typedef list_iterator const_iterator; + typedef const_iterator iterator; // list is immutable + iterator begin() const { return list_iterator( *this ); } + iterator end() const { return list_iterator(); } + + // end of list + }; + +////////////////////////////////////////////////////////////////////// +// Class odd_list is not normally accessed by the user. +////////////////////////////////////////////////////////////////////// + + struct OddListDummyY {}; + + template + class odd_list : public listlike::ListLike + { + public: + typedef + typename boost::type_with_alignment::value>::type + xfst_type; + private: + union { xfst_type fst; unsigned char dummy[sizeof(T)]; }; + + const T& first() const { + return *static_cast(static_cast(&fst)); + } + T& first() { + return *static_cast(static_cast(&fst)); + } + list second; // If XNIL, then this odd_list is NIL + + template friend class list; + template friend class Cache; + + odd_list( OddListDummyY ) + : second( Cache::XBAD() ) { } + + void init( const T& x ) { + new (static_cast(&fst)) T(x); + } + + bool fst_is_valid() const { + if( second.rep != Cache::XNIL() ) + if( second.rep != Cache::XBAD() ) + return true; + return false; + } + + bool priv_isEmpty() const { return second.rep == Cache::XNIL(); } + T priv_head() const { +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if( priv_isEmpty() ) + throw lazy_exception("Tried to take head() of empty odd_list"); +#endif + return first(); + } + + list priv_tail() const { +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if( priv_isEmpty() ) + throw lazy_exception("Tried to take tail() of empty odd_list"); +#endif + return second; + } + + public: + static const bool is_lazy = true; + + typedef T value_type; + typedef list tail_result_type; + typedef odd_list force_result_type; + typedef list delay_result_type; + template struct cons_rebind { + typedef odd_list type; + typedef list delay_type; + }; + + odd_list() : second( Cache::XNIL() ) { } + odd_list( a_unique_type_for_nil ) : second( Cache::XNIL() ) { } + odd_list( const T& x, const list& y ) : second(y) { init(x); } + odd_list( const T& x, a_unique_type_for_nil ) : second(NIL) { init(x); } + + odd_list( const odd_list& x ) : second(x.second) { + if( fst_is_valid() ) { + init( x.first() ); + } + } + + template + odd_list( It begin, const It& end ) + : second( begin==end ? Cache::XNIL() : + ( init(*begin++), list( begin, end ) ) ) {} + + odd_list& operator=( const odd_list& x ) { + if( this == &x ) return *this; + if( fst_is_valid() ) { + if( x.fst_is_valid() ) + first() = x.first(); + else + first().~T(); + } + else { + if( x.fst_is_valid() ) + init( x.first() ); + } + second = x.second; + return *this; + } + + ~odd_list() { + if( fst_is_valid() ) { + first().~T(); + } + } + + operator bool() const { return !priv_isEmpty(); } + const force_result_type& force() const { return *this; } + delay_result_type delay() const { return list(*this); } + + T head() const { return priv_head(); } + tail_result_type tail() const { return priv_tail(); } + + // The following helps makes odd_list almost an STL "container" + typedef list_iterator const_iterator; + typedef const_iterator iterator; // odd_list is immutable + iterator begin() const { return list_iterator( this->delay() ); } + iterator end() const { return list_iterator(); } + + // end of odd_list + }; + +////////////////////////////////////////////////////////////////////// +// struct cvt +////////////////////////////////////////////////////////////////////// + + // This converts ()->list to ()->odd_list. + // In other words, here is the 'extra work' done when using the + // unoptimized interface. + template + struct cvt /*: public c_fun_type >*/ { + typedef odd_list return_type; + F f; + cvt( const F& ff ) : f(ff) {} + odd_list operator()() const { + list l = f(); + return l.force(); + } + }; + + +////////////////////////////////////////////////////////////////////// +// Cache and associated functions. +////////////////////////////////////////////////////////////////////// + +// I malloc a RefCountType to hold the refCount and init it to 1 to ensure the +// refCount will never get to 0, so the destructor-of-global-object +// order at the end of the program is a non-issue. In other words, the +// memory allocated here is only reclaimed by the operating system. + template + Cache* xnil_helper() { + void *p = std::malloc( sizeof(RefCountType) ); + *((RefCountType*)p) = 1; + return static_cast*>( p ); + } + + template + Cache* xnil_helper_nil() { + Cache* p = xnil_helper(); + return p; + } + + template + Cache* xnil_helper_bad() { + Cache* p = xnil_helper(); + return p; + } + + template + Cache* xempty_helper() { + Cache* p = new Cache( CacheEmpty() ); + return p; + } + + // This makes a boost phoenix function type with return type + // odd_list + template + struct fun0_type_helper{ + typedef boost::function0 > fun_type; + typedef boost::phoenix::function phx_type; + }; + + + template + struct make_fun0_odd_list { + + typedef typename fun0_type_helper::fun_type fun_type; + typedef typename fun0_type_helper::phx_type phx_type; + typedef phx_type result_type; + + template + result_type operator()(const F& f) const + { + fun_type ff(f); + phx_type g(ff); + return g; + } + + // Overload for the case where it is a boost phoenix function already. + template + typename boost::phoenix::function operator() + (const boost::phoenix::function& f) const + { + return f; + } + + }; + + template + class Cache : boost::noncopyable { + mutable RefCountType refC; + // This is the boost::function type + typedef typename fun0_type_helper::fun_type fun_odd_list_T; + // This is the boost::phoenix::function type; + typedef typename fun0_type_helper::phx_type fun0_odd_list_T; + mutable fun0_odd_list_T fxn; + mutable odd_list val; + // val.second.rep can be XBAD, XNIL, or a valid ptr + // - XBAD: val is invalid (fxn is valid) + // - XNIL: this is the empty list + // - anything else: val.first() is head, val.second is tail() + + // This functoid should never be called; it represents a + // self-referent Cache, which should be impossible under the current + // implementation. Nonetheless, we need a 'dummy' function object to + // represent invalid 'fxn's (val.second.rep!=XBAD), and this + // implementation seems to be among the most reasonable. + struct blackhole_helper /*: c_fun_type< odd_list >*/ { + typedef odd_list return_type; + odd_list operator()() const { +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + throw lazy_exception("You have entered a black hole."); +#else + return odd_list(); +#endif + } + }; + + // Don't get rid of these XFOO() functions; they impose no overhead, + // and provide a useful place to add debugging code for tracking down + // before-main()-order-of-initialization problems. + static const boost::intrusive_ptr >& XEMPTY() { + static boost::intrusive_ptr > xempty( xempty_helper() ); + return xempty; + } + static const boost::intrusive_ptr >& XNIL() { + // this list is nil + static boost::intrusive_ptr > xnil( xnil_helper_nil() ); + return xnil; + } + + static const boost::intrusive_ptr >& XBAD() { + // the pair is invalid; use fxn + static boost::intrusive_ptr > xbad( xnil_helper_bad() ); + return xbad; + } + + static fun0_odd_list_T /* >*/ the_blackhole; + static fun0_odd_list_T& blackhole() { + static fun0_odd_list_T the_blackhole; + //( make_fun0_odd_list()( blackhole_helper() ) ); + return the_blackhole; + } + + odd_list& cache() const { + if( val.second.rep == XBAD() ) { + val = fxn()(); + fxn = blackhole(); + } + return val; + } + + template friend class list; + template friend class odd_list; + template friend struct ConsHelp2; + template friend struct cvt; + template friend struct ListHelp; + template friend Cache* xempty_helper(); + + Cache( CacheEmpty ) : refC(0), fxn(blackhole()), val() {} + Cache( const odd_list& x ) : refC(0), fxn(blackhole()), val(x) {} + Cache( const T& x, const list& l ) : refC(0),fxn(blackhole()),val(x,l) + {} + + Cache( const fun0_odd_list_T& f ) + : refC(0), fxn(f), val( OddListDummyY() ) {} + + // f must be a boost phoenix function object? + template + Cache( const F& f ) // ()->odd_list + : refC(0), fxn(make_fun0_odd_list()(f)), val( OddListDummyY() ) {} + + // This is for ()->list to ()->odd_list + struct CvtFxn {}; + template + Cache( CvtFxn, const F& f ) // ()->list + : refC(0), fxn(make_fun0_odd_list()(cvt(f))), val( OddListDummyY() ) {} + + template + friend void intrusive_ptr_add_ref( const Cache* p ); + template + friend void intrusive_ptr_release( const Cache* p ); + }; + + template + void intrusive_ptr_add_ref( const Cache* p ) { + ++ (p->refC); + } + template + void intrusive_ptr_release( const Cache* p ) { + if( !--(p->refC) ) delete p; + } + +////////////////////////////////////////////////////////////////////// +// Rest of list's stuff +////////////////////////////////////////////////////////////////////// + +template struct ListHelp > { + boost::intrusive_ptr > operator()( const F& f ) const { + return boost::intrusive_ptr > + (new Cache(typename Cache::CvtFxn(),f)); + } +}; +template struct ListHelp > { + boost::intrusive_ptr > operator()( const F& f ) const { + return boost::intrusive_ptr >(new Cache(f)); + } +}; + +template +class list_iterator +: public std::iterator { + list l; + bool is_nil; + void advance() { + l = l.tail(); + if( !l ) + is_nil = true; + } + class Proxy { // needed for operator-> + const T x; + friend class list_iterator; + Proxy( const T& xx ) : x(xx) {} + public: + const T* operator->() const { return &x; } + }; +public: + list_iterator() : l(), is_nil(true) {} + explicit list_iterator( const list& ll ) : l(ll), is_nil(!ll) {} + + const T operator*() const { return l.head(); } + const Proxy operator->() const { return Proxy(l.head()); } + list_iterator& operator++() { + advance(); + return *this; + } + const list_iterator operator++(int) { + list_iterator i( *this ); + advance(); + return i; + } + bool operator==( const list_iterator& i ) const { + return is_nil && i.is_nil; + } + bool operator!=( const list_iterator& i ) const { + return ! this->operator==(i); + } +}; + + + } // namespace impl + + using impl::list; + using impl::odd_list; + using impl::list_iterator; + +////////////////////////////////////////////////////////////////////// +// op== and op<, overloaded for all combos of list, odd_list, and NIL +////////////////////////////////////////////////////////////////////// +// All of these null head and tail are now non lazy using e.g. null(a)(). +// They need an extra () e.g. null(a)(). + +// FIX THIS comparison operators can be implemented simpler with enable_if +template +bool operator==( const odd_list& a, a_unique_type_for_nil ) { + return null(a)(); +} +template +bool operator==( const list& a, a_unique_type_for_nil ) { + return null(a)(); +} +template +bool operator==( a_unique_type_for_nil, const odd_list& a ) { + return null(a)(); +} +template +bool operator==( a_unique_type_for_nil, const list& a ) { + return null(a)(); +} +template +bool operator==( const list& a, const list& b ) { + if( null(a)() && null(b)() ) + return true; + if( null(a)() || null(b)() ) + return false; + return (head(a)()==head(b)()) && (tail(a)()==tail(b)()); +} +template +bool operator==( const odd_list& a, const odd_list& b ) { + if( null(a)() && null(b)() ) + return true; + if( null(a)() || null(b)() ) + return false; + return (head(a)()==head(b)()) && (tail(a)()==tail(b)()); +} +template +bool operator==( const list& a, const odd_list& b ) { + if( null(a)() && null(b)() ) + return true; + if( null(a)() || null(b)() ) + return false; + return (head(a)()==head(b)()) && (tail(a)()==tail(b)()); +} +template +bool operator==( const odd_list& a, const list& b ) { + if( null(a)() && null(b)() ) + return true; + if( null(a)() || null(b)() ) + return false; + return (head(a)()==head(b)()) && (tail(a)()==tail(b)()); +} + +template +bool operator<( const list& a, const list& b ) { + if( null(a)() && !null(b)() ) return true; + if( null(b)() ) return false; + if( head(b)() < head(a)() ) return false; + if( head(a)() < head(b)() ) return true; + return (tail(a)() < tail(b)()); +} +template +bool operator<( const odd_list& a, const list& b ) { + if( null(a)() && !null(b)() ) return true; + if( null(b)() ) return false; + if( head(b)() < head(a)() ) return false; + if( head(a)() < head(b)() ) return true; + return (tail(a)() < tail(b)()); +} +template +bool operator<( const list& a, const odd_list& b ) { + if( null(a) && !null(b) ) return true; + if( null(b) ) return false; + if( head(b) < head(a) ) return false; + if( head(a) < head(b) ) return true; + return (tail(a) < tail(b)); +} +template +bool operator<( const odd_list& a, const odd_list& b ) { + if( null(a)() && !null(b)() ) return true; + if( null(b)() ) return false; + if( head(b)() < head(a)() ) return false; + if( head(a)() < head(b)() ) return true; + return (tail(a)() < tail(b)()); +} +template +bool operator<( const odd_list&, a_unique_type_for_nil ) { + return false; +} +template +bool operator<( const list&, a_unique_type_for_nil ) { + return false; +} +template +bool operator<( a_unique_type_for_nil, const odd_list& b ) { + return !null(b)(); +} +template +bool operator<( a_unique_type_for_nil, const list& b ) { + return !null(b)(); +} + +////////////////////////////////////////////////////////////////////// +// Implement cat and cons after the list types are defined. +////////////////////////////////////////////////////////////////////// + namespace impl { + using listlike::ListLike; + + template + struct ConsHelp2 + { + typedef typename boost::remove_reference::type TT; + typedef typename L::force_result_type type; + static type go( const TT& x, const F& f ) { + return type( x, f ); + } + }; + template + struct ConsHelp2,true> + { + typedef typename boost::remove_reference::type TT; + typedef list L; + typedef typename L::force_result_type type; + static type go( const TT& x, const F& f ) { + return odd_list(x, list( + boost::intrusive_ptr >(new Cache( + typename Cache::CvtFxn(),f)))); + } + }; + template + struct ConsHelp2,true> + { + typedef typename boost::remove_reference::type TT; + typedef odd_list L; + typedef typename L::force_result_type type; + static type go( const TT& x, const F& f ) { + return odd_list(x, list( ListRaw(), new Cache(f) )); + } + }; + template + struct ConsHelp2 + { + typedef typename boost::remove_reference::type TT; + typedef odd_list type; + static type go( const TT& x, const F& f ) { + return odd_list(x, list( ListRaw(), new Cache(f) )); + } + }; + + template struct ConsHelp1 { + typedef typename boost::remove_reference::type TT; + typedef typename L::force_result_type type; + static type go( const TT& x, const L& l ) { + return type(x,l); + } + }; + template struct ConsHelp1 { + typedef typename boost::remove_reference::type TT; + typedef odd_list type; + static type go( const TT& x, const a_unique_type_for_nil& n ) { + return type(x,n); + } + }; + template struct ConsHelp1 { + // It's a function returning a list + // This is the one I have not fixed yet.... + // typedef typename F::result_type L; + // typedef typename result_of::template ListType::result_type L; + typedef odd_list L; + typedef ConsHelp2::value> help; + typedef typename help::type type; + static type go( const T& x, const F& f ) { + return help::go(x,f); + } + }; + + template + struct ConsHelp0; + + template + struct ConsHelp0 { + typedef typename boost::remove_reference::type TT; + typedef odd_list type; + }; + + template + struct ConsHelp0 { + typedef typename boost::remove_reference::type TT; + typedef odd_list type; + }; + + template + struct ConsHelp0 { + typedef typename boost::remove_reference::type TT; + typedef odd_list type; + }; + + template + struct ConsHelp0 { + // This removes any references from L for correct return type + // identification. + typedef typename boost::remove_reference::type LType; + typedef typename ConsHelp1::value>::type type; + }; + + ///////////////////////////////////////////////////////////////////// + // cons (t,l) - cons a value to the front of a list. + // Note: The first arg, t, must be a value. + // The second arg, l, can be a list or NIL + // or a function that returns a list. + ///////////////////////////////////////////////////////////////////// + struct Cons + { + /* template struct sig : public fun_type< + typename ConsHelp1::value>::type> {}; + */ + template struct result; + + template + struct result + { + typedef typename ConsHelp0::is_nil>::type type; + }; + + template + struct result + { + typedef typename boost::remove_reference::type TT; + typedef odd_list type; + }; + + template + typename result::type + operator()( const T& x, const L& l ) const { + typedef typename result::type LL; + typedef typename result_of::ListType::LType LType; + typedef ConsHelp1::value> help; + return help::go(x,l); + } + + template + typename result::type + operator()( const T& x, const a_unique_type_for_nil &n ) const { + typedef typename result::type LL; + typedef ConsHelp1::value> help; + return help::go(x,n); + } + + }; + } + + typedef boost::phoenix::function Cons; + Cons cons; + + namespace impl { + + template + struct CatHelp0; + + template + struct CatHelp0 { + typedef typename result_of::template ListType::LType type; + }; + + template + struct CatHelp0 { + typedef typename result_of::template ListType::LType type; + //typedef L type; + }; + + template + struct CatHelp0 { + typedef typename result_of::template ListType::LType type; + //typedef L type; + }; + + template + struct CatHelp0 { + // This removes any references from L for correct return type + // identification. + typedef typename result_of::template ListType::LType type; + // typedef typename ConsHelp1::value>::type type; + }; + + ///////////////////////////////////////////////////////////////////// + // cat (l,m) - concatenate lists. + // Note: The first arg, l, must be a list or NIL. + // The second arg, m, can be a list or NIL + // or a function that returns a list. + ///////////////////////////////////////////////////////////////////// + struct Cat + { + template + struct Helper /*: public c_fun_type*/ { + template struct result; + + template + struct result + { + typedef typename result_of::ListType::tail_result_type type; + }; + + typedef R return_type; + R operator()( const L& l, const M& m, + reuser2::tail_result_type,M> + r = NIL ) const { + if( null(l)() ) + return m().force(); + else + return cons( head(l)(), r( Helper(), tail(l), m )() ); + } + }; + template + struct Helper /*: public c_fun_type*/ { + template struct result; + + template + struct result + { + typedef typename result_of::ListType::tail_result_type type; + }; + typedef R return_type; + R operator()( const L& l, const M& m, + reuser2::tail_result_type,M> + r = NIL ) const { + if( null(l)() ) + return m.force(); + else + return cons( head(l)(), r(Helper(), tail(l), m )()); + } + }; + template + struct Helper + /*: public c_fun_type > */ + { + typedef odd_list::value_type> type; + odd_list::value_type> + operator()( const L& l, const a_unique_type_for_nil& ) const { + return l; + } + }; + public: + /*template struct sig : public fun_type< + typename RT::result_type> + {}; */ + // Need to work out the return type here. + template struct result; + + template + struct result + { + typedef typename CatHelp0::is_nil>::type type; + // typedef typename result_of::ListType::tail_result_type type; + }; + + template + struct result + { + typedef typename result_of::ListType::tail_result_type type; + }; + template + typename result::type operator()( const L& l, const M& m ) const + { + listlike::EnsureListLike(); + return Helper::value, + typename result::type>()(l,m); + } + + template + typename result::type operator()( const L& l, const a_unique_type_for_nil& n ) const + { + listlike::EnsureListLike(); + return l; + } + + }; + + + } + + typedef boost::phoenix::function Cat; + Cat cat; + + +////////////////////////////////////////////////////////////////////// +// Handy functions for making list literals +////////////////////////////////////////////////////////////////////// +// Yes, these aren't functoids, they're just template functions. I'm +// lazy and created these mostly to make it easily to make little lists +// in the sample code snippets that appear in papers. + +struct UseList { + template struct List { typedef list type; }; +}; +struct UseOddList { + template struct List { typedef odd_list type; }; +}; +struct UseStrictList { + template struct List { typedef strict_list type; }; +}; + +template +struct list_with { + template + typename Kind::template List::type + operator()( const T& a ) const { + typename Kind::template List::type l; + l = cons( a, l ); + return l; + } + + template + typename Kind::template List::type + operator()( const T& a, const T& b ) const { + typename Kind::template List::type l; + l = cons( b, l ); + l = cons( a, l ); + return l; + } + + template + typename Kind::template List::type + operator()( const T& a, const T& b, const T& c ) const { + typename Kind::template List::type l; + l = cons( c, l ); + l = cons( b, l ); + l = cons( a, l ); + return l; + } + + template + typename Kind::template List::type + operator()( const T& a, const T& b, const T& c, const T& d ) const { + typename Kind::template List::type l; + l = cons( d, l ); + l = cons( c, l ); + l = cons( b, l ); + l = cons( a, l ); + return l; + } + + template + typename Kind::template List::type + operator()( const T& a, const T& b, const T& c, const T& d, + const T& e ) const { + typename Kind::template List::type l; + l = cons( e, l ); + l = cons( d, l ); + l = cons( c, l ); + l = cons( b, l ); + l = cons( a, l ); + return l; + } +}; +////////////////////////////////////////////////////////////////////// + + } + +} + +#endif diff --git a/include/boost/phoenix/function/lazy_operator.hpp b/include/boost/phoenix/function/lazy_operator.hpp new file mode 100644 index 0000000..c88b768 --- /dev/null +++ b/include/boost/phoenix/function/lazy_operator.hpp @@ -0,0 +1,670 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy operator.hpp +// +// Build lazy operations for Phoenix equivalents for FC++ +// +// These are equivalents of the Boost FC++ functoids in operator.hpp +// +// Implemented so far: +// +// make_pair +// plus minus multiplies divides modulus +// negate equal not_equal greater less +// greater_equal less_equal logical_and logical_or +// logical_not min max inc dec +// +// These are not from the FC++ operator.hpp but were made for testing purposes. +// +// identity (renamed id) +// sin +// +// These are now being modified to use boost::phoenix::function +// so that they are available for use as arguments. +// Types are being defined in capitals e.g. Id id; +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + + +#ifndef BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR +#define BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR + +#include +#include +#include +#include +#include + +namespace boost { + + namespace phoenix { + +////////////////////////////////////////////////////////////////////// +// a_unique_type_for_nil +////////////////////////////////////////////////////////////////////// + +// This may need to be moved elsewhere to define reuser. + struct a_unique_type_for_nil { + bool operator==( a_unique_type_for_nil ) const { return true; } + bool operator< ( a_unique_type_for_nil ) const { return false; } + typedef a_unique_type_for_nil value_type; + }; + // This maybe put into a namespace. + a_unique_type_for_nil NIL; + +////////////////////////////////////////////////////////////////////// +// lazy_exception - renamed from fcpp_exception. +////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + struct lazy_exception : public std::exception { + const char* s; + lazy_exception( const char* ss ) : s(ss) {} + const char* what() const throw() { return s; } + }; +#endif + +////////////////////////////////////////////////////////////////////// + + // in ref_count.hpp in BoostFC++ + typedef unsigned int RefCountType; + + namespace impl { + + struct Id + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0) const + { + return a0; + } + + }; + + + } + + //BOOST_PHOENIX_ADAPT_CALLABLE(id, impl::id, 1) + typedef boost::phoenix::function Id; + Id id; + +#ifdef BOOST_RESULT_OF_USE_TR1 + // Experiment following examples in + // phoenix/stl/container/container.hpp + + namespace result_of { + + template < + typename Arg1 + , typename Arg2 + > + class make_pair + { + public: + typedef typename boost::remove_reference::type Arg1Type; + typedef typename boost::remove_reference::type Arg2Type; + typedef std::pair type; + typedef std::pair result_type; + }; + } +#endif + + namespace impl + { + + struct make_pair { + + +#ifdef BOOST_RESULT_OF_USE_TR1 + template + struct result; + // This fails with -O2 unless refs are removed from A1 and A2. + template + struct result + { + typedef typename result_of::make_pair::type type; + }; +#else + template + struct result; + + template + struct result + : boost::remove_reference > + {}; + +#endif + + + template +#ifdef BOOST_RESULT_OF_USE_TR1 + typename result::type +#else + std::pair +#endif + operator()(A0 const & a0, A1 const & a1) const + { + return std::make_pair(a0,a1); + } + + }; + } + +BOOST_PHOENIX_ADAPT_CALLABLE(make_pair, impl::make_pair, 2) + + namespace impl + { + + // For now I will leave the return type deduction as it is. + // I want to look at bringing in the sort of type deduction for + // mixed types which I have in FC++. + // Also I could look at the case where one of the arguments is + // another functor or a Phoenix placeholder. + struct Plus + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0, A1 const & a1) const + { + //A0 res = a0 + a1; + //return res; + return a0 + a1; + } + + template + A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const + { + return a0 + a1 + a2; + } + }; + + struct Minus + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 - a1; + } + + }; + + struct multiplies + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 * a1; + } + + }; + + struct divides + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 / a1; + } + + }; + + struct modulus + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 % a1; + } + + }; + + struct negate + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0) const + { + return -a0; + } + }; + + struct equal + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 == a1; + } + }; + + struct not_equal + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 != a1; + } + }; + + struct greater + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 > a1; + } + }; + + struct less + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 < a1; + } + }; + + struct greater_equal + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 >= a1; + } + }; + + struct less_equal + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 <= a1; + } + }; + + struct logical_and + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 && a1; + } + }; + + struct logical_or + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 || a1; + } + }; + + struct logical_not + { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + bool operator()(A0 const & a0) const + { + return !a0; + } + }; + + struct min + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0, A1 const & a1) const + { + if ( a0 < a1 ) return a0; else return a1; + } + + }; + + struct max + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0, A1 const & a1) const + { + if ( a0 < a1 ) return a1; else return a0; + } + + }; + + struct Inc + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0) const + { + return a0 + 1; + } + + }; + + struct Dec + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0) const + { + return a0 - 1; + } + + }; + + struct Sin + { + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(A0 const & a0) const + { + return std::sin(a0); + } + + }; + + // Example of templated struct. + // How do I make it callable? + template + struct what { + + typedef Result result_type; + + Result operator()(Result const & r) const + { + return r; + } + // what is not complete - error. + //static boost::function1 res = what(); + }; + + template + struct what0 { + + typedef Result result_type; + + Result operator()() const + { + return Result(100); + } + + }; + + template + class MonomorphicWrapper0 /* : public c_fun_type */ + { + F f; + public: + typedef Result result_type; + MonomorphicWrapper0( const F& g ) : f(g) {} + Result operator()() const { + return f(); + } + }; + + /* I need the equivalent of this + template + full0 > monomorphize0( const F& f ) + { + return make_full0( impl::XMonomorphicWrapper0( f ) ); + }*/ + + + // boost::function0 res = MonomorphicWrapper0(f); + + + template + boost::function monomorphize0( const F& f ) + { + boost::function0 ff = MonomorphicWrapper0( f ); + //BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(Res,fres,ff) + return ff; + } + + // This is C++1y + //template + //static boost::function1 res = what(); + + + } + ///////////////////////////////////////////////////////// + // Look at this. How to use Phoenix with a templated + // struct. First adapt with boost::function and then + // convert that to Phoenix!! + // I have not found out how to do it directly. + ///////////////////////////////////////////////////////// +boost::function1 what_int = impl::what(); +typedef boost::function1 fun1_int_int; +typedef boost::function0 fun0_int; +boost::function0 what0_int = impl::what0(); +BOOST_PHOENIX_ADAPT_FUNCTION(int,what,what_int,1) +BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(int,what0,what0_int) +// And this shows how to make them into argument callable functions. +typedef boost::phoenix::function What_arg; +typedef boost::phoenix::function What0_arg; +What_arg what_arg(what_int); +What0_arg what0_arg(what0_int); + +//BOOST_PHOENIX_ADAPT_CALLABLE(plus, impl::plus, 2) +//BOOST_PHOENIX_ADAPT_CALLABLE(plus, impl::plus, 3) +//BOOST_PHOENIX_ADAPT_CALLABLE(minus, impl::minus, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(multiplies, impl::multiplies, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(divides, impl::divides, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(modulus, impl::modulus, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(negate, impl::negate, 1) +BOOST_PHOENIX_ADAPT_CALLABLE(equal, impl::equal, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(not_equal, impl::not_equal, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(greater, impl::greater, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(less, impl::less, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(greater_equal, impl::greater_equal, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(less_equal, impl::less_equal, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(logical_and, impl::logical_and, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(logical_or, impl::logical_or, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(logical_not, impl::logical_not, 1) +BOOST_PHOENIX_ADAPT_CALLABLE(min, impl::min, 2) +BOOST_PHOENIX_ADAPT_CALLABLE(max, impl::max, 2) +//BOOST_PHOENIX_ADAPT_CALLABLE(inc, impl::inc, 1) +//BOOST_PHOENIX_ADAPT_CALLABLE(dec, impl::dec, 1) +//BOOST_PHOENIX_ADAPT_CALLABLE(sin, impl::sin, 1) + +// To use these as arguments they have to be defined like this. + typedef boost::phoenix::function Plus; + typedef boost::phoenix::function Minus; + typedef boost::phoenix::function Inc; + typedef boost::phoenix::function Dec; + typedef boost::phoenix::function Sin; + Plus plus; + Minus minus; + Inc inc; + Dec dec; + Sin sin; +} + +} + + + + +#endif diff --git a/include/boost/phoenix/function/lazy_prelude.hpp b/include/boost/phoenix/function/lazy_prelude.hpp new file mode 100644 index 0000000..fc1e35a --- /dev/null +++ b/include/boost/phoenix/function/lazy_prelude.hpp @@ -0,0 +1,830 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy prelude.hpp +// +// Build lazy operations for Phoenix equivalents for FC++ +// +// These are equivalents of the Boost FC++ functoids in prelude.hpp +// +// Usage: All of these are functors which need various numbers of arguments. +// Those can be supplied as real arguments or as Phoenix arguments. +// Execution will happen when all the arguments are supplied. +// e.g. +// take(2,list)() or take(2,arg1)(list) +// +// Implemented so far: +// +// id (moved back to operators.hpp) +// +// A lot of what comes here uses the list type, so that will be needed first. +// +// Now that list is available I can start to build things here. +// +// +// until(pred,f,start) - if pred(start) is true, return start +// apply value = f(start) +// apply value = f(value) +// until pred(value) is true +// return value +// +// The predicate argument pred must be a lazy function taking one argument +// and returning bool. +// This can be a lazy function with an argument already. +// This has to be declared before the call to until. +// The type can be declated using Predicate as in this example: +// +// Predicate::type f(greater(arg1,10)); +// std::cout << until(f, inc, 1)() << std::endl; +// +// until2(pred,f,start,value2) - if pred(start,value2) is true, return start +// apply value1 = f(start) +// apply value1 = f(value1) +// until pred(value1,value2) is true +// return value1 +// +// NOTE: until2 has been defined because this code does not support +// FC++ currying, so that a partial function cannot be passed +// as an argument. This provides a way of passing a second parameter. +// There is now the option to use Predicate as shown above. +// +// odd(n) true if n is odd +// even(n) true if n is even +// +// last(list) +// all_but_last(list) +// at(list,n) +// length(list) +// filter(pred,list) +// iterate(function,value) +// repeat(value) +// take(n,list) +// drop(n,list) +// enum_from(x) +// enum_from_to(x,y) +// +//////////////////////////////////////////////////////////////////////////// +// Interdependence: +// The old Boost FC++ has a set of headers which interelate and call each +// other in a complicated way. I am going to document the interdependence +// of the files here. I will then make sure that they are called correctly +// starting from this file. John Fletcher. February 2015. +//////////////////////////////////////////////////////////////////////////// +// BoostFC++ header sequence: +// +// prelude.hpp -> list.hpp (optinally monad.hpp at end) +// list.hpp -> reuse.hpp +// reuse.hpp -> function.hpp +// function.hpp -> ref_count.hpp operator.hpp +// ref_count.hpp -> config.hpp boost headers and RefCountType definition +// operator.hpp -> lambda.hpp +// lambda.hpp -> full.hpp (use of lambda internals is optional) +// full.hpp -> smart.hpp curry.hpp pre_lambda.hpp (optionally full4.hpp) +// smart.hpp -> signature.hpp +// curry.hpp -> signature.hpp +// signature.hpp -> config.hpp +// +//////////////////////////////////////////////////////////////////////////// +// Proposed order in lazy_prelude.hpp +// on the basis that files need what they call. +// +// lazy_config.hpp (If needed)* probably not needed. +// lazy_signature.hpp (If needed)* +// lazy_smart.hpp (If needed)* +// lazy_curry.hpp (If needed)* +// lazy_full.hpp (If needed)* +// lazy_operator.hpp (absorb definition of RefCountType) +// lazy_function.hpp (may not now be needed) +// lazy_reuse.hpp (implemented without use of FC++ functions) +// lazy_list.hpp +// +// * file does not yet exist. +//////////////////////////////////////////////////////////////////////////// +// This is implemented such that no other lazy_ file calls other lazy_ files. +// They do call their own external files, which may well be duplicates. +// That can be sorted out later. +//////////////////////////////////////////////////////////////////////////// +// Notes: full and curry operations should be covered by Phoenix. +// The lambda operations are quite different from Phoenix lambda +// and will be omitted. +// The implementation monad can be postponed. +// Some of function and reuse are needed for the list type. +// I will review later whether they are part of the external interface. +// +// John Fletcher February 2015. +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + + +#ifndef BOOST_PHOENIX_FUNCTION_LAZY_PRELUDE +#define BOOST_PHOENIX_FUNCTION_LAZY_PRELUDE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////// +// To come here, the Haskell Prelude things which need list. +// Things which do not need list are in lazy_operator.hpp. +//////////////////////////////////////////////////////////////////////////// + +namespace boost { + + namespace phoenix { + + // These are in fcpp namespace as they introduce an FC++ style. + namespace fcpp { + + template + struct Predicate { + typedef typename boost::function1 fun1_bool_T; + typedef typename boost::phoenix::function bool_F_T; + typedef bool_F_T type; + }; + + template + struct Function0 { + typedef typename boost::function0 fun0_R; + typedef typename boost::phoenix::function R_F; + typedef R_F type; + }; + + template + struct Function1 { + typedef typename boost::function1 fun1_R_A0; + typedef typename boost::phoenix::function R_F_A0; + typedef R_F_A0 type; + }; + + template + struct Function2 { + typedef typename boost::function2 fun2_R_A0_A1; + typedef typename boost::phoenix::function R_F_A0_A1; + typedef R_F_A0_A1 type; + }; + + } + + namespace impl { + using fcpp::INV; + using fcpp::VAR; + using fcpp::reuser1; + using fcpp::reuser2; + using fcpp::reuser3; + using boost::phoenix::arg_names::arg1; + + struct Pow { + + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(N n, const A0 & a0, + reuser2 r = NIL ) const { + if ( n <= 0 ) + return A0(1); + else if ( n==1 ) + return a0; + else { + A0 a1 = r( Pow(), n-1, a0)(); + return a0*a1; + } + } + + }; + + struct Apply { + + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + A0 operator()(N n, const F &f, const A0 & a0, + reuser3 r = NIL ) const { + if ( n <= 0 ) + return a0; + else if ( n==1 ) + return f(arg1)(a0); + else { + A0 a1 = r( Apply(), n-1, f, a0)(); + return f(a1)(); + } + } + + }; + + // This will apply f() at least once. + struct Apply0 { + + template + struct result; + + template + struct result + { + // Need result type from F + typedef typename F::result_type type; + }; + + template + typename result::type operator()(N n, const F &f, + reuser2 r = NIL ) const { + if ( n <= 1 ) + return f()(); + else { + A0 a1 = r( Apply(), n-1, f)(); + return f()(); + } + } + + }; + + struct Odd { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + typename result::type operator()( const T& x ) const { + return x%2==1; + } + }; + + struct Even { + template + struct result; + + template + struct result + { + typedef bool type; + }; + + template + typename result::type operator()( const T& x ) const { + return x%2==0; + } + }; + + } + typedef boost::phoenix::function Pow; + typedef boost::phoenix::function Apply; + typedef boost::phoenix::function Apply0; + typedef boost::phoenix::function Odd; + typedef boost::phoenix::function Even; + Pow pow; + Apply apply; + Apply apply0; + Odd odd; + Even even; + + namespace impl { + using fcpp::INV; + using fcpp::VAR; + using fcpp::reuser1; + using fcpp::reuser2; + using fcpp::reuser3; + using boost::phoenix::arg_names::arg1; + + // I cannot yet do currying to pass e.g. greater(9,arg1) + // as a function. This can be done using Predicate::type. + struct Until { + + template struct result; + + template + struct result + : boost::remove_reference {}; + + template + T operator()( const Pred& p,const Unary& op,const T &start) const + { + T tmp = start; + while( !p(tmp)() ) { + tmp = apply(1,op,tmp)(); + } + return tmp; + } + + }; + + struct Until2 { + + template struct result; + + template + struct result + : boost::remove_reference {}; + + template + typename result::type + operator()( const Binary& p, const Unary& op, const T & start, + const X & check ) const + { + T tmp1 = start; + T tmp2; + while( !p(tmp1,check)() ) { + tmp2 = apply(1,op,tmp1)(); + tmp1 = tmp2; + + } + return tmp1; + } + }; + + struct Last { + template struct result; + + template + struct result + { + typedef typename result_of::ListType::value_type type; + }; + + template + typename result::type + operator()( const L& ll ) const { + size_t x = 0; + typename result_of::ListType::delay_result_type l = delay(ll); + while( !null( tail(l)() )() ) { + l = tail(l)(); + ++x; +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) + break; +#endif + } +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) + throw lazy_exception("Your list is too long!!"); +#endif + return head(l)(); + } + }; + + struct Init { + + template struct result; + + template + struct result + { + typedef typename result_of::ListType::force_result_type type; + }; + + template + typename result::type + operator()( const L& l, + reuser1::delay_result_type> + r = NIL ) const { + if( null( tail( l )() )() ) + return NIL; + else + return cons( head(l)(), r( Init(), tail(l)() )() )(); + } + }; + + struct Length { + template struct result; + + template + struct result + { + typedef size_t type; + }; + + template + size_t operator()( const L& ll ) const { + typename L::delay_result_type l = delay(ll); + size_t x = 0; + while( !null(l)() ) { + l = tail(l); + ++x; + if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) + break; + } +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) + throw lazy_exception("Your list is too long!!"); +#endif + return x; + } + }; + + // at is Haskell's operator (!!) + // This is zero indexed. at(l,0)() returns the first element. + struct At { + template struct result; + + template + struct result + { + typedef typename result_of::ListType::value_type type; + }; + + template + typename result::type + operator()( L l, size_t n ) const { + while( n!=0 ) { + l = tail(l); + --n; + } + return head(l)(); + } + }; + + template + struct FilterH + { + P p; + L l; + FilterH( const P& pp, const L& ll) : p(pp), l(ll) {} + template struct result; + + template + struct result + { + typedef typename boost::phoenix::result_of:: + ListType::delay_result_type type; + }; + typename result::type operator()() const { + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 Fun2_R_P_L; + typedef boost::phoenix::function FilterH_R_P_L; + if (null(l)() ) + return NIL; + Fun2_R_P_L fun2_R_P_L = FilterH(p,tail(l)); + FilterH_R_P_L filterh_R_P_L(fun2_R_P_L); + if( p(head(l))() ) + return cons( head(l)(), filterh_R_P_L() ); + else + return filterh_R_P_L(); + } + }; + + struct Filter { + template struct result; + + template + struct result + { + typedef typename result_of::ListType::delay_result_type + type; + }; + + template + typename result::type + operator()( const P& p, const L& ll) const + { + typename result_of::ListType::delay_result_type + l = delay(ll); + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 Fun2_R_P_L; + typedef boost::phoenix::function FilterH_R_P_L; + Fun2_R_P_L fun2_R_P_L = FilterH(p,l); + FilterH_R_P_L filterh_R_P_L(fun2_R_P_L); + return filterh_R_P_L(); + } + }; + + template + struct IterateH + { + F f; + T t; + IterateH( const F& ff, const T& tt) : f(ff), t(tt) {} + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type type; + }; + + typename result::type operator()() const { + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 Fun2_R_F_T; + typedef boost::phoenix::function IterateH_R_F_T; + Fun2_R_F_T fun2_R_F_T = IterateH(f,f(t)()); + IterateH_R_F_T iterateh_R_F_T(fun2_R_F_T); + return cons( t, iterateh_R_F_T() ); + } + }; + + + struct Iterate { + // Note: this does always return an odd_list; iterate() takes no ListLike + // parameter, and it requires that its result be lazy. + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type type; + }; + + template + typename result::type operator() + (const F& f, const T& t) const { + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 Fun2_R_F_T; + typedef boost::phoenix::function IterateH_R_F_T; + Fun2_R_F_T fun2_R_F_T = IterateH(f,f(t)()); + IterateH_R_F_T iterateh_R_F_T(fun2_R_F_T); + return iterateh_R_F_T(); + } + }; + + } + + typedef boost::phoenix::function Until; + typedef boost::phoenix::function Until2; + typedef boost::phoenix::function Last; + typedef boost::phoenix::function Init; + typedef boost::phoenix::function Length; + typedef boost::phoenix::function At; + typedef boost::phoenix::function Filter; + typedef boost::phoenix::function Iterate; + Until until; + Until2 until2; + Last last; + Init all_but_last; // renamed from init which is not available. + Length length; + At at; + Filter filter; + Iterate iterate; + + namespace impl { + + struct Repeat { + // See note for iterate() + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type type; + }; + + template + typename result::type operator()( const T& x) const + { + return iterate(id,x); + } + }; + + struct Take { + + template struct result; + + template + struct result + { + typedef typename result_of::ListType::force_result_type type; + }; + + template + typename result::type + operator()( N n, const L& l, + reuser2::force_result_type> + r = NIL + ) const { + if( n <= 0 || null(l)() ) + return NIL; + else { + return cons( head(l)(), r( Take(), n-1, tail(l)() )() )(); + } + } + }; + + struct Drop { + template struct result; + + template + struct result + { + typedef typename result_of::ListType::delay_result_type type; + }; + + template + typename result::type + operator()( size_t n, const L& ll ) const { + typename L::delay_result_type l = delay(ll); + while( n!=0 && !null(l)() ) { + --n; + l = tail(l)(); + } + return l; + } + }; + + template + struct EFH + { + typedef typename boost::remove_reference TT; + typedef typename boost::remove_const::type TTT; + mutable T x; + EFH( const T& xx) : x(xx) {} + template struct result; + + template + struct result + { + typedef typename boost::phoenix::UseList::template + List::type LType; + typedef typename boost::phoenix::result_of:: + ListType::delay_result_type type; + }; + typename result::type operator()() const { + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 fun1_R_TTT; + //std::cout << "EFH (" << x << ")" << std::endl; + ++x; + fun1_R_TTT efh_R_TTT = EFH(x); + typedef boost::phoenix::function EFH_R_T; + EFH_R_T efh_R_T(efh_R_TTT); +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) + throw lazy_exception("Running away in EFH!!"); +#endif + return cons( x-1, efh_R_T() ); + } + }; + + struct Enum_from { + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type type; + }; + + template + typename result::type operator() + (const T & x) const + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 fun1_R_TTT; + fun1_R_TTT efh_R_TTT = EFH(x); + typedef boost::phoenix::function EFH_R_T; + EFH_R_T efh_R_T(efh_R_TTT); + //std::cout << "enum_from (" << x << ")" << std::endl; + return efh_R_T(); + } + }; + + template + struct EFTH + { + typedef typename boost::remove_reference TT; + typedef typename boost::remove_const::type TTT; + mutable T x; + T y; + EFTH( const T& xx, const T& yy) : x(xx), y(yy) {} + template struct result; + + template + struct result + { + typedef typename boost::phoenix::UseList::template + List::type LType; + typedef typename boost::phoenix::result_of:: + ListType::delay_result_type type; + }; + typename result::type operator()() const { + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 fun1_R_TTT; + //std::cout << "EFTH (" << x << ")" << std::endl; + if (x > y ) return NIL; + ++x; + fun1_R_TTT efth_R_TTT = EFTH(x,y); + typedef boost::phoenix::function EFTH_R_T; + EFTH_R_T efth_R_T(efth_R_TTT); +#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS + if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) + throw lazy_exception("Running away in EFTH!!"); +#endif + return cons( x-1, efth_R_T() ); + } + }; + + struct Enum_from_to { + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type type; + }; + + template + typename result::type operator() + (const T & x, const T & y) const + { + typedef typename boost::remove_reference::type TT; + typedef typename boost::remove_const::type TTT; + typedef typename UseList::template List::type LType; + typedef typename result_of::ListType:: + delay_result_type result_type; + typedef boost::function0 fun1_R_TTT; + fun1_R_TTT efth_R_TTT = EFTH(x,y); + typedef boost::phoenix::function EFTH_R_T; + EFTH_R_T efth_R_T(efth_R_TTT); + //std::cout << "enum_from (" << x << ")" << std::endl; + return efth_R_T(); + } + }; + + } + + + //BOOST_PHOENIX_ADAPT_CALLABLE(apply, impl::apply, 3) + // Functors to be used in reuser will have to be defined + // using boost::phoenix::function directly + // in order to be able to be used as arguments. + typedef boost::phoenix::function Repeat; + typedef boost::phoenix::function Take; + typedef boost::phoenix::function Drop; + typedef boost::phoenix::function Enum_from; + typedef boost::phoenix::function Enum_from_to; + Repeat repeat; + Take take; + Drop drop; + Enum_from enum_from; + Enum_from_to enum_from_to; + + namespace fcpp { + + + } + + } + +} + + +#endif diff --git a/include/boost/phoenix/function/lazy_reuse.hpp b/include/boost/phoenix/function/lazy_reuse.hpp new file mode 100644 index 0000000..cef2ded --- /dev/null +++ b/include/boost/phoenix/function/lazy_reuse.hpp @@ -0,0 +1,242 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy_reuse.hpp +// +// Build lazy operations for Phoenix equivalents for FC++ +// +// These are equivalents of the Boost FC++ functoids in reuse.hpp +// +// Implemented so far: +// +// reuser1 (not yet tested) +// reuser2 (not yet tested) +// reuser3 +// +// NOTE: It has been possible to simplify the operation of this code. +// It now makes no use of boost::function or old FC++ code. +// +// The functor type F must be an operator defined with +// boost::phoenix::function. +// See the example Apply in lazy_prelude.hpp +// +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + +#ifndef BOOST_PHOENIX_FUNCTION_LAZY_REUSE +#define BOOST_PHOENIX_FUNCTION_LAZY_REUSE + +#include +#include +#include + + +namespace boost { + + namespace phoenix { + + namespace fcpp { + +////////////////////////////////////////////////////////////////////// +// Original FC++ comment: +// "Reuser"s are effectively special-purpose versions of curry() that +// enable recursive list functoids to reuse the thunk of the curried +// recursive call. See +// http://www.cc.gatech.edu/~yannis/fc++/New/reusers.html +// for a more detailed description. +////////////////////////////////////////////////////////////////////// + +// For efficiency, we mark parameters as either "VAR"iant or "INV"ariant. +struct INV {}; +struct VAR {}; + +template struct Maybe_Var_Inv; +template +struct Maybe_Var_Inv { + static void remake( X& x, const X& val ) { + x.~X(); + new (&x) X(val); + } + static X clone( const X& x ) { return X(x); } +}; +template +struct Maybe_Var_Inv { + static void remake( X&, const X& ) {} + static const X& clone( const X& x ) { return x; } +}; + +///////////////////////////////////////////////////////////////////// +// ThunkImpl is an implementation of Fun0Impl for this use. +///////////////////////////////////////////////////////////////////// + +template +class ThunkImpl +{ + mutable RefCountType refC; +public: + ThunkImpl() : refC(0) {} + virtual Result operator()() const =0; + virtual ~ThunkImpl() {} + template + friend void intrusive_ptr_add_ref( const ThunkImpl* p ); + template + friend void intrusive_ptr_release( const ThunkImpl* p ); +}; + +template +void intrusive_ptr_add_ref( const ThunkImpl* p ) { + ++ (p->refC); +} +template +void intrusive_ptr_release( const ThunkImpl* p ) { + if( !--(p->refC) ) delete p; +} + +////////////////////////////////////////////////////////////////////// +// reuser1 is needed in list operations +////////////////////////////////////////////////////////////////////// + +template +struct reuser1; + +template +struct Thunk1 : public ThunkImpl { + mutable F f; + mutable X x; + Thunk1( const F& ff, const X& xx ) : f(ff), x(xx) {} + void init( const F& ff, const X& xx ) const { + Maybe_Var_Inv::remake( f, ff ); + Maybe_Var_Inv::remake( x, xx ); + } + R operator()() const { + return Maybe_Var_Inv::clone(f)( + Maybe_Var_Inv::clone(x), + reuser1(this) ); + } +}; + +template +struct reuser1 { + typedef typename F::template result::type R; + typedef typename boost::phoenix::function fun0_type; + typedef Thunk1 M; + typedef M result_type; + boost::intrusive_ptr ref; + reuser1(a_unique_type_for_nil) {} + reuser1(const M* m) : ref(m) {} + M operator()( const F& f, const X& x ) { + if( !ref ) ref = boost::intrusive_ptr( new M(f,x) ); + else ref->init(f,x); + return *ref; + } + void iter( const F& f, const X& x ) { + if( ref ) ref->init(f,x); + } +}; + +////////////////////////////////////////////////////////////////////// +// reuser2 is needed in list +////////////////////////////////////////////////////////////////////// + +template +struct reuser2; + +template +struct Thunk2 : public ThunkImpl { + mutable F f; + mutable X x; + mutable Y y; + Thunk2( const F& ff, const X& xx, const Y& yy ) : f(ff), x(xx), y(yy) {} + void init( const F& ff, const X& xx, const Y& yy ) const { + Maybe_Var_Inv::remake( f, ff ); + Maybe_Var_Inv::remake( x, xx ); + Maybe_Var_Inv::remake( y, yy ); + } + R operator()() const { + return Maybe_Var_Inv::clone(f)( + Maybe_Var_Inv::clone(x), + Maybe_Var_Inv::clone(y), + reuser2(this) ); + } +}; + +template +struct reuser2 { + typedef typename F::template result::type R; + typedef Thunk2 M; + typedef M result_type; + boost::intrusive_ptr ref; + reuser2(a_unique_type_for_nil) {} + reuser2(const M* m) : ref(m) {} + M operator()( const F& f, const X& x, const Y& y ) { + if( !ref ) ref = boost::intrusive_ptr( new M(f,x,y) ); + else ref->init(f,x,y); + return *ref; + } + void iter( const F& f, const X& x, const Y& y ) { + if( ref ) ref->init(f,x,y); + } +}; + +////////////////////////////////////////////////////////////////////// +// reuser3 +////////////////////////////////////////////////////////////////////// + +template +struct reuser3; + +template +struct Thunk3 : public ThunkImpl { + mutable F f; + mutable X x; + mutable Y y; + mutable Z z; + Thunk3( const F& ff, const X& xx, const Y& yy, const Z& zz ) + : f(ff), x(xx), y(yy), z(zz) {} + void init( const F& ff, const X& xx, const Y& yy, const Z& zz ) const { + Maybe_Var_Inv::remake( f, ff ); + Maybe_Var_Inv::remake( x, xx ); + Maybe_Var_Inv::remake( y, yy ); + Maybe_Var_Inv::remake( z, zz ); + } + R operator()() const { + return Maybe_Var_Inv::clone(f)( + Maybe_Var_Inv::clone(x), + Maybe_Var_Inv::clone(y), + Maybe_Var_Inv::clone(z), + reuser3(this) ); + } +}; + +template +struct reuser3 { + typedef typename F::template result::type R; + typedef Thunk3 M; + typedef M result_type; + boost::intrusive_ptr ref; + reuser3(a_unique_type_for_nil) {} + reuser3(const M* m) : ref(m) {} + M operator()( const F& f, const X& x, const Y& y, const Z& z ) { + if( !ref ) ref = boost::intrusive_ptr( new M(f,x,y,z) ); + else ref->init(f,x,y,z); + return *ref; + } + void iter( const F& f, const X& x, const Y& y, const Z& z ) { + if( ref ) ref->init(f,x,y,z); + } +}; + + } + + } +} + +#endif diff --git a/include/boost/phoenix/version.hpp b/include/boost/phoenix/version.hpp index ce813ba..baf215d 100644 --- a/include/boost/phoenix/version.hpp +++ b/include/boost/phoenix/version.hpp @@ -14,7 +14,7 @@ // This is the version of the library // /////////////////////////////////////////////////////////////////////////////// -#define BOOST_PHOENIX_VERSION 0x3101 // 3.1.1 +#define BOOST_PHOENIX_VERSION 0x3200 // 3.2.0 // boost/predef is not in Boost before 1.55.0 #include @@ -26,7 +26,7 @@ #endif #ifdef BOOST_PHOENIX_HAVE_BOOST_PREDEF -#define BOOST_PHOENIX_VERSION_NUMBER = BOOST_VERSION_NUMBER(3,1,1) +#define BOOST_PHOENIX_VERSION_NUMBER = BOOST_VERSION_NUMBER(3,2,0) #endif #endif diff --git a/test/Jamfile b/test/Jamfile index 8b04926..8120377 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -53,8 +53,12 @@ test-suite phoenix_function : [ run function/adapt_function.cpp ] [ run function/function_tests.cpp ] [ run function/lazy_argument_tests.cpp ] + [ run function/lazy_list_tests.cpp ] + [ run function/lazy_list2_tests.cpp ] + [ run function/lazy_list3_tests.cpp ] [ run function/lazy_make_pair_tests.cpp ] [ run function/lazy_templated_struct_tests.cpp ] + [ run function/lazy_operator_tests.cpp ] # [ run function/function_tests_phx2.cpp ] ; @@ -221,6 +225,7 @@ test-suite phoenix_include : [ run include/core/value.cpp ] [ run include/core/visit_each.cpp ] [ run include/function/function.cpp : : : : function_function ] + [ run include/function/lazy_headers.cpp ] [ run include/fusion/at.cpp ] [ run include/object/const_cast.cpp ] [ run include/object/construct.cpp ] diff --git a/test/boost_bind_compatibility/bind_dm_test.cpp b/test/boost_bind_compatibility/bind_dm_test.cpp index fcf699d..44fbd26 100644 --- a/test/boost_bind_compatibility/bind_dm_test.cpp +++ b/test/boost_bind_compatibility/bind_dm_test.cpp @@ -71,7 +71,8 @@ int main() int const v = 42; -#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 50000) && __OPTIMIZE__ +//#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 50000) && __OPTIMIZE__ +#if defined(__OPTIMIZE__) && __OPTIMIZE__ // Change bind_dm_test.cpp to bind to _1 twice. BOOST_TEST( bind( &X::m, _1)( bind( f, _1 )( v ) ) == v ); #else diff --git a/test/function/lazy_list2_tests.cpp b/test/function/lazy_list2_tests.cpp new file mode 100644 index 0000000..c294a8f --- /dev/null +++ b/test/function/lazy_list2_tests.cpp @@ -0,0 +1,42 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy_list2_tests.cpp +// +// more tests on list +// +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + +#include + +#include +#include +#include + + +int main() +{ + namespace phx = boost::phoenix; + using boost::phoenix::arg_names::arg1; + using boost::phoenix::arg_names::arg2; + using namespace phx; + + list l0; + list l1 = list_with<>()(1,2,3,4,5); + list l2 = all_but_last(l1)(); + + BOOST_TEST(null(l0)()); + BOOST_TEST(head(l1)() == 1); + BOOST_TEST(head(tail(l1))() == 2); + BOOST_TEST(last(l1)() == 5); + BOOST_TEST(last(l2)() == 4); + BOOST_TEST(head(drop(2,l2))() == 3); + + return boost::report_errors(); +} diff --git a/test/function/lazy_list3_tests.cpp b/test/function/lazy_list3_tests.cpp new file mode 100644 index 0000000..53d7868 --- /dev/null +++ b/test/function/lazy_list3_tests.cpp @@ -0,0 +1,54 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy_list3_tests.cpp +// +// more tests on list +// +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + +#include + +#include +#include +#include + + +int main() +{ + namespace phx = boost::phoenix; + //using boost::phoenix::arg_names::arg1; + //using boost::phoenix::arg_names::arg2; + using namespace phx; + + list l = enum_from(2); + list ll = take(4,l); + list lll = take(12,l); + list l2 = enum_from_to(2,10); + list ll2 = take(4,l2); + list lll2 = take(12,l2); + list evens = filter(even,l); + list odds = filter(odd,l); + list even4 = take(4,evens)(); + list odd4 = take(4,odds)(); + list itersome = take(4,iterate(dec,1))(); + list repeatsome = take(4,repeat(1))(); + + BOOST_TEST(last(ll)() == 5); + BOOST_TEST(last(lll)() == 13); + BOOST_TEST(last(ll2)() == 5); + BOOST_TEST(last(lll2)() == 10); + BOOST_TEST(length(lll2)() == 9); + BOOST_TEST(at(even4,3)() == 8); + BOOST_TEST(at(odd4,2)() == 7); + BOOST_TEST(at(itersome,3)() == -3); + BOOST_TEST(at(repeatsome,3)() == 1); + + return boost::report_errors(); +} diff --git a/test/function/lazy_list_tests.cpp b/test/function/lazy_list_tests.cpp new file mode 100644 index 0000000..47caf64 --- /dev/null +++ b/test/function/lazy_list_tests.cpp @@ -0,0 +1,78 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy_list_tests.cpp +// +// tests on list +// +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + +#include + +#include +#include +#include + + +int main() +{ + namespace phx = boost::phoenix; + using boost::phoenix::arg_names::arg1; + using boost::phoenix::arg_names::arg2; + using phx::null; + using phx::list; + using phx::head; + using phx::tail; + using phx::cons; + using phx::cat; + using phx::take; + using phx::NIL; + + list l0; + list l1 = cons(1,l0); + list l2 = cons(2,l1); + list l3 = cons(3,l2); + list l4 = cons(4,l3); + list l5 = cons(5,NIL); + list l6 = take(2,l4)(); + list l7 = cons(7,take(2,l4)); + list l8 = take(1,take(3,l4))(); + + BOOST_TEST(null(l0)()); + BOOST_TEST(null(arg1)(l0)); + BOOST_TEST(head(l1)() == 1); + BOOST_TEST(head(arg1)(l1) == 1); + BOOST_TEST(head(tail(l2))() == 1); + BOOST_TEST(head(tail(arg1))(l2) == 1); + BOOST_TEST(head(tail(tail(l3)))() == 1); + BOOST_TEST(head(tail(tail(arg1)))(l3) == 1); + BOOST_TEST(head(tail(tail(l4)))() == 2); + BOOST_TEST(head(tail(tail(arg1)))(l4) == 2); + BOOST_TEST(head(l5)() == 5); + BOOST_TEST(head(arg1)(l5) == 5); + BOOST_TEST(head(tail(l6))() == 3); + BOOST_TEST(head(tail(arg1))(l6) == 3); + BOOST_TEST(head(tail(l7))() == 4); + BOOST_TEST(head(tail(arg1))(l7) == 4); + BOOST_TEST(head(l8)() == 4); + BOOST_TEST(head(arg1)(l8) == 4); + + list l9 = cat(l8,take(2,l4)); + list l10 = cat(l8,NIL); + list l11 = cat(l0,l7); + list l12 = cat(l10,l8); + + BOOST_TEST(head(tail(l9))() == 4); + BOOST_TEST(head(l10)() == 4); + BOOST_TEST(head(arg1)(l11) == 7); + BOOST_TEST(head(l12)() == 4); + + + return boost::report_errors(); +} diff --git a/test/function/lazy_operator_tests.cpp b/test/function/lazy_operator_tests.cpp new file mode 100644 index 0000000..ef05717 --- /dev/null +++ b/test/function/lazy_operator_tests.cpp @@ -0,0 +1,46 @@ +//////////////////////////////////////////////////////////////////////////// +// lazy_operator_tests.cpp +// +// lazy operator tests +// +//////////////////////////////////////////////////////////////////////////// +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2015 John Fletcher + + 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) +==============================================================================*/ + +#include + +#include +#include +#include + + +int main() +{ + using boost::phoenix::plus; + using boost::phoenix::minus; + using boost::phoenix::arg_names::arg1; + using boost::phoenix::arg_names::arg2; + + int a = 123; + int b = 256; + + BOOST_TEST(plus(arg1, arg2)(a, b) == a+b); + BOOST_TEST(plus(arg1, arg2, 3)(a, b) == a+b+3); + BOOST_TEST(plus(arg1, b)(a) == a+b); + BOOST_TEST(plus(a, arg2)(a,b) == a+b); + BOOST_TEST(plus(a, arg1)(b) == a+b); + BOOST_TEST(plus(a, b)() == a+b); + BOOST_TEST(minus(a, b)() == a-b); + BOOST_TEST(plus(minus(a, b),b)() == a); + BOOST_TEST(plus(minus(arg1, b),b)(a) == a); + BOOST_TEST(plus(minus(arg1, arg2),b)(a,b) == a); + BOOST_TEST(plus(minus(arg1, arg2),arg2)(a,b) ==a); + + return boost::report_errors(); +} diff --git a/test/include/function/lazy_headers.cpp b/test/include/function/lazy_headers.cpp new file mode 100644 index 0000000..8015d18 --- /dev/null +++ b/test/include/function/lazy_headers.cpp @@ -0,0 +1,10 @@ +/*============================================================================= + Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2011 Thomas Heller + Copyright (c) 2015 John Fletcher + 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) +==============================================================================*/ +#include +int main() {} diff --git a/test/scope/lambda_tests3a.cpp b/test/scope/lambda_tests3a.cpp index 20ff470..ce9846f 100644 --- a/test/scope/lambda_tests3a.cpp +++ b/test/scope/lambda_tests3a.cpp @@ -53,7 +53,8 @@ main() } { -#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 50000) && __OPTIMIZE__ +//#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 50000) && __OPTIMIZE__ +#if defined(__OPTIMIZE__) && __OPTIMIZE__ int x = (let(_a = _1)[bind(_a)])(lambda[val(1)]()); #else int x = (let(_a = lambda[val(1)])[bind(_a)])(); diff --git a/test/scope/let_tests.cpp b/test/scope/let_tests.cpp index 5a8424d..34350ea 100644 --- a/test/scope/let_tests.cpp +++ b/test/scope/let_tests.cpp @@ -152,7 +152,7 @@ main() { // show that we can return a local from an outer scope int y = 0; -#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 50000) && __OPTIMIZE__ +#if defined(__OPTIMIZE__) && __OPTIMIZE__ int x = (let(_a = _2)[let(_b = _1)[ _a ]])(y,1); #else int x = (let(_a = 1)[let(_b = _1)[ _a ]])(y); diff --git a/test/scope/let_tests_157.cpp b/test/scope/let_tests_157.cpp index 41211d2..7979cea 100644 --- a/test/scope/let_tests_157.cpp +++ b/test/scope/let_tests_157.cpp @@ -152,7 +152,7 @@ main() { // show that we can return a local from an outer scope int y = 0; -#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 50000) && __OPTIMIZE__ +#if defined(__OPTIMIZE__) && __OPTIMIZE__ int x = (let(_a = _2)[let(_b = _1)[ _a ]])(y,1); #else int x = (let(_a = 1)[let(_b = _1)[ _a ]])(y);