diff --git a/build_h2.bat b/build_h2.bat index 080a89ff6..50e0da0c4 100644 --- a/build_h2.bat +++ b/build_h2.bat @@ -3,4 +3,5 @@ cd source cppfront reflect.h2 -verb %1 cd ..\include cppfront cpp2regex.h2 -verb %1 +cppfront cpp2taylor.h2 -verb %1 cd.. diff --git a/include/cpp2ad_stack.h b/include/cpp2ad_stack.h new file mode 100644 index 000000000..cdc13efaa --- /dev/null +++ b/include/cpp2ad_stack.h @@ -0,0 +1,38 @@ +#ifndef CPP2_CPP2AD_STACK_H +#define CPP2_CPP2AD_STACK_H + +#include + +namespace cpp2 { + +struct ad_stack { + + template + static void push(T const& v) { + std::vector& stack = get_stack(); + + stack.push_back(v); + } + + template + static T pop() { + std::vector& stack = get_stack(); + + T v = stack.back(); + stack.pop_back(); + + return v; + } + + private: + + template + static std::vector& get_stack() { + static std::vector stack = {}; + + return stack; + } +}; +} // cpp2 namespace + +#endif // CPP2_CPP2AD_STACK_H \ No newline at end of file diff --git a/include/cpp2regex.h b/include/cpp2regex.h index e2a69946c..146372422 100644 --- a/include/cpp2regex.h +++ b/include/cpp2regex.h @@ -261,10 +261,10 @@ template [[nodiscard]] auto make_ #line 184 "cpp2regex.h2" // Helpers for creating wrappers of the iterators. // -template [[nodiscard]] auto make_forward_iterator(Iter const& pos) -> auto; -template [[nodiscard]] auto make_forward_iterator(std::reverse_iterator const& pos) -> auto; -template [[nodiscard]] auto make_reverse_iterator(Iter const& pos) -> auto; -template [[nodiscard]] auto make_reverse_iterator(std::reverse_iterator const& pos) -> auto; +template [[nodiscard]] auto cpp2_make_forward_iterator(Iter const& pos) -> auto; +template [[nodiscard]] auto cpp2_make_forward_iterator(std::reverse_iterator const& pos) -> auto; +template [[nodiscard]] auto cpp2_make_reverse_iterator(Iter const& pos) -> auto; +template [[nodiscard]] auto cpp2_make_reverse_iterator(std::reverse_iterator const& pos) -> auto; #line 192 "cpp2regex.h2" // End function that returns a valid match. @@ -927,13 +927,13 @@ template [[nodiscard]] auto make_ } #line 186 "cpp2regex.h2" -template [[nodiscard]] auto make_forward_iterator(Iter const& pos) -> auto { return pos; } +template [[nodiscard]] auto cpp2_make_forward_iterator(Iter const& pos) -> auto { return pos; } #line 187 "cpp2regex.h2" -template [[nodiscard]] auto make_forward_iterator(std::reverse_iterator const& pos) -> auto { return CPP2_UFCS(base)(pos); } +template [[nodiscard]] auto cpp2_make_forward_iterator(std::reverse_iterator const& pos) -> auto { return CPP2_UFCS(base)(pos); } #line 188 "cpp2regex.h2" -template [[nodiscard]] auto make_reverse_iterator(Iter const& pos) -> auto { return std::make_reverse_iterator(pos); } +template [[nodiscard]] auto cpp2_make_reverse_iterator(Iter const& pos) -> auto { return std::make_reverse_iterator(pos); } #line 189 "cpp2regex.h2" -template [[nodiscard]] auto make_reverse_iterator(std::reverse_iterator const& pos) -> auto { return pos; } +template [[nodiscard]] auto cpp2_make_reverse_iterator(std::reverse_iterator const& pos) -> auto { return pos; } #line 196 "cpp2regex.h2" [[nodiscard]] auto true_end_func::operator()(auto const& cur, auto& ctx) const& -> decltype(auto) { return ctx.pass(cur); } @@ -1153,7 +1153,7 @@ template [[nodiscard]] auto line_start_toke #line 575 "cpp2regex.h2" template [[nodiscard]] auto lookahead_token_matcher(auto const& cur, auto& ctx, auto const& func) -> bool { - auto r {func(make_forward_iterator(cur), make_forward_match_context(ctx), true_end_func())}; + auto r {func(cpp2_make_forward_iterator(cur), make_forward_match_context(ctx), true_end_func())}; if (!(positive)) { r.matched = !(r.matched); } @@ -1164,7 +1164,7 @@ template [[nodiscard]] auto lookahead_token_match #line 589 "cpp2regex.h2" template [[nodiscard]] auto lookbehind_token_matcher(auto const& cur, auto& ctx, auto const& func) -> bool { - auto r {func(make_reverse_iterator(cur), make_reverse_match_context(ctx), true_end_func())}; + auto r {func(cpp2_make_reverse_iterator(cur), make_reverse_match_context(ctx), true_end_func())}; if (!(positive)) { r.matched = !(r.matched); } diff --git a/include/cpp2regex.h2 b/include/cpp2regex.h2 index 763c5638b..6fbc03f12 100644 --- a/include/cpp2regex.h2 +++ b/include/cpp2regex.h2 @@ -183,10 +183,10 @@ make_reverse_match_context: (inout ctx: reverse_m // Helpers for creating wrappers of the iterators. // -make_forward_iterator: (pos: Iter) -> _ = pos; -make_forward_iterator: (pos: std::reverse_iterator) -> _ = pos.base(); -make_reverse_iterator: (pos: Iter) -> _ = std::make_reverse_iterator(pos); -make_reverse_iterator: (pos: std::reverse_iterator) -> _ = pos; +cpp2_make_forward_iterator: (pos: Iter) -> _ = pos; +cpp2_make_forward_iterator: (pos: std::reverse_iterator) -> _ = pos.base(); +cpp2_make_reverse_iterator: (pos: Iter) -> _ = std::make_reverse_iterator(pos); +cpp2_make_reverse_iterator: (pos: std::reverse_iterator) -> _ = pos; // End function that returns a valid match. @@ -574,7 +574,7 @@ line_start_token_matcher: (cur, inout ctx) -> bool // lookahead_token_matcher: (cur, inout ctx, func) -> bool = { - r := func(make_forward_iterator(cur), make_forward_match_context(ctx), true_end_func()); + r := func(cpp2_make_forward_iterator(cur), make_forward_match_context(ctx), true_end_func()); if !positive { r.matched = !r.matched; } @@ -588,7 +588,7 @@ lookahead_token_matcher: (cur, inout ctx, func) -> bool // lookbehind_token_matcher: (cur, inout ctx, func) -> bool = { - r := func(make_reverse_iterator(cur), make_reverse_match_context(ctx), true_end_func()); + r := func(cpp2_make_reverse_iterator(cur), make_reverse_match_context(ctx), true_end_func()); if !positive { r.matched = !r.matched; } diff --git a/include/cpp2taylor.h b/include/cpp2taylor.h new file mode 100644 index 000000000..34ab94f52 --- /dev/null +++ b/include/cpp2taylor.h @@ -0,0 +1,521 @@ + +#ifndef CPP2TAYLOR_H_CPP2 +#define CPP2TAYLOR_H_CPP2 + + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "cpp2taylor.h2" + +#line 4 "cpp2taylor.h2" +namespace cpp2 { + +template class taylor; + + +#line 257 "cpp2taylor.h2" +} + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "cpp2taylor.h2" +#ifndef CPP2_CPP2TAYLOR_H +#define CPP2_CPP2TAYLOR_H + +#line 4 "cpp2taylor.h2" +namespace cpp2 { + +template class taylor { + public: std::array v {}; + + public: explicit taylor(); + public: taylor(R const& d1); +#line 10 "cpp2taylor.h2" + public: auto operator=(R const& d1) -> taylor& ; + +#line 14 "cpp2taylor.h2" + public: taylor(taylor const& that); +#line 14 "cpp2taylor.h2" + public: auto operator=(taylor const& that) -> taylor& ; +#line 14 "cpp2taylor.h2" + public: taylor(taylor&& that) noexcept; +#line 14 "cpp2taylor.h2" + public: auto operator=(taylor&& that) noexcept -> taylor& ; + + public: taylor(std::initializer_list const& l); +#line 16 "cpp2taylor.h2" + public: auto operator=(std::initializer_list const& l) -> taylor& ; + +#line 23 "cpp2taylor.h2" + // C++ interface + + public: [[nodiscard]] auto operator[](cpp2::impl::in k) const& -> R; + +#line 35 "cpp2taylor.h2" + public: auto set(cpp2::impl::in k, cpp2::impl::in value) & -> void; + +#line 45 "cpp2taylor.h2" + // C++2 interface / AD interface + + public: [[nodiscard]] auto get(cpp2::impl::in i, cpp2::impl::in v0) const& -> R; + +#line 58 "cpp2taylor.h2" + // Overload for reverse AD. + public: auto operator+=(cpp2::impl::in o) & -> auto&&; + +#line 64 "cpp2taylor.h2" + // Overload for reverse AD. + public: auto operator-=(cpp2::impl::in o) & -> auto&&; + +#line 70 "cpp2taylor.h2" + // Overload for simple handling of connected adds. + public: [[nodiscard]] auto operator+(cpp2::impl::in o) const& -> taylor; + +#line 75 "cpp2taylor.h2" + // Overload for simple handling of connected minuses. + public: [[nodiscard]] auto operator-(cpp2::impl::in o) const& -> taylor; + +#line 80 "cpp2taylor.h2" + // Overload for simple handling of prefix +. + public: [[nodiscard]] auto operator+() const& -> taylor; + +#line 85 "cpp2taylor.h2" + // Overload for simple handling of prefix -. + public: [[nodiscard]] auto operator-() const& -> taylor; + +#line 97 "cpp2taylor.h2" + public: [[nodiscard]] auto add(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 108 "cpp2taylor.h2" + public: [[nodiscard]] auto sub(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 119 "cpp2taylor.h2" + public: template [[nodiscard]] auto mul(taylor const& o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 133 "cpp2taylor.h2" + public: [[nodiscard]] auto div(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 151 "cpp2taylor.h2" + public: [[nodiscard]] auto sqrt(cpp2::impl::in v0) const& -> taylor; + +#line 170 "cpp2taylor.h2" + public: [[nodiscard]] auto log(cpp2::impl::in v0) const& -> taylor; + +#line 189 "cpp2taylor.h2" + public: [[nodiscard]] auto exp(cpp2::impl::in v0) const& -> taylor; + +#line 208 "cpp2taylor.h2" + public: static auto comp_sin_cos(taylor& s, taylor& c, cpp2::impl::in u, cpp2::impl::in u0) -> void; + +#line 225 "cpp2taylor.h2" + public: [[nodiscard]] auto sin(cpp2::impl::in v0) const& -> taylor; + +#line 235 "cpp2taylor.h2" + public: [[nodiscard]] auto cos(cpp2::impl::in v0) const& -> taylor; + +#line 244 "cpp2taylor.h2" +}; + +template [[nodiscard]] auto to_string(taylor const& o) -> std::string; + +#line 257 "cpp2taylor.h2" +} // cpp2 namespace + +#endif // CPP2_CPP2TAYLOR_H + + +//=== Cpp2 function definitions ================================================= + +#line 1 "cpp2taylor.h2" + +#line 4 "cpp2taylor.h2" +namespace cpp2 { + +#line 9 "cpp2taylor.h2" + template taylor::taylor(){} +#line 10 "cpp2taylor.h2" + template taylor::taylor(R const& d1) + : v{ }{ + +#line 12 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS_LITERAL(v, 0) = d1; + } +#line 10 "cpp2taylor.h2" + template auto taylor::operator=(R const& d1) -> taylor& { + v = {}; + +#line 12 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS_LITERAL(v, 0) = d1; + return *this; +#line 13 "cpp2taylor.h2" + } +#line 14 "cpp2taylor.h2" + template taylor::taylor(taylor const& that) + : v{ that.v }{} +#line 14 "cpp2taylor.h2" + template auto taylor::operator=(taylor const& that) -> taylor& { + v = that.v; + return *this; } +#line 14 "cpp2taylor.h2" + template taylor::taylor(taylor&& that) noexcept + : v{ std::move(that).v }{} +#line 14 "cpp2taylor.h2" + template auto taylor::operator=(taylor&& that) noexcept -> taylor& { + v = std::move(that).v; + return *this; } + +#line 16 "cpp2taylor.h2" + template taylor::taylor(std::initializer_list const& l){ +{ +auto i{1}; + +#line 18 "cpp2taylor.h2" + for ( auto const& cur : l ) { + set(i, cur); + } +} +#line 21 "cpp2taylor.h2" + } +#line 16 "cpp2taylor.h2" + template auto taylor::operator=(std::initializer_list const& l) -> taylor& { + v = {}; +{ +auto i{1}; + +#line 18 "cpp2taylor.h2" + for ( auto const& cur : l ) { + set(i, cur); + } +} + return *this; +#line 21 "cpp2taylor.h2" + } + +#line 25 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::operator[](cpp2::impl::in k) const& -> R{ + if (cpp2::cpp2_default.is_active() && !([_0 = 1, _1 = k, _2 = dim]{ return cpp2::impl::cmp_less_eq(_0,_1) && cpp2::impl::cmp_less_eq(_1,_2); }()) ) { cpp2::cpp2_default.report_violation(""); } + R r {CPP2_ASSERT_IN_BOUNDS(v, k - 1)}; +{ +auto i{2}; + +#line 29 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(i,k); i += 1 ) { + r *= i; + } +} +#line 32 "cpp2taylor.h2" + return r; + } + +#line 35 "cpp2taylor.h2" + template auto taylor::set(cpp2::impl::in k, cpp2::impl::in value) & -> void{ + if (cpp2::cpp2_default.is_active() && !([_0 = 1, _1 = k, _2 = dim]{ return cpp2::impl::cmp_less_eq(_0,_1) && cpp2::impl::cmp_less_eq(_1,_2); }()) ) { cpp2::cpp2_default.report_violation(""); } + CPP2_ASSERT_IN_BOUNDS(v, k - 1) = value; +{ +auto i{2}; + +#line 40 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(i,k); i += 1 ) { + CPP2_ASSERT_IN_BOUNDS(v, k - 1) /= CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(CPP2_ASSERT_IN_BOUNDS(v, k - 1)),i); + } +} +#line 43 "cpp2taylor.h2" + } + +#line 47 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::get(cpp2::impl::in i, cpp2::impl::in v0) const& -> R{ + if (i == 0) { + return v0; + } + else {if (cpp2::impl::cmp_greater(i,dim)) { + return 0.0; + }} + + return CPP2_ASSERT_IN_BOUNDS(v, i - 1); + } + +#line 59 "cpp2taylor.h2" + template auto taylor::operator+=(cpp2::impl::in o) & -> auto&&{ + (*this) = (*this) + o; + return (*this); + } + +#line 65 "cpp2taylor.h2" + template auto taylor::operator-=(cpp2::impl::in o) & -> auto&&{ + (*this) = (*this) - o; + return (*this); + } + +#line 71 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::operator+(cpp2::impl::in o) const& -> taylor{ + return add(o, 0.0, 0.0); // Primal values are not required. + } + +#line 76 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::operator-(cpp2::impl::in o) const& -> taylor{ + return sub(o, 0.0, 0.0); // Primal values are not required. + } + +#line 81 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::operator+() const& -> taylor{ + return (*this); + } + +#line 86 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::operator-() const& -> taylor{ + taylor r {}; +{ +auto k{1}; + +#line 90 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) = -CPP2_ASSERT_IN_BOUNDS(v, k - 1); + } +} + +#line 94 "cpp2taylor.h2" + return r; + } + +#line 97 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::add(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor{ + taylor r {}; +{ +auto k{1}; + +#line 101 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) = get(k, v0) + CPP2_UFCS(get)(o, k, o0); + } +} + +#line 105 "cpp2taylor.h2" + return r; + } + +#line 108 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::sub(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor{ + taylor r {}; +{ +auto k{1}; + +#line 112 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) = get(k, v0) - CPP2_UFCS(get)(o, k, o0); + } +} + +#line 116 "cpp2taylor.h2" + return r; + } + +#line 119 "cpp2taylor.h2" + template template [[nodiscard]] auto taylor::mul(taylor const& o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor{ + int constexpr dim_r{ std::max(dim, dim_o) }; + taylor r {}; +{ +auto k{1}; + +#line 124 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim_r); k += 1 ) { +{ +auto j{0}; + +#line 126 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(j,k); j += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) += get(j, v0) * o.get(k - j, o0); + } +} +#line 129 "cpp2taylor.h2" + } +} +#line 130 "cpp2taylor.h2" + return r; + } + +#line 133 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::div(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor{ + taylor r {}; + R r0 {v0 / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(v0),o0)}; + + R factor {1.0 / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(1.0),o0)}; +{ +auto k{1}; + +#line 140 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) = get(k, v0); +{ +auto j{0}; + +#line 143 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less(j,k); j += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) -= CPP2_UFCS(get)(r, j, r0) * o.get(k - j, o0); + } +} +#line 146 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) *= factor; + } +} +#line 148 "cpp2taylor.h2" + return r; + } + +#line 151 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::sqrt(cpp2::impl::in v0) const& -> taylor{ + taylor r {}; + R r0 {std::sqrt(v0)}; + + R factor {0.5 / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(0.5),r0)}; +{ +auto k{1}; + +#line 158 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) = get(k, v0); +{ +auto j{1}; + +#line 161 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less(j,k); j += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) -= r.get(j, r0) * r.get(k - j, r0); + } +} +#line 164 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) *= factor; + } +} + +#line 167 "cpp2taylor.h2" + return r; + } + +#line 170 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::log(cpp2::impl::in v0) const& -> taylor{ + taylor r {}; + R r0 {std::log(v0)}; + + R factor {1.0 / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(1.0),v0)}; +{ +auto k{1}; + +#line 177 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) = k * get(k, v0); +{ +auto j{1}; + +#line 180 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less(j,k); j += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) -= j * get(k - j, v0) * r.get(j, r0); + } +} +#line 183 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) *= factor / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(factor),k); + } +} + +#line 186 "cpp2taylor.h2" + return r; + } + +#line 189 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::exp(cpp2::impl::in v0) const& -> taylor{ + taylor r {}; + R r0 {std::exp(v0)}; + + R factor {1.0 / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(1.0),v0)}; +{ +auto k{1}; + +#line 196 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { +{ +auto j{1}; + +#line 198 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(j,k); j += 1 ) { + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) += j * r.get(k - j, r0) * get(j, v0); + } +} +#line 201 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) /= CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(CPP2_ASSERT_IN_BOUNDS(r.v, k - 1)),k); + } +} + +#line 204 "cpp2taylor.h2" + return r; + } + +#line 208 "cpp2taylor.h2" + template auto taylor::comp_sin_cos(taylor& s, taylor& c, cpp2::impl::in u, cpp2::impl::in u0) -> void{ + R s0 {std::sin(u0)}; + R c0 {std::cos(u0)}; +{ +auto k{1}; + +#line 213 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { +{ +auto j{1}; + +#line 215 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(j,k); j += 1 ) { + CPP2_ASSERT_IN_BOUNDS(s.v, k - 1) += j * u.get(j, u0) * c.get(k - j, c0); + CPP2_ASSERT_IN_BOUNDS(c.v, k - 1) -= j * u.get(j, u0) * s.get(k - j, s0); + } +} +#line 219 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(s.v, k - 1) /= CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(CPP2_ASSERT_IN_BOUNDS(s.v, k - 1)),k); + CPP2_ASSERT_IN_BOUNDS(c.v, k - 1) /= CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(CPP2_ASSERT_IN_BOUNDS(c.v, k - 1)),k); + } +} +#line 222 "cpp2taylor.h2" + } + +#line 225 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::sin(cpp2::impl::in v0) const& -> taylor{ + taylor t {}; + taylor r {}; + + comp_sin_cos(r, t, (*this), v0); + static_cast(cpp2::move(t)); + + return r; + } + +#line 235 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::cos(cpp2::impl::in v0) const& -> taylor{ + taylor t {}; + taylor r {}; + + comp_sin_cos(t, r, (*this), v0); + static_cast(cpp2::move(t)); + + return r; + } + +#line 246 "cpp2taylor.h2" +template [[nodiscard]] auto to_string(taylor const& o) -> std::string{ + std::string r {"("}; +{ +auto i{1}; + +#line 249 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(i,order); i += 1 ) { + r += " " + cpp2::to_string(CPP2_ASSERT_IN_BOUNDS(o, i)) + ""; + } +} +#line 252 "cpp2taylor.h2" + r += " )"; + + return r; +} + +} + +#endif diff --git a/include/cpp2taylor.h2 b/include/cpp2taylor.h2 new file mode 100644 index 000000000..cf7f79efe --- /dev/null +++ b/include/cpp2taylor.h2 @@ -0,0 +1,259 @@ +#ifndef CPP2_CPP2TAYLOR_H +#define CPP2_CPP2TAYLOR_H + +cpp2: namespace = { + +taylor: type = { + public v : std::array = (); + + operator=:(out this) = {} + operator=:(out this, d1: R) = { + v = (); + v[0] = d1; + } + operator=:(out this, that) = {} + + operator=:(out this, l: std::initializer_list) = { + (copy i := 1) + for l do (cur) { + set(i, cur); + } + } + + // C++ interface + + operator[]: (this, k: int) -> R = { + assert(1 <= k <= dim); + r: R = v[k - 1]; + (copy i := 2) + while i <= k next i += 1 { + r *= i; + } + return r; + } + + set: (inout this, k: int, value: R) = { + assert(1 <= k <= dim); + v[k - 1] = value; + + (copy i := 2) + while i <= k next i += 1 { + v[k - 1] /= i; + } + } + + // C++2 interface / AD interface + + get: (this, i: int, v0: R) -> R = { + if i == 0 { + return v0; + } + else if i > dim { + return 0.0; + } + + return v[i - 1]; + } + + // Overload for reverse AD. + operator+=: (inout this, o: taylor) -> forward_ref _ = { + this = this + o; + return this; + } + + // Overload for reverse AD. + operator-=: (inout this, o: taylor) -> forward_ref _ = { + this = this - o; + return this; + } + + // Overload for simple handling of connected adds. + operator+: (this, o: taylor) -> taylor = { + return add(o, 0.0, 0.0); // Primal values are not required. + } + + // Overload for simple handling of connected minuses. + operator-: (this, o: taylor) -> taylor = { + return sub(o, 0.0, 0.0); // Primal values are not required. + } + + // Overload for simple handling of prefix +. + operator+: (this) -> taylor = { + return this; + } + + // Overload for simple handling of prefix -. + operator-: (this) -> taylor = { + r: taylor = (); + + (copy k:= 1) + while k <= dim next k += 1 { + r.v[k - 1] = -v[k - 1]; + } + + return r; + } + + add: (this, o: taylor, v0: R, o0: R) -> taylor = { + r: taylor = (); + + (copy k:= 1) + while k <= dim next k += 1 { + r.v[k - 1] = get(k, v0) + o.get(k, o0); + } + + return r; + } + + sub: (this, o: taylor, v0: R, o0: R) -> taylor = { + r: taylor = (); + + (copy k:= 1) + while k <= dim next k += 1 { + r.v[k - 1] = get(k, v0) - o.get(k, o0); + } + + return r; + } + + mul: (this, in_ref o: taylor, v0: R, o0: R) -> taylor = { + dim_r : int == std::max(dim, dim_o); + r: taylor = (); + + (copy k:= 1) + while k <= dim_r next k += 1 { + (copy j := 0) + while j <= k next j += 1 { + r..v[k - 1] += get(j, v0) * o..get(k - j, o0); + } + } + return r; + } + + div: (this, o: taylor, v0: R, o0: R) -> taylor = { + r: taylor = (); + r0: R = v0 / o0; + + factor : R = 1.0 / o0; + + (copy k:= 1) + while k <= dim next k += 1 { + r..v[k - 1] = get(k, v0); + (copy j := 0) + while j < k next j += 1 { + r..v[k - 1] -= r.get(j, r0) * o..get(k - j, o0); + } + r..v[k - 1] *= factor; + } + return r; + } + + sqrt: (this, v0: R) -> taylor = { + r: taylor = (); + r0: R = std::sqrt(v0); + + factor : R = 0.5 / r0; + + (copy k:= 1) + while k <= dim next k += 1 { + r..v[k - 1] = get(k, v0); + (copy j := 1) + while j < k next j += 1 { + r..v[k - 1] -= r..get(j, r0) * r..get(k - j, r0); + } + r..v[k - 1] *= factor; + } + + return r; + } + + log: (this, v0: R) -> taylor = { + r: taylor = (); + r0: R = std::log(v0); + + factor : R = 1.0 / v0; + + (copy k:= 1) + while k <= dim next k += 1 { + r..v[k - 1] =k * get(k, v0); + (copy j := 1) + while j < k next j += 1 { + r..v[k - 1] -= j * get(k - j, v0) * r..get(j, r0); + } + r..v[k - 1] *= factor / k; + } + + return r; + } + + exp: (this, v0: R) -> taylor = { + r: taylor = (); + r0: R = std::exp(v0); + + factor : R = 1.0 / v0; + + (copy k:= 1) + while k <= dim next k += 1 { + (copy j := 1) + while j <= k next j += 1 { + r..v[k - 1] += j * r..get(k - j, r0) * get(j, v0); + } + r..v[k - 1] /= k; + } + + return r; + } + + + comp_sin_cos: (inout s: taylor, inout c: taylor, u: taylor, u0: R) = { + s0: R = std::sin(u0); + c0: R = std::cos(u0); + + (copy k:= 1) + while k <= dim next k += 1 { + (copy j := 1) + while j <= k next j += 1 { + s..v[k - 1] += j * u..get(j, u0) * c..get(k - j, c0); + c..v[k - 1] -= j * u..get(j, u0) * s..get(k - j, s0); + } + s..v[k - 1] /= k; + c..v[k - 1] /= k; + } + } + + + sin: (this, v0: R) -> taylor = { + t: taylor = (); + r: taylor = (); + + comp_sin_cos(r, t, this, v0); + _ = t; + + return r; + } + + cos: (this, v0: R) -> taylor = { + t: taylor = (); + r: taylor = (); + + comp_sin_cos(t, r, this, v0); + _ = t; + + return r; + } +} + +to_string: (o: taylor) -> std::string = { + r : std::string = "("; + (copy i := 1) + while i <= order next i += 1 { + r += " (o[i])$"; + } + r += " )"; + + return r; +} + +} // cpp2 namespace + +#endif // CPP2_CPP2TAYLOR_H \ No newline at end of file diff --git a/regression-tests/mixed-autodiff-taylor.cpp2 b/regression-tests/mixed-autodiff-taylor.cpp2 new file mode 100644 index 000000000..17aa3fccb --- /dev/null +++ b/regression-tests/mixed-autodiff-taylor.cpp2 @@ -0,0 +1,87 @@ +#include + +order : int == 6; +taylor: type == cpp2::taylor; + +test_add: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y = x.add(x, x0, x0); + y0 = x0 + x0; +} + +test_sub: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = 0.0; + y = taylor(); + + y = y.sub(x, y0, x0); + y0 = y0 - x0; +} + +test_mul: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = x0; + y = x; + + (copy i:=0) + while i < 6 next i += 1 { + y = y..mul(x, y0, x0); + y0 *= x0; + } +} + +test_div: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = 1.0; + y = taylor(); + + y = y.div(x, y0, x0); + y0 /= x0; +} + +test_sqrt: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = sqrt(x0); + y = x.sqrt(x0); +} + +test_log: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = log(x0); + y = x.log(x0); +} + +test_exp: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = exp(x0); + y = x.exp(x0); +} + +test_sin: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = sin(x0); + y = x.sin(x0); +} + +test_cos: (x0: double, x: taylor) -> (y0: double, y: taylor) = { + y0 = cos(x0); + y = x.cos(x0); +} + +write_output: (func: std::string, x: double, x_d: taylor, ret) = { + _ = x; + _ = x_d; + std::cout << "(func)$ = (ret.y0)$" << std::endl; + (copy i:=1) + while i <= order next i += 1 { + std::cout << "(func)$ diff order (i)$ = (ret.y[i])$" << std::endl; + } +} + +main: () = { + + x: double = 2.0; + x_d: taylor = (1.0); + + write_output("x + x", x, x_d, test_add(x, x_d)); + write_output("0 - x", x, x_d, test_sub(x, x_d)); + write_output("x^7", x, x_d, test_mul(x, x_d)); + write_output("1/x", x, x_d, test_div(x, x_d)); + write_output("sqrt(x)", x, x_d, test_sqrt(x, x_d)); + write_output("log(x)", x, x_d, test_log(x, x_d)); + write_output("exp(x)", x, x_d, test_exp(x, x_d)); + write_output("sin(x)", x, x_d, test_sin(x, x_d)); + write_output("cos(x)", x, x_d, test_cos(x, x_d)); +} diff --git a/regression-tests/pure2-autodiff-higher-order.cpp2 b/regression-tests/pure2-autodiff-higher-order.cpp2 new file mode 100644 index 000000000..cfa25c6bc --- /dev/null +++ b/regression-tests/pure2-autodiff-higher-order.cpp2 @@ -0,0 +1,245 @@ +ad_order : int == 6; +ad_type : type == cpp2::taylor; + +ad_name: namespace = { + +func_outer: (x: double, y: double) -> (ret: double) = { + ret = x + y; +} + +type_outer: type = { + public a: double = 0.0; + + add: (this, b: double) -> double = { + return a + b; + } +} + +ad_test: @autodiff<"order=6"> @print type = { + + add_1: (x: double, y: double) -> (r: double) = { + r = x + y; + } + + add_2: (x: double, y: double) -> (r: double) = { + r = x + y + x; + } + + sub_1: (x: double, y: double) -> (r: double) = { + r = x - y; + } + + sub_2: (x: double, y: double) -> (r: double) = { + r = x - y - x; + } + + add_sub_2: (x: double, y: double) -> (r: double) = { + r = x + y - x; + } + + mul_1: (x: double, y: double) -> (r: double) = { + r = x * y; + } + + mul_2: (x: double, y: double) -> (r: double) = { + r = x * y * x; + } + + div_1: (x: double, y: double) -> (r: double) = { + r = x / y; + } + + div_2: (x: double, y: double) -> (r: double) = { + r = x / y / y; + } + + mul_div_2: (x: double, y: double) -> (r: double) = { + r = x * y / x; + } + + mul_add: (x: double, y: double) -> (r: double) = { + r = x * (x + y); + } + + add_mul: (x: double, y: double) -> (r: double) = { + r = x + x * y; + } + + prefix_add: (x: double, y: double) -> (r: double) = { + r = +x + y; + } + + prefix_sub: (x: double, y: double) -> (r: double) = { + r = -x + y; + } + + func: (x: double, y: double) -> (ret: double) = { + ret = x + y; + } + + func_call: (x: double, y: double) -> (r: double) = { + r = x * func(x, y); + } + + func_outer_call: (x: double, y: double) -> (r: double) = { + r = x * func_outer(x, y); + } + + sin_call: (x: double, y: double) -> (r: double) = { + r = sin(x - y); + } + + if_branch: (x: double, y: double) -> (r: double) = { + r = x; + + if x < 0.0 { + r = y; + } + } + + if_else_branch: (x: double, y: double) -> (r: double) = { + if x < 0.0 { + r = y; + } + else { + r = x; + } + } + + direct_return: (x: double, y: double) -> double = { + return x + y; + } + + intermediate_var: (x: double, y: double) -> (r: double) = { + t: double = x + y; + + r = t; + } + + intermediate_passive_var: (x: double, y: double) -> (r: double) = { + i: int = (); // TODO: Handle as passive when type information on call side is available. + r = x + y; + i = 2; + + _ = i; + } + + intermediate_untyped: (x: double, y: double) -> (r: double) = { + t := 0.0; + t = x + y; + + r = t; + } + + intermediate_default_init: (x: double, y: double) -> (r: double) = { + t: double = (); + t = x + y; + + r = t; + } + + intermediate_no_init: (x: double, y: double) -> (r: double) = { + t: double; + t = x + y; + + r = t; + } + + while_loop: (x: double, y: double) -> (r: double) = { + i: int = 0; + + r = x; + while i < 2 next (i += 1) { + r = r + y ; + } + } + + do_while_loop: (x: double, y: double) -> (r: double) = { + i: int = 0; + + r = x; + do { + r = r + y ; + } + next (i += 1) + while i < 2; + } + + for_loop: (x: double, y: double) -> (r: double) = { + v: std::vector = (); + + v.push_back(x); + v.push_back(y); + + r = 0.0; + for v + do (t) + { + r = r + t; + } + } + + type_outer_use: (x: double, y: double) -> (r: double) = { + t : type_outer = (); + t.a = x; + + r = t.a + y; + } + + type_outer_call: (x: double, y: double) -> (r: double) = { + t : type_outer = (); + t.a = x; + + r = t.add(y); + } +} +} + +write_output: (func: std::string, x: double, x_d: ad_type, y: double, y_d: ad_type, ret) = { + std::cout << "diff((func)$) at (x = (x)$, x_d = (x_d)$, y = (y)$, y_d = (y_d)$):" << std::endl; + std::cout << " r = (ret.r)$" << std::endl; + (copy i:=1) + while i <= ad_order next i += 1 { + std::cout << " d(i)$ = (ret.r_d[i])$" << std::endl; + } +} + +main: () = { + + + x: double = 2.0; + x_d: ad_type = 1.0; + y: double = 3.0; + y_d: ad_type = 2.0; + + write_output("x + y", x, x_d, y, y_d, ad_name::ad_test::add_1_d(x, x_d, y, y_d)); + write_output("x + y + x", x, x_d, y, y_d, ad_name::ad_test::add_2_d(x, x_d, y, y_d)); + write_output("x - y", x, x_d, y, y_d, ad_name::ad_test::sub_1_d(x, x_d, y, y_d)); + write_output("x - y - x", x, x_d, y, y_d, ad_name::ad_test::sub_2_d(x, x_d, y, y_d)); + write_output("x + y - x", x, x_d, y, y_d, ad_name::ad_test::add_sub_2_d(x, x_d, y, y_d)); + write_output("x * y", x, x_d, y, y_d, ad_name::ad_test::mul_1_d(x, x_d, y, y_d)); + write_output("x * y * x", x, x_d, y, y_d, ad_name::ad_test::mul_2_d(x, x_d, y, y_d)); + write_output("x / y", x, x_d, y, y_d, ad_name::ad_test::div_1_d(x, x_d, y, y_d)); + write_output("x / y / y", x, x_d, y, y_d, ad_name::ad_test::div_2_d(x, x_d, y, y_d)); + write_output("x * y / x", x, x_d, y, y_d, ad_name::ad_test::mul_div_2_d(x, x_d, y, y_d)); + write_output("x * (x + y)", x, x_d, y, y_d, ad_name::ad_test::mul_add_d(x, x_d, y, y_d)); + write_output("x + x * y", x, x_d, y, y_d, ad_name::ad_test::add_mul_d(x, x_d, y, y_d)); + write_output("+x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_add_d(x, x_d, y, y_d)); + write_output("-x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_sub_d(x, x_d, y, y_d)); + write_output("x * func(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_call_d(x, x_d, y, y_d)); + write_output("x * func_outer(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_outer_call_d(x, x_d, y, y_d)); + write_output("sin(x - y)", x, x_d, y, y_d, ad_name::ad_test::sin_call_d(x, x_d, y, y_d)); + write_output("if branch", x, x_d, y, y_d, ad_name::ad_test::if_branch_d(x, x_d, y, y_d)); + write_output("if else branch", x, x_d, y, y_d, ad_name::ad_test::if_else_branch_d(x, x_d, y, y_d)); + write_output("direct return", x, x_d, y, y_d, ad_name::ad_test::direct_return_d(x, x_d, y, y_d)); + write_output("intermediate var", x, x_d, y, y_d, ad_name::ad_test::intermediate_var_d(x, x_d, y, y_d)); + write_output("intermediate passive var", x, x_d, y, y_d, ad_name::ad_test::intermediate_passive_var_d(x, x_d, y, y_d)); + write_output("intermediate untyped", x, x_d, y, y_d, ad_name::ad_test::intermediate_untyped_d(x, x_d, y, y_d)); + write_output("intermediate default init", x, x_d, y, y_d, ad_name::ad_test::intermediate_default_init_d(x, x_d, y, y_d)); + write_output("intermediate no init", x, x_d, y, y_d, ad_name::ad_test::intermediate_no_init_d(x, x_d, y, y_d)); + write_output("while loop", x, x_d, y, y_d, ad_name::ad_test::while_loop_d(x, x_d, y, y_d)); + write_output("do while loop", x, x_d, y, y_d, ad_name::ad_test::do_while_loop_d(x, x_d, y, y_d)); + write_output("for loop", x, x_d, y, y_d, ad_name::ad_test::for_loop_d(x, x_d, y, y_d)); + write_output("tye_outer.a + y", x, x_d, y, y_d, ad_name::ad_test::type_outer_use_d(x, x_d, y, y_d)); + write_output("type_outer.add(y)", x, x_d, y, y_d, ad_name::ad_test::type_outer_call_d(x, x_d, y, y_d)); +} diff --git a/regression-tests/pure2-autodiff.cpp2 b/regression-tests/pure2-autodiff.cpp2 new file mode 100644 index 000000000..7438068d5 --- /dev/null +++ b/regression-tests/pure2-autodiff.cpp2 @@ -0,0 +1,361 @@ +ad_name: namespace = { + +func_outer: (x: double, y: double) -> (ret: double) = { + ret = x + y; +} + +type_outer: type = { + public a: double = 0.0; + + add: (this, b: double) -> double = { + return a + b; + } +} + +ad_test: @autodiff @print type = { + + add_1: (x: double, y: double) -> (r: double) = { + r = x + y; + } + + add_2: (x: double, y: double) -> (r: double) = { + r = x + y + x; + } + + sub_1: (x: double, y: double) -> (r: double) = { + r = x - y; + } + + sub_2: (x: double, y: double) -> (r: double) = { + r = x - y - x; + } + + add_sub_2: (x: double, y: double) -> (r: double) = { + r = x + y - x; + } + + mul_1: (x: double, y: double) -> (r: double) = { + r = x * y; + } + + mul_2: (x: double, y: double) -> (r: double) = { + r = x * y * x; + } + + div_1: (x: double, y: double) -> (r: double) = { + r = x / y; + } + + div_2: (x: double, y: double) -> (r: double) = { + r = x / y / y; + } + + mul_div_2: (x: double, y: double) -> (r: double) = { + r = x * y / x; + } + + mul_add: (x: double, y: double) -> (r: double) = { + r = x * (x + y); + } + + add_mul: (x: double, y: double) -> (r: double) = { + r = x + x * y; + } + + prefix_add: (x: double, y: double) -> (r: double) = { + r = +x + y; + } + + prefix_sub: (x: double, y: double) -> (r: double) = { + r = -x + y; + } + + func: (x: double, y: double) -> (ret: double) = { + ret = x + y; + } + + func_call: (x: double, y: double) -> (r: double) = { + r = x * func(x, y); + } + + func_outer_call: (x: double, y: double) -> (r: double) = { + r = x * func_outer(x, y); + } + + sin_call: (x: double, y: double) -> (r: double) = { + r = sin(x - y); + } + + if_branch: (x: double, y: double) -> (r: double) = { + r = x; + + if x < 0.0 { + r = y; + } + } + + if_else_branch: (x: double, y: double) -> (r: double) = { + if x < 0.0 { + r = y; + } + else { + r = x; + } + } + + direct_return: (x: double, y: double) -> double = { + return x + y; + } + + intermediate_var: (x: double, y: double) -> (r: double) = { + t: double = x + y; + + r = t; + } + + intermediate_passive_var: (x: double, y: double) -> (r: double) = { + i: int = (); + r = x + y; + i = 2; + + _ = i; + } + + intermediate_untyped: (x: double, y: double) -> (r: double) = { + t := 0.0; + t = x + y; + + r = t; + } + + intermediate_default_init: (x: double, y: double) -> (r: double) = { + t: double = (); + t = x + y; + + r = t; + } + + intermediate_no_init: (x: double, y: double) -> (r: double) = { + t: double; + t = x + y; + + r = t; + } + + while_loop: (x: double, y: double) -> (r: double) = { + r = x; + + (copy i: int = 0, copy t: double = 0.0) + while i < 2 next (i += 1) { + t = y; + r = r + t; + } + } + + do_while_loop: (x: double, y: double) -> (r: double) = { + r = x; + + (copy i: = 0) + do { + r = r + y ; + } + next (i += 1) + while i < 2; + } + + for_loop: (x: double, y: double) -> (r: double) = { + v: std::vector = (); + + v.push_back(x); + v.push_back(y); + + r = 0.0; + for v + do (t) + { + r = r + t; + } + } + + type_outer_use: (x: double, y: double) -> (r: double) = { + t : type_outer = (); + t.a = x; + + r = t.a + y; + } + + type_outer_call: (x: double, y: double) -> (r: double) = { + t : type_outer = (); + t.a = x; + + r = t.add(y); + } +} + +ad_test_reverse: @autodiff<"reverse"> @print type = { + + add_1: (x: double, y: double) -> (r: double) = { + r = x + y; + } + + add_2: (x: double, y: double) -> (r: double) = { + r = x + y + x; + } + + sub_1: (x: double, y: double) -> (r: double) = { + r = x - y; + } + + sub_2: (x: double, y: double) -> (r: double) = { + r = x - y - x; + } + + add_sub_2: (x: double, y: double) -> (r: double) = { + r = x + y - x; + } + + mul_1: (x: double, y: double) -> (r: double) = { + r = x * y; + } + + mul_2: (x: double, y: double) -> (r: double) = { + r = x * y * x; + } + + div_1: (x: double, y: double) -> (r: double) = { + r = x / y; + } + + div_2: (x: double, y: double) -> (r: double) = { + r = x / y / y; + } + + mul_div_2: (x: double, y: double) -> (r: double) = { + r = x * y / x; + } + + mul_add: (x: double, y: double) -> (r: double) = { + r = x * (x + y); + } + + add_mul: (x: double, y: double) -> (r: double) = { + r = x + x * y; + } + + sin_call: (x: double, y: double) -> (r: double) = { + r = sin(x - y); + } + + func: (x: double, y: double) -> (ret: double) = { + ret = x + y; + } + + func_call: (x: double, y: double) -> (r: double) = { + r = x * func(x, y); + } + + func_outer_call: (x: double, y: double) -> (r: double) = { + r = x * func_outer(x, y); + } +} +} + +ad_test_twice: @autodiff @autodiff<"suffix=_d2"> @print type = { + mul_1: (x: double) -> (r: double) = { + r = x * x; + } +} + +write_output: (func: std::string, x: double, x_d: double, y: double, y_d: double, ret) = { + std::cout << "diff((func)$) at (x = (x)$, x_d = (x_d)$, y = (y)$, y_d = (y_d)$) = (r = (ret.r)$, r_d = (ret.r_d)$)" << std::endl; +} + +write_output_reverse: (func: std::string, x: double, inout x_b: double, y: double, inout y_b: double, inout r_b: double, ret) = { + r_b = 1.0; + std::cout << "diff((func)$) at (x = (x)$, y = (y)$, r_b = (r_b)$) = (r = (ret)$, x_b = (x_b)$, y_b = (y_b)$)" << std::endl; + x_b = 0.0; + y_b = 0.0; +} + +ad_test_2: @autodiff<"order=2"> @print type = { + f: (x: double) -> (y: double) = { + if x < -3 + { + y = x * x; + } + else if x < 3 + { + y = x + sin(x) + 10; + } + else + { + y = sin(x) * x*x; + } + } +} + +main: () = { + + x: double = 2.0; + x_d: double = 1.0; + y: double = 3.0; + y_d: double = 2.0; + + write_output("x + y", x, x_d, y, y_d, ad_name::ad_test::add_1_d(x, x_d, y, y_d)); + write_output("x + y + x", x, x_d, y, y_d, ad_name::ad_test::add_2_d(x, x_d, y, y_d)); + write_output("x - y", x, x_d, y, y_d, ad_name::ad_test::sub_1_d(x, x_d, y, y_d)); + write_output("x - y - x", x, x_d, y, y_d, ad_name::ad_test::sub_2_d(x, x_d, y, y_d)); + write_output("x + y - x", x, x_d, y, y_d, ad_name::ad_test::add_sub_2_d(x, x_d, y, y_d)); + write_output("x * y", x, x_d, y, y_d, ad_name::ad_test::mul_1_d(x, x_d, y, y_d)); + write_output("x * y * x", x, x_d, y, y_d, ad_name::ad_test::mul_2_d(x, x_d, y, y_d)); + write_output("x / y", x, x_d, y, y_d, ad_name::ad_test::div_1_d(x, x_d, y, y_d)); + write_output("x / y / y", x, x_d, y, y_d, ad_name::ad_test::div_2_d(x, x_d, y, y_d)); + write_output("x * y / x", x, x_d, y, y_d, ad_name::ad_test::mul_div_2_d(x, x_d, y, y_d)); + write_output("x * (x + y)", x, x_d, y, y_d, ad_name::ad_test::mul_add_d(x, x_d, y, y_d)); + write_output("x + x * y", x, x_d, y, y_d, ad_name::ad_test::add_mul_d(x, x_d, y, y_d)); + write_output("+x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_add_d(x, x_d, y, y_d)); + write_output("-x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_sub_d(x, x_d, y, y_d)); + write_output("x * func(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_call_d(x, x_d, y, y_d)); + write_output("x * func_outer(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_outer_call_d(x, x_d, y, y_d)); + write_output("sin(x - y)", x, x_d, y, y_d, ad_name::ad_test::sin_call_d(x, x_d, y, y_d)); + write_output("if branch", x, x_d, y, y_d, ad_name::ad_test::if_branch_d(x, x_d, y, y_d)); + write_output("if else branch", x, x_d, y, y_d, ad_name::ad_test::if_else_branch_d(x, x_d, y, y_d)); + write_output("direct return", x, x_d, y, y_d, ad_name::ad_test::direct_return_d(x, x_d, y, y_d)); + write_output("intermediate var", x, x_d, y, y_d, ad_name::ad_test::intermediate_var_d(x, x_d, y, y_d)); + write_output("intermediate passive var", x, x_d, y, y_d, ad_name::ad_test::intermediate_passive_var_d(x, x_d, y, y_d)); + write_output("intermediate untyped", x, x_d, y, y_d, ad_name::ad_test::intermediate_untyped_d(x, x_d, y, y_d)); + write_output("intermediate default init", x, x_d, y, y_d, ad_name::ad_test::intermediate_default_init_d(x, x_d, y, y_d)); + write_output("intermediate no init", x, x_d, y, y_d, ad_name::ad_test::intermediate_no_init_d(x, x_d, y, y_d)); + write_output("while loop", x, x_d, y, y_d, ad_name::ad_test::while_loop_d(x, x_d, y, y_d)); + write_output("do while loop", x, x_d, y, y_d, ad_name::ad_test::do_while_loop_d(x, x_d, y, y_d)); + write_output("for loop", x, x_d, y, y_d, ad_name::ad_test::for_loop_d(x, x_d, y, y_d)); + write_output("tye_outer.a + y", x, x_d, y, y_d, ad_name::ad_test::type_outer_use_d(x, x_d, y, y_d)); + write_output("type_outer.add(y)", x, x_d, y, y_d, ad_name::ad_test::type_outer_call_d(x, x_d, y, y_d)); + + x_b: double = 0.0; + y_b: double = 0.0; + w_b: double = 1.0; + + write_output_reverse("x + y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x + y + x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x - y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::sub_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x - y - x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::sub_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x + y - x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_sub_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * y * x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x / y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::div_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x / y / y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::div_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * y / x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_div_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * (x + y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_add_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x + x * y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_mul_b(x, x_b, y, y_b, w_b)); + write_output_reverse("sin(x-y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::sin_call_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * func(x-y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::func_call_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * func_outer(x-y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::func_outer_call_b(x, x_b, y, y_b, w_b)); + + _ = x_b; + _ = y_b; + _ = w_b; + + r_twice := ad_test_twice::mul_1_d_d2(x, x_d, x_d, 0.0); + std::cout << "2nd order diff of x*x at (x)$ = (r_twice.r_d_d2)$" << std::endl; +} diff --git a/regression-tests/pure2-regex_20_lookbehind.cpp2 b/regression-tests/pure2-regex_20_lookbehind.cpp2 new file mode 100644 index 000000000..75ad0ade5 --- /dev/null +++ b/regression-tests/pure2-regex_20_lookbehind.cpp2 @@ -0,0 +1,286 @@ +create_result: (resultExpr: std::string, r) -> std::string = { + result: std::string = ""; + + get_next := :(iter) -> _ = { + start := std::distance(resultExpr&$*.cbegin(), iter); + firstDollar := resultExpr&$*.find("$", start); + firstAt := resultExpr&$*.find("@", start); + + end := std::min(firstDollar, firstAt); + if end != std::string::npos { + return resultExpr&$*.cbegin() + end; + } + else { + return resultExpr&$*.cend(); + } + }; + extract_group_and_advance := :(inout iter) -> _ = { + start := iter; + + while std::isdigit(iter*) next iter++ {} + + return std::stoi(std::string(start, iter)); + }; + extract_until := :(inout iter, to: char) -> _ = { + start := iter; + + while (to != iter*) next iter++ {} // TODO: Without bracket: error: postfix unary * (dereference) cannot be immediately followed by a (, identifier, or literal - add whitespace before * here if you meant binary * (multiplication) + + return std::string(start, iter); + }; + + iter := resultExpr.begin(); + + while iter != resultExpr.end() { + next := get_next(iter); + + if next != iter { + result += std::string(iter, next); + } + if next != resultExpr.end() { + if next* == '$' { + next++; + + if next* == '&' { + next++; + result += r.group(0); + } + else if next* == '-' || next* == '+' { + is_start := next* == '-'; + next++; + if next* == '{' { + next++; // Skip { + group := extract_until(next, '}'); + next++; // Skip } + result += r.group(group); + } + else if next* == '[' { + next++; // Skip [ + group := extract_group_and_advance(next); + next++; // Skip ] + + if is_start { + result += std::to_string(r.group_start(group)); + } + else { + result += std::to_string(r.group_end(group)); + } + } + else { + // Return max group + result += r.group(r.group_number() - 1); + } + } + else if std::isdigit(next*) { + group := extract_group_and_advance(next); + result += r.group(group); + } + else { + std::cerr << "Not implemented"; + } + } + else if next* == '@' { + next++; + + if next* == '-' || next* == '+' { + i := 0; + while i < cpp2::unchecked_narrow(r.group_number()) next i++ { + pos := 0; + if next* == '-' { + pos = r.group_start(i); + } + else { + pos = r.group_end(i); + } + result += std::to_string(pos); + } + next++; + } + else { + std::cerr << "Not implemented"; + } + } + else { + std::cerr << "Not implemented."; + } + } + iter = next; + } + + return result; +} + +sanitize: (copy str: std::string) -> std::string = +{ + str = cpp2::string_util::replace_all(str, "\a", "\\a"); + str = cpp2::string_util::replace_all(str, "\f", "\\f"); + str = cpp2::string_util::replace_all(str, "\x1b", "\\e"); + str = cpp2::string_util::replace_all(str, "\n", "\\n"); + str = cpp2::string_util::replace_all(str, "\r", "\\r"); + str = cpp2::string_util::replace_all(str, "\t", "\\t"); + + return str; +} + +test: (regex: M, id: std::string, regex_str: std::string, str: std::string, kind: std::string, resultExpr: std::string, + resultExpected: std::string) = { + + warning: std::string = ""; + if regex.to_string() != regex_str { + warning = "Warning: Parsed regex does not match."; + } + + status: std::string = "OK"; + + r := regex.search(str); + + if "y" == kind || "yM" == kind || "yS" == kind || "yB" == kind { + if !r.matched { + status = "Failure: Regex should apply."; + } + else { + // Have a match check the result + + result := create_result(resultExpr, r); + + if result != resultExpected { + status = "Failure: Result is wrong. (is: (sanitize(result))$)"; + } + } + } + else if "n" == kind { + if r.matched { + status = "Failure: Regex should not apply. Result is '(r.group(0))$'"; + } + } else { + status = "Unknown kind '(kind)$'"; + } + + if !warning.empty() { + warning += " "; + } + std::cout << "(id)$_(kind)$: (status)$ (warning)$regex: (regex_str)$ parsed_regex: (regex.to_string())$ str: (sanitize(str))$ result_expr: (resultExpr)$ expected_results (sanitize(resultExpected))$" << std::endl; +} + + +test_tests_20_lookbehind: @regex type = { + regex_01 := R"((?<=a)b)"; + regex_02 := R"((?<=af?)b)"; + regex_03 := R"((?<=a)b)"; + regex_04 := R"((?<=a(?:fo)?)b)"; + regex_05 := R"((?<=a)b)"; + regex_06 := R"((?<=a(?:foo)?)b)"; + regex_07 := R"((?)foo)"; + regex_50 := R"((?)foo)"; + regex_51 := R"((?<=bar>ABC)foo)"; + regex_52 := R"((?ABC)foo)"; + regex_53 := R"((?<=abcd(?<=(aaaabcd))))"; + regex_54 := R"((?=xy(?<=(aaxy))))"; + regex_55 := R"((?=xy(?<=(aaxyz?))))"; + regex_56 := R"((?<=(?=(aaxy))aa))"; + run: (this) = { + std::cout << "Running tests_20_lookbehind:"<< std::endl; + test(regex_01, "01", R"((?<=a)b)", "ab", "y", R"($&)", "b"); + test(regex_02, "02", R"((?<=af?)b)", "ab", "y", R"($&)", "b"); + test(regex_03, "03", R"((?<=a)b)", "cb", "n", R"(-)", "-"); + test(regex_04, "04", R"((?<=a(?:fo)?)b)", "cb", "n", R"(-)", "-"); + test(regex_05, "05", R"((?<=a)b)", "b", "n", R"(-)", "-"); + test(regex_06, "06", R"((?<=a(?:foo)?)b)", "b", "n", R"(-)", "-"); + test(regex_07, "07", R"((?)foo)", "bar>foo", "y", R"($&)", "foo"); + test(regex_50, "50", R"((?)foo)", "bar>foo", "n", R"(-)", "-"); + test(regex_51, "51", R"((?<=bar>ABC)foo)", "bar>ABCfoo", "y", R"($&)", "foo"); + test(regex_52, "52", R"((?ABC)foo)", "bar>ABCfoo", "n", R"(-)", "-"); + test(regex_53, "53", R"((?<=abcd(?<=(aaaabcd))))", "..aaaabcd..", "y", R"($1)", "aaaabcd"); + test(regex_54, "54", R"((?=xy(?<=(aaxy))))", "..aaxy..", "y", R"($1)", "aaxy"); + test(regex_55, "55", R"((?=xy(?<=(aaxyz?))))", "..aaxy..", "y", R"($1)", "aaxy"); + test(regex_56, "56", R"((?<=(?=(aaxy))aa))", "..aaxy..", "y", R"($1)", "aaxy"); + std::cout << std::endl; + } +} +main: () = { + test_tests_20_lookbehind().run(); +} diff --git a/regression-tests/test-results/clang-12-c++20/mixed-autodiff-taylor.cpp.execution b/regression-tests/test-results/clang-12-c++20/mixed-autodiff-taylor.cpp.execution new file mode 100644 index 000000000..0a486b06f --- /dev/null +++ b/regression-tests/test-results/clang-12-c++20/mixed-autodiff-taylor.cpp.execution @@ -0,0 +1,63 @@ +x + x = 4.000000 +x + x diff order 1 = 2.000000 +x + x diff order 2 = 0.000000 +x + x diff order 3 = 0.000000 +x + x diff order 4 = 0.000000 +x + x diff order 5 = 0.000000 +x + x diff order 6 = 0.000000 +0 - x = -2.000000 +0 - x diff order 1 = -1.000000 +0 - x diff order 2 = 0.000000 +0 - x diff order 3 = 0.000000 +0 - x diff order 4 = 0.000000 +0 - x diff order 5 = 0.000000 +0 - x diff order 6 = 0.000000 +x^7 = 128.000000 +x^7 diff order 1 = 448.000000 +x^7 diff order 2 = 1344.000000 +x^7 diff order 3 = 3360.000000 +x^7 diff order 4 = 6720.000000 +x^7 diff order 5 = 10080.000000 +x^7 diff order 6 = 10080.000000 +1/x = 0.500000 +1/x diff order 1 = -0.250000 +1/x diff order 2 = 0.250000 +1/x diff order 3 = -0.375000 +1/x diff order 4 = 0.750000 +1/x diff order 5 = -1.875000 +1/x diff order 6 = 5.625000 +sqrt(x) = 1.414214 +sqrt(x) diff order 1 = 0.353553 +sqrt(x) diff order 2 = -0.088388 +sqrt(x) diff order 3 = 0.066291 +sqrt(x) diff order 4 = -0.082864 +sqrt(x) diff order 5 = 0.145012 +sqrt(x) diff order 6 = -0.326277 +log(x) = 0.693147 +log(x) diff order 1 = 0.500000 +log(x) diff order 2 = -0.250000 +log(x) diff order 3 = 0.250000 +log(x) diff order 4 = -0.375000 +log(x) diff order 5 = 0.750000 +log(x) diff order 6 = -1.875000 +exp(x) = 7.389056 +exp(x) diff order 1 = 7.389056 +exp(x) diff order 2 = 7.389056 +exp(x) diff order 3 = 7.389056 +exp(x) diff order 4 = 7.389056 +exp(x) diff order 5 = 7.389056 +exp(x) diff order 6 = 7.389056 +sin(x) = 0.909297 +sin(x) diff order 1 = -0.416147 +sin(x) diff order 2 = -0.909297 +sin(x) diff order 3 = 0.416147 +sin(x) diff order 4 = 0.909297 +sin(x) diff order 5 = -0.416147 +sin(x) diff order 6 = -0.909297 +cos(x) = -0.416147 +cos(x) diff order 1 = -0.909297 +cos(x) diff order 2 = 0.416147 +cos(x) diff order 3 = 0.909297 +cos(x) diff order 4 = -0.416147 +cos(x) diff order 5 = -0.909297 +cos(x) diff order 6 = 0.416147 diff --git a/regression-tests/test-results/clang-12-c++20/pure2-autodiff-higher-order.cpp.execution b/regression-tests/test-results/clang-12-c++20/pure2-autodiff-higher-order.cpp.execution new file mode 100644 index 000000000..84a5f58de --- /dev/null +++ b/regression-tests/test-results/clang-12-c++20/pure2-autodiff-higher-order.cpp.execution @@ -0,0 +1,240 @@ +diff(x + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y + x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 7.000000 + d1 = 4.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -1.000000 + d1 = -1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -3.000000 + d1 = -2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 6.000000 + d1 = 7.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y * x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 12.000000 + d1 = 20.000000 + d2 = 22.000000 + d3 = 12.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.666667 + d1 = -0.111111 + d2 = 0.148148 + d3 = -0.296296 + d4 = 0.790123 + d5 = -2.633745 + d6 = 10.534979 +diff(x / y / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.222222 + d1 = -0.185185 + d2 = 0.296296 + d3 = -0.691358 + d4 = 2.106996 + d5 = -7.901235 + d6 = 35.116598 +diff(x * y / x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * (x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 8.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(+x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(-x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 1.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(sin(x - y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -0.841471 + d1 = -0.540302 + d2 = 0.841471 + d3 = 0.540302 + d4 = -0.841471 + d5 = -0.540302 + d6 = 0.841471 +diff(if branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(if else branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(direct return) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate passive var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate untyped) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate default init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate no init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(do while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(for loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(tye_outer.a + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(type_outer.add(y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 diff --git a/regression-tests/test-results/clang-12-c++20/pure2-autodiff.cpp.execution b/regression-tests/test-results/clang-12-c++20/pure2-autodiff.cpp.execution new file mode 100644 index 000000000..863bd6bd5 --- /dev/null +++ b/regression-tests/test-results/clang-12-c++20/pure2-autodiff.cpp.execution @@ -0,0 +1,46 @@ +diff(x + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y + x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 7.000000, r_d = 4.000000) +diff(x - y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -1.000000, r_d = -1.000000) +diff(x - y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -3.000000, r_d = -2.000000) +diff(x + y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 6.000000, r_d = 7.000000) +diff(x * y * x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 12.000000, r_d = 20.000000) +diff(x / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.666667, r_d = -0.111111) +diff(x / y / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.222222, r_d = -0.185185) +diff(x * y / x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * (x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x + x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 8.000000) +diff(+x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(-x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 1.000000, r_d = 1.000000) +diff(x * func(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(sin(x - y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -0.841471, r_d = -0.540302) +diff(if branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(if else branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(direct return) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate passive var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate untyped) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate default init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate no init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(do while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(for loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(tye_outer.a + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(type_outer.add(y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 5.000000, x_b = 1.000000, y_b = 1.000000) +diff(x + y + x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 7.000000, x_b = 2.000000, y_b = 1.000000) +diff(x - y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -1.000000, x_b = 1.000000, y_b = -1.000000) +diff(x - y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -3.000000, x_b = 0.000000, y_b = -1.000000) +diff(x + y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 6.000000, x_b = 3.000000, y_b = 2.000000) +diff(x * y * x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 12.000000, x_b = 12.000000, y_b = 4.000000) +diff(x / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.666667, x_b = 0.333333, y_b = -0.222222) +diff(x / y / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.222222, x_b = 0.111111, y_b = -0.148148) +diff(x * y / x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * (x + y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x + x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 8.000000, x_b = 4.000000, y_b = 2.000000) +diff(sin(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -0.841471, x_b = 0.540302, y_b = -0.540302) +diff(x * func(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x * func_outer(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +2nd order diff of x*x at 2.000000 = 2.000000 diff --git a/regression-tests/test-results/clang-12-c++20/pure2-regex_20_lookbehind.cpp.execution b/regression-tests/test-results/clang-12-c++20/pure2-regex_20_lookbehind.cpp.execution new file mode 100644 index 000000000..cd61d4f56 --- /dev/null +++ b/regression-tests/test-results/clang-12-c++20/pure2-regex_20_lookbehind.cpp.execution @@ -0,0 +1,58 @@ +Running tests_20_lookbehind: +01_y: OK regex: (?<=a)b parsed_regex: (?<=a)b str: ab result_expr: $& expected_results b +02_y: OK regex: (?<=af?)b parsed_regex: (?<=af?)b str: ab result_expr: $& expected_results b +03_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: cb result_expr: - expected_results - +04_n: OK regex: (?<=a(?:fo)?)b parsed_regex: (?<=a(?:fo)?)b str: cb result_expr: - expected_results - +05_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: b result_expr: - expected_results - +06_n: OK regex: (?<=a(?:foo)?)b parsed_regex: (?<=a(?:foo)?)b str: b result_expr: - expected_results - +07_y: OK regex: (?)foo parsed_regex: (?<=bar>)foo str: bar>foo result_expr: $& expected_results foo +50_n: OK regex: (?)foo parsed_regex: (?)foo str: bar>foo result_expr: - expected_results - +51_y: OK regex: (?<=bar>ABC)foo parsed_regex: (?<=bar>ABC)foo str: bar>ABCfoo result_expr: $& expected_results foo +52_n: OK regex: (?ABC)foo parsed_regex: (?ABC)foo str: bar>ABCfoo result_expr: - expected_results - +53_y: OK regex: (?<=abcd(?<=(aaaabcd))) parsed_regex: (?<=abcd(?<=(aaaabcd))) str: ..aaaabcd.. result_expr: $1 expected_results aaaabcd +54_y: OK regex: (?=xy(?<=(aaxy))) parsed_regex: (?=xy(?<=(aaxy))) str: ..aaxy.. result_expr: $1 expected_results aaxy +55_y: OK regex: (?=xy(?<=(aaxyz?))) parsed_regex: (?=xy(?<=(aaxyz?))) str: ..aaxy.. result_expr: $1 expected_results aaxy +56_y: OK regex: (?<=(?=(aaxy))aa) parsed_regex: (?<=(?=(aaxy))aa) str: ..aaxy.. result_expr: $1 expected_results aaxy + diff --git a/regression-tests/test-results/gcc-10-c++20/mixed-autodiff-taylor.cpp.execution b/regression-tests/test-results/gcc-10-c++20/mixed-autodiff-taylor.cpp.execution new file mode 100644 index 000000000..0a486b06f --- /dev/null +++ b/regression-tests/test-results/gcc-10-c++20/mixed-autodiff-taylor.cpp.execution @@ -0,0 +1,63 @@ +x + x = 4.000000 +x + x diff order 1 = 2.000000 +x + x diff order 2 = 0.000000 +x + x diff order 3 = 0.000000 +x + x diff order 4 = 0.000000 +x + x diff order 5 = 0.000000 +x + x diff order 6 = 0.000000 +0 - x = -2.000000 +0 - x diff order 1 = -1.000000 +0 - x diff order 2 = 0.000000 +0 - x diff order 3 = 0.000000 +0 - x diff order 4 = 0.000000 +0 - x diff order 5 = 0.000000 +0 - x diff order 6 = 0.000000 +x^7 = 128.000000 +x^7 diff order 1 = 448.000000 +x^7 diff order 2 = 1344.000000 +x^7 diff order 3 = 3360.000000 +x^7 diff order 4 = 6720.000000 +x^7 diff order 5 = 10080.000000 +x^7 diff order 6 = 10080.000000 +1/x = 0.500000 +1/x diff order 1 = -0.250000 +1/x diff order 2 = 0.250000 +1/x diff order 3 = -0.375000 +1/x diff order 4 = 0.750000 +1/x diff order 5 = -1.875000 +1/x diff order 6 = 5.625000 +sqrt(x) = 1.414214 +sqrt(x) diff order 1 = 0.353553 +sqrt(x) diff order 2 = -0.088388 +sqrt(x) diff order 3 = 0.066291 +sqrt(x) diff order 4 = -0.082864 +sqrt(x) diff order 5 = 0.145012 +sqrt(x) diff order 6 = -0.326277 +log(x) = 0.693147 +log(x) diff order 1 = 0.500000 +log(x) diff order 2 = -0.250000 +log(x) diff order 3 = 0.250000 +log(x) diff order 4 = -0.375000 +log(x) diff order 5 = 0.750000 +log(x) diff order 6 = -1.875000 +exp(x) = 7.389056 +exp(x) diff order 1 = 7.389056 +exp(x) diff order 2 = 7.389056 +exp(x) diff order 3 = 7.389056 +exp(x) diff order 4 = 7.389056 +exp(x) diff order 5 = 7.389056 +exp(x) diff order 6 = 7.389056 +sin(x) = 0.909297 +sin(x) diff order 1 = -0.416147 +sin(x) diff order 2 = -0.909297 +sin(x) diff order 3 = 0.416147 +sin(x) diff order 4 = 0.909297 +sin(x) diff order 5 = -0.416147 +sin(x) diff order 6 = -0.909297 +cos(x) = -0.416147 +cos(x) diff order 1 = -0.909297 +cos(x) diff order 2 = 0.416147 +cos(x) diff order 3 = 0.909297 +cos(x) diff order 4 = -0.416147 +cos(x) diff order 5 = -0.909297 +cos(x) diff order 6 = 0.416147 diff --git a/regression-tests/test-results/gcc-10-c++20/pure2-autodiff-higher-order.cpp.execution b/regression-tests/test-results/gcc-10-c++20/pure2-autodiff-higher-order.cpp.execution new file mode 100644 index 000000000..84a5f58de --- /dev/null +++ b/regression-tests/test-results/gcc-10-c++20/pure2-autodiff-higher-order.cpp.execution @@ -0,0 +1,240 @@ +diff(x + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y + x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 7.000000 + d1 = 4.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -1.000000 + d1 = -1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -3.000000 + d1 = -2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 6.000000 + d1 = 7.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y * x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 12.000000 + d1 = 20.000000 + d2 = 22.000000 + d3 = 12.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.666667 + d1 = -0.111111 + d2 = 0.148148 + d3 = -0.296296 + d4 = 0.790123 + d5 = -2.633745 + d6 = 10.534979 +diff(x / y / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.222222 + d1 = -0.185185 + d2 = 0.296296 + d3 = -0.691358 + d4 = 2.106996 + d5 = -7.901235 + d6 = 35.116598 +diff(x * y / x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * (x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 8.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(+x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(-x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 1.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(sin(x - y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -0.841471 + d1 = -0.540302 + d2 = 0.841471 + d3 = 0.540302 + d4 = -0.841471 + d5 = -0.540302 + d6 = 0.841471 +diff(if branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(if else branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(direct return) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate passive var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate untyped) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate default init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate no init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(do while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(for loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(tye_outer.a + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(type_outer.add(y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 diff --git a/regression-tests/test-results/gcc-10-c++20/pure2-autodiff.cpp.execution b/regression-tests/test-results/gcc-10-c++20/pure2-autodiff.cpp.execution new file mode 100644 index 000000000..863bd6bd5 --- /dev/null +++ b/regression-tests/test-results/gcc-10-c++20/pure2-autodiff.cpp.execution @@ -0,0 +1,46 @@ +diff(x + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y + x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 7.000000, r_d = 4.000000) +diff(x - y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -1.000000, r_d = -1.000000) +diff(x - y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -3.000000, r_d = -2.000000) +diff(x + y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 6.000000, r_d = 7.000000) +diff(x * y * x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 12.000000, r_d = 20.000000) +diff(x / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.666667, r_d = -0.111111) +diff(x / y / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.222222, r_d = -0.185185) +diff(x * y / x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * (x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x + x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 8.000000) +diff(+x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(-x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 1.000000, r_d = 1.000000) +diff(x * func(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(sin(x - y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -0.841471, r_d = -0.540302) +diff(if branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(if else branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(direct return) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate passive var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate untyped) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate default init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate no init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(do while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(for loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(tye_outer.a + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(type_outer.add(y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 5.000000, x_b = 1.000000, y_b = 1.000000) +diff(x + y + x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 7.000000, x_b = 2.000000, y_b = 1.000000) +diff(x - y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -1.000000, x_b = 1.000000, y_b = -1.000000) +diff(x - y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -3.000000, x_b = 0.000000, y_b = -1.000000) +diff(x + y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 6.000000, x_b = 3.000000, y_b = 2.000000) +diff(x * y * x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 12.000000, x_b = 12.000000, y_b = 4.000000) +diff(x / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.666667, x_b = 0.333333, y_b = -0.222222) +diff(x / y / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.222222, x_b = 0.111111, y_b = -0.148148) +diff(x * y / x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * (x + y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x + x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 8.000000, x_b = 4.000000, y_b = 2.000000) +diff(sin(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -0.841471, x_b = 0.540302, y_b = -0.540302) +diff(x * func(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x * func_outer(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +2nd order diff of x*x at 2.000000 = 2.000000 diff --git a/regression-tests/test-results/gcc-10-c++20/pure2-regex_20_lookbehind.cpp.execution b/regression-tests/test-results/gcc-10-c++20/pure2-regex_20_lookbehind.cpp.execution new file mode 100644 index 000000000..cd61d4f56 --- /dev/null +++ b/regression-tests/test-results/gcc-10-c++20/pure2-regex_20_lookbehind.cpp.execution @@ -0,0 +1,58 @@ +Running tests_20_lookbehind: +01_y: OK regex: (?<=a)b parsed_regex: (?<=a)b str: ab result_expr: $& expected_results b +02_y: OK regex: (?<=af?)b parsed_regex: (?<=af?)b str: ab result_expr: $& expected_results b +03_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: cb result_expr: - expected_results - +04_n: OK regex: (?<=a(?:fo)?)b parsed_regex: (?<=a(?:fo)?)b str: cb result_expr: - expected_results - +05_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: b result_expr: - expected_results - +06_n: OK regex: (?<=a(?:foo)?)b parsed_regex: (?<=a(?:foo)?)b str: b result_expr: - expected_results - +07_y: OK regex: (?)foo parsed_regex: (?<=bar>)foo str: bar>foo result_expr: $& expected_results foo +50_n: OK regex: (?)foo parsed_regex: (?)foo str: bar>foo result_expr: - expected_results - +51_y: OK regex: (?<=bar>ABC)foo parsed_regex: (?<=bar>ABC)foo str: bar>ABCfoo result_expr: $& expected_results foo +52_n: OK regex: (?ABC)foo parsed_regex: (?ABC)foo str: bar>ABCfoo result_expr: - expected_results - +53_y: OK regex: (?<=abcd(?<=(aaaabcd))) parsed_regex: (?<=abcd(?<=(aaaabcd))) str: ..aaaabcd.. result_expr: $1 expected_results aaaabcd +54_y: OK regex: (?=xy(?<=(aaxy))) parsed_regex: (?=xy(?<=(aaxy))) str: ..aaxy.. result_expr: $1 expected_results aaxy +55_y: OK regex: (?=xy(?<=(aaxyz?))) parsed_regex: (?=xy(?<=(aaxyz?))) str: ..aaxy.. result_expr: $1 expected_results aaxy +56_y: OK regex: (?<=(?=(aaxy))aa) parsed_regex: (?<=(?=(aaxy))aa) str: ..aaxy.. result_expr: $1 expected_results aaxy + diff --git a/regression-tests/test-results/gcc-13-c++2b/mixed-autodiff-taylor.cpp.execution b/regression-tests/test-results/gcc-13-c++2b/mixed-autodiff-taylor.cpp.execution new file mode 100644 index 000000000..0a486b06f --- /dev/null +++ b/regression-tests/test-results/gcc-13-c++2b/mixed-autodiff-taylor.cpp.execution @@ -0,0 +1,63 @@ +x + x = 4.000000 +x + x diff order 1 = 2.000000 +x + x diff order 2 = 0.000000 +x + x diff order 3 = 0.000000 +x + x diff order 4 = 0.000000 +x + x diff order 5 = 0.000000 +x + x diff order 6 = 0.000000 +0 - x = -2.000000 +0 - x diff order 1 = -1.000000 +0 - x diff order 2 = 0.000000 +0 - x diff order 3 = 0.000000 +0 - x diff order 4 = 0.000000 +0 - x diff order 5 = 0.000000 +0 - x diff order 6 = 0.000000 +x^7 = 128.000000 +x^7 diff order 1 = 448.000000 +x^7 diff order 2 = 1344.000000 +x^7 diff order 3 = 3360.000000 +x^7 diff order 4 = 6720.000000 +x^7 diff order 5 = 10080.000000 +x^7 diff order 6 = 10080.000000 +1/x = 0.500000 +1/x diff order 1 = -0.250000 +1/x diff order 2 = 0.250000 +1/x diff order 3 = -0.375000 +1/x diff order 4 = 0.750000 +1/x diff order 5 = -1.875000 +1/x diff order 6 = 5.625000 +sqrt(x) = 1.414214 +sqrt(x) diff order 1 = 0.353553 +sqrt(x) diff order 2 = -0.088388 +sqrt(x) diff order 3 = 0.066291 +sqrt(x) diff order 4 = -0.082864 +sqrt(x) diff order 5 = 0.145012 +sqrt(x) diff order 6 = -0.326277 +log(x) = 0.693147 +log(x) diff order 1 = 0.500000 +log(x) diff order 2 = -0.250000 +log(x) diff order 3 = 0.250000 +log(x) diff order 4 = -0.375000 +log(x) diff order 5 = 0.750000 +log(x) diff order 6 = -1.875000 +exp(x) = 7.389056 +exp(x) diff order 1 = 7.389056 +exp(x) diff order 2 = 7.389056 +exp(x) diff order 3 = 7.389056 +exp(x) diff order 4 = 7.389056 +exp(x) diff order 5 = 7.389056 +exp(x) diff order 6 = 7.389056 +sin(x) = 0.909297 +sin(x) diff order 1 = -0.416147 +sin(x) diff order 2 = -0.909297 +sin(x) diff order 3 = 0.416147 +sin(x) diff order 4 = 0.909297 +sin(x) diff order 5 = -0.416147 +sin(x) diff order 6 = -0.909297 +cos(x) = -0.416147 +cos(x) diff order 1 = -0.909297 +cos(x) diff order 2 = 0.416147 +cos(x) diff order 3 = 0.909297 +cos(x) diff order 4 = -0.416147 +cos(x) diff order 5 = -0.909297 +cos(x) diff order 6 = 0.416147 diff --git a/regression-tests/test-results/gcc-13-c++2b/pure2-autodiff-higher-order.cpp.execution b/regression-tests/test-results/gcc-13-c++2b/pure2-autodiff-higher-order.cpp.execution new file mode 100644 index 000000000..84a5f58de --- /dev/null +++ b/regression-tests/test-results/gcc-13-c++2b/pure2-autodiff-higher-order.cpp.execution @@ -0,0 +1,240 @@ +diff(x + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y + x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 7.000000 + d1 = 4.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -1.000000 + d1 = -1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -3.000000 + d1 = -2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 6.000000 + d1 = 7.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y * x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 12.000000 + d1 = 20.000000 + d2 = 22.000000 + d3 = 12.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.666667 + d1 = -0.111111 + d2 = 0.148148 + d3 = -0.296296 + d4 = 0.790123 + d5 = -2.633745 + d6 = 10.534979 +diff(x / y / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.222222 + d1 = -0.185185 + d2 = 0.296296 + d3 = -0.691358 + d4 = 2.106996 + d5 = -7.901235 + d6 = 35.116598 +diff(x * y / x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * (x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 8.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(+x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(-x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 1.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(sin(x - y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -0.841471 + d1 = -0.540302 + d2 = 0.841471 + d3 = 0.540302 + d4 = -0.841471 + d5 = -0.540302 + d6 = 0.841471 +diff(if branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(if else branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(direct return) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate passive var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate untyped) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate default init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate no init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(do while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(for loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(tye_outer.a + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(type_outer.add(y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 diff --git a/regression-tests/test-results/gcc-13-c++2b/pure2-autodiff.cpp.execution b/regression-tests/test-results/gcc-13-c++2b/pure2-autodiff.cpp.execution new file mode 100644 index 000000000..863bd6bd5 --- /dev/null +++ b/regression-tests/test-results/gcc-13-c++2b/pure2-autodiff.cpp.execution @@ -0,0 +1,46 @@ +diff(x + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y + x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 7.000000, r_d = 4.000000) +diff(x - y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -1.000000, r_d = -1.000000) +diff(x - y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -3.000000, r_d = -2.000000) +diff(x + y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 6.000000, r_d = 7.000000) +diff(x * y * x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 12.000000, r_d = 20.000000) +diff(x / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.666667, r_d = -0.111111) +diff(x / y / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.222222, r_d = -0.185185) +diff(x * y / x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * (x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x + x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 8.000000) +diff(+x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(-x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 1.000000, r_d = 1.000000) +diff(x * func(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(sin(x - y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -0.841471, r_d = -0.540302) +diff(if branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(if else branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(direct return) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate passive var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate untyped) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate default init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate no init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(do while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(for loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(tye_outer.a + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(type_outer.add(y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 5.000000, x_b = 1.000000, y_b = 1.000000) +diff(x + y + x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 7.000000, x_b = 2.000000, y_b = 1.000000) +diff(x - y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -1.000000, x_b = 1.000000, y_b = -1.000000) +diff(x - y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -3.000000, x_b = 0.000000, y_b = -1.000000) +diff(x + y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 6.000000, x_b = 3.000000, y_b = 2.000000) +diff(x * y * x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 12.000000, x_b = 12.000000, y_b = 4.000000) +diff(x / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.666667, x_b = 0.333333, y_b = -0.222222) +diff(x / y / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.222222, x_b = 0.111111, y_b = -0.148148) +diff(x * y / x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * (x + y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x + x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 8.000000, x_b = 4.000000, y_b = 2.000000) +diff(sin(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -0.841471, x_b = 0.540302, y_b = -0.540302) +diff(x * func(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x * func_outer(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +2nd order diff of x*x at 2.000000 = 2.000000 diff --git a/regression-tests/test-results/gcc-13-c++2b/pure2-regex_20_lookbehind.cpp.execution b/regression-tests/test-results/gcc-13-c++2b/pure2-regex_20_lookbehind.cpp.execution new file mode 100644 index 000000000..cd61d4f56 --- /dev/null +++ b/regression-tests/test-results/gcc-13-c++2b/pure2-regex_20_lookbehind.cpp.execution @@ -0,0 +1,58 @@ +Running tests_20_lookbehind: +01_y: OK regex: (?<=a)b parsed_regex: (?<=a)b str: ab result_expr: $& expected_results b +02_y: OK regex: (?<=af?)b parsed_regex: (?<=af?)b str: ab result_expr: $& expected_results b +03_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: cb result_expr: - expected_results - +04_n: OK regex: (?<=a(?:fo)?)b parsed_regex: (?<=a(?:fo)?)b str: cb result_expr: - expected_results - +05_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: b result_expr: - expected_results - +06_n: OK regex: (?<=a(?:foo)?)b parsed_regex: (?<=a(?:foo)?)b str: b result_expr: - expected_results - +07_y: OK regex: (?)foo parsed_regex: (?<=bar>)foo str: bar>foo result_expr: $& expected_results foo +50_n: OK regex: (?)foo parsed_regex: (?)foo str: bar>foo result_expr: - expected_results - +51_y: OK regex: (?<=bar>ABC)foo parsed_regex: (?<=bar>ABC)foo str: bar>ABCfoo result_expr: $& expected_results foo +52_n: OK regex: (?ABC)foo parsed_regex: (?ABC)foo str: bar>ABCfoo result_expr: - expected_results - +53_y: OK regex: (?<=abcd(?<=(aaaabcd))) parsed_regex: (?<=abcd(?<=(aaaabcd))) str: ..aaaabcd.. result_expr: $1 expected_results aaaabcd +54_y: OK regex: (?=xy(?<=(aaxy))) parsed_regex: (?=xy(?<=(aaxy))) str: ..aaxy.. result_expr: $1 expected_results aaxy +55_y: OK regex: (?=xy(?<=(aaxyz?))) parsed_regex: (?=xy(?<=(aaxyz?))) str: ..aaxy.. result_expr: $1 expected_results aaxy +56_y: OK regex: (?<=(?=(aaxy))aa) parsed_regex: (?<=(?=(aaxy))aa) str: ..aaxy.. result_expr: $1 expected_results aaxy + diff --git a/regression-tests/test-results/gcc-14-c++2b/mixed-autodiff-taylor.cpp.execution b/regression-tests/test-results/gcc-14-c++2b/mixed-autodiff-taylor.cpp.execution new file mode 100644 index 000000000..0a486b06f --- /dev/null +++ b/regression-tests/test-results/gcc-14-c++2b/mixed-autodiff-taylor.cpp.execution @@ -0,0 +1,63 @@ +x + x = 4.000000 +x + x diff order 1 = 2.000000 +x + x diff order 2 = 0.000000 +x + x diff order 3 = 0.000000 +x + x diff order 4 = 0.000000 +x + x diff order 5 = 0.000000 +x + x diff order 6 = 0.000000 +0 - x = -2.000000 +0 - x diff order 1 = -1.000000 +0 - x diff order 2 = 0.000000 +0 - x diff order 3 = 0.000000 +0 - x diff order 4 = 0.000000 +0 - x diff order 5 = 0.000000 +0 - x diff order 6 = 0.000000 +x^7 = 128.000000 +x^7 diff order 1 = 448.000000 +x^7 diff order 2 = 1344.000000 +x^7 diff order 3 = 3360.000000 +x^7 diff order 4 = 6720.000000 +x^7 diff order 5 = 10080.000000 +x^7 diff order 6 = 10080.000000 +1/x = 0.500000 +1/x diff order 1 = -0.250000 +1/x diff order 2 = 0.250000 +1/x diff order 3 = -0.375000 +1/x diff order 4 = 0.750000 +1/x diff order 5 = -1.875000 +1/x diff order 6 = 5.625000 +sqrt(x) = 1.414214 +sqrt(x) diff order 1 = 0.353553 +sqrt(x) diff order 2 = -0.088388 +sqrt(x) diff order 3 = 0.066291 +sqrt(x) diff order 4 = -0.082864 +sqrt(x) diff order 5 = 0.145012 +sqrt(x) diff order 6 = -0.326277 +log(x) = 0.693147 +log(x) diff order 1 = 0.500000 +log(x) diff order 2 = -0.250000 +log(x) diff order 3 = 0.250000 +log(x) diff order 4 = -0.375000 +log(x) diff order 5 = 0.750000 +log(x) diff order 6 = -1.875000 +exp(x) = 7.389056 +exp(x) diff order 1 = 7.389056 +exp(x) diff order 2 = 7.389056 +exp(x) diff order 3 = 7.389056 +exp(x) diff order 4 = 7.389056 +exp(x) diff order 5 = 7.389056 +exp(x) diff order 6 = 7.389056 +sin(x) = 0.909297 +sin(x) diff order 1 = -0.416147 +sin(x) diff order 2 = -0.909297 +sin(x) diff order 3 = 0.416147 +sin(x) diff order 4 = 0.909297 +sin(x) diff order 5 = -0.416147 +sin(x) diff order 6 = -0.909297 +cos(x) = -0.416147 +cos(x) diff order 1 = -0.909297 +cos(x) diff order 2 = 0.416147 +cos(x) diff order 3 = 0.909297 +cos(x) diff order 4 = -0.416147 +cos(x) diff order 5 = -0.909297 +cos(x) diff order 6 = 0.416147 diff --git a/regression-tests/test-results/gcc-14-c++2b/pure2-autodiff-higher-order.cpp.execution b/regression-tests/test-results/gcc-14-c++2b/pure2-autodiff-higher-order.cpp.execution new file mode 100644 index 000000000..84a5f58de --- /dev/null +++ b/regression-tests/test-results/gcc-14-c++2b/pure2-autodiff-higher-order.cpp.execution @@ -0,0 +1,240 @@ +diff(x + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y + x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 7.000000 + d1 = 4.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -1.000000 + d1 = -1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x - y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -3.000000 + d1 = -2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + y - x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 6.000000 + d1 = 7.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * y * x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 12.000000 + d1 = 20.000000 + d2 = 22.000000 + d3 = 12.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.666667 + d1 = -0.111111 + d2 = 0.148148 + d3 = -0.296296 + d4 = 0.790123 + d5 = -2.633745 + d6 = 10.534979 +diff(x / y / y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 0.222222 + d1 = -0.185185 + d2 = 0.296296 + d3 = -0.691358 + d4 = 2.106996 + d5 = -7.901235 + d6 = 35.116598 +diff(x * y / x) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 3.000000 + d1 = 2.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * (x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x + x * y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 8.000000 + d2 = 4.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(+x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(-x + y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 1.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 10.000000 + d1 = 11.000000 + d2 = 6.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(sin(x - y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = -0.841471 + d1 = -0.540302 + d2 = 0.841471 + d3 = 0.540302 + d4 = -0.841471 + d5 = -0.540302 + d6 = 0.841471 +diff(if branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(if else branch) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 2.000000 + d1 = 1.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(direct return) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate passive var) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate untyped) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate default init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(intermediate no init) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(do while loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 8.000000 + d1 = 5.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(for loop) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(tye_outer.a + y) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 +diff(type_outer.add(y)) at (x = 2.000000, x_d = ( 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ), y = 3.000000, y_d = ( 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 )): + r = 5.000000 + d1 = 3.000000 + d2 = 0.000000 + d3 = 0.000000 + d4 = 0.000000 + d5 = 0.000000 + d6 = 0.000000 diff --git a/regression-tests/test-results/gcc-14-c++2b/pure2-autodiff.cpp.execution b/regression-tests/test-results/gcc-14-c++2b/pure2-autodiff.cpp.execution new file mode 100644 index 000000000..863bd6bd5 --- /dev/null +++ b/regression-tests/test-results/gcc-14-c++2b/pure2-autodiff.cpp.execution @@ -0,0 +1,46 @@ +diff(x + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y + x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 7.000000, r_d = 4.000000) +diff(x - y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -1.000000, r_d = -1.000000) +diff(x - y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -3.000000, r_d = -2.000000) +diff(x + y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 6.000000, r_d = 7.000000) +diff(x * y * x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 12.000000, r_d = 20.000000) +diff(x / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.666667, r_d = -0.111111) +diff(x / y / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.222222, r_d = -0.185185) +diff(x * y / x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * (x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x + x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 8.000000) +diff(+x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(-x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 1.000000, r_d = 1.000000) +diff(x * func(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(sin(x - y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -0.841471, r_d = -0.540302) +diff(if branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(if else branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(direct return) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate passive var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate untyped) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate default init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate no init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(do while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(for loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(tye_outer.a + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(type_outer.add(y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 5.000000, x_b = 1.000000, y_b = 1.000000) +diff(x + y + x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 7.000000, x_b = 2.000000, y_b = 1.000000) +diff(x - y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -1.000000, x_b = 1.000000, y_b = -1.000000) +diff(x - y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -3.000000, x_b = 0.000000, y_b = -1.000000) +diff(x + y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 6.000000, x_b = 3.000000, y_b = 2.000000) +diff(x * y * x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 12.000000, x_b = 12.000000, y_b = 4.000000) +diff(x / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.666667, x_b = 0.333333, y_b = -0.222222) +diff(x / y / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.222222, x_b = 0.111111, y_b = -0.148148) +diff(x * y / x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * (x + y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x + x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 8.000000, x_b = 4.000000, y_b = 2.000000) +diff(sin(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -0.841471, x_b = 0.540302, y_b = -0.540302) +diff(x * func(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x * func_outer(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +2nd order diff of x*x at 2.000000 = 2.000000 diff --git a/regression-tests/test-results/gcc-14-c++2b/pure2-regex_20_lookbehind.cpp.execution b/regression-tests/test-results/gcc-14-c++2b/pure2-regex_20_lookbehind.cpp.execution new file mode 100644 index 000000000..cd61d4f56 --- /dev/null +++ b/regression-tests/test-results/gcc-14-c++2b/pure2-regex_20_lookbehind.cpp.execution @@ -0,0 +1,58 @@ +Running tests_20_lookbehind: +01_y: OK regex: (?<=a)b parsed_regex: (?<=a)b str: ab result_expr: $& expected_results b +02_y: OK regex: (?<=af?)b parsed_regex: (?<=af?)b str: ab result_expr: $& expected_results b +03_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: cb result_expr: - expected_results - +04_n: OK regex: (?<=a(?:fo)?)b parsed_regex: (?<=a(?:fo)?)b str: cb result_expr: - expected_results - +05_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: b result_expr: - expected_results - +06_n: OK regex: (?<=a(?:foo)?)b parsed_regex: (?<=a(?:foo)?)b str: b result_expr: - expected_results - +07_y: OK regex: (?)foo parsed_regex: (?<=bar>)foo str: bar>foo result_expr: $& expected_results foo +50_n: OK regex: (?)foo parsed_regex: (?)foo str: bar>foo result_expr: - expected_results - +51_y: OK regex: (?<=bar>ABC)foo parsed_regex: (?<=bar>ABC)foo str: bar>ABCfoo result_expr: $& expected_results foo +52_n: OK regex: (?ABC)foo parsed_regex: (?ABC)foo str: bar>ABCfoo result_expr: - expected_results - +53_y: OK regex: (?<=abcd(?<=(aaaabcd))) parsed_regex: (?<=abcd(?<=(aaaabcd))) str: ..aaaabcd.. result_expr: $1 expected_results aaaabcd +54_y: OK regex: (?=xy(?<=(aaxy))) parsed_regex: (?=xy(?<=(aaxy))) str: ..aaxy.. result_expr: $1 expected_results aaxy +55_y: OK regex: (?=xy(?<=(aaxyz?))) parsed_regex: (?=xy(?<=(aaxyz?))) str: ..aaxy.. result_expr: $1 expected_results aaxy +56_y: OK regex: (?<=(?=(aaxy))aa) parsed_regex: (?<=(?=(aaxy))aa) str: ..aaxy.. result_expr: $1 expected_results aaxy + diff --git a/regression-tests/test-results/mixed-autodiff-taylor.cpp b/regression-tests/test-results/mixed-autodiff-taylor.cpp new file mode 100644 index 000000000..0d9798c13 --- /dev/null +++ b/regression-tests/test-results/mixed-autodiff-taylor.cpp @@ -0,0 +1,215 @@ +#include + + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "mixed-autodiff-taylor.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "mixed-autodiff-taylor.cpp2" + +#line 3 "mixed-autodiff-taylor.cpp2" +int inline constexpr order{ 6 }; +using taylor = cpp2::taylor; + +struct test_add_ret { double y0; taylor y; }; + +#line 6 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_add(cpp2::impl::in x0, cpp2::impl::in x) -> test_add_ret; +struct test_sub_ret { double y0; taylor y; }; + + + +#line 11 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_sub(cpp2::impl::in x0, cpp2::impl::in x) -> test_sub_ret; +struct test_mul_ret { double y0; taylor y; }; + + + +#line 19 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_mul(cpp2::impl::in x0, cpp2::impl::in x) -> test_mul_ret; +struct test_div_ret { double y0; taylor y; }; + + + +#line 30 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_div(cpp2::impl::in x0, cpp2::impl::in x) -> test_div_ret; +struct test_sqrt_ret { double y0; taylor y; }; + + + +#line 38 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_sqrt(cpp2::impl::in x0, cpp2::impl::in x) -> test_sqrt_ret; +struct test_log_ret { double y0; taylor y; }; + + + +#line 43 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_log(cpp2::impl::in x0, cpp2::impl::in x) -> test_log_ret; +struct test_exp_ret { double y0; taylor y; }; + + + +#line 48 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_exp(cpp2::impl::in x0, cpp2::impl::in x) -> test_exp_ret; +struct test_sin_ret { double y0; taylor y; }; + + + +#line 53 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_sin(cpp2::impl::in x0, cpp2::impl::in x) -> test_sin_ret; +struct test_cos_ret { double y0; taylor y; }; + + + +#line 58 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_cos(cpp2::impl::in x0, cpp2::impl::in x) -> test_cos_ret; + +#line 63 "mixed-autodiff-taylor.cpp2" +auto write_output(cpp2::impl::in func, cpp2::impl::in x, cpp2::impl::in x_d, auto const& ret) -> void; + +#line 73 "mixed-autodiff-taylor.cpp2" +auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "mixed-autodiff-taylor.cpp2" + +#line 6 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_add(cpp2::impl::in x0, cpp2::impl::in x) -> test_add_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 7 "mixed-autodiff-taylor.cpp2" + y.construct(CPP2_UFCS(add)(x, x, x0, x0)); + y0.construct(x0 + x0); +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 11 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_sub(cpp2::impl::in x0, cpp2::impl::in x) -> test_sub_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 12 "mixed-autodiff-taylor.cpp2" + y0.construct(0.0); + y.construct(taylor()); + + y.value() = CPP2_UFCS(sub)(y.value(), x, y0.value(), x0); + y0.value() = y0.value() - x0; +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 19 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_mul(cpp2::impl::in x0, cpp2::impl::in x) -> test_mul_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 20 "mixed-autodiff-taylor.cpp2" + y0.construct(x0); + y.construct(x); +{ +auto i{0}; + +#line 24 "mixed-autodiff-taylor.cpp2" + for( ; cpp2::impl::cmp_less(i,6); i += 1 ) { + y.value() = y.value().mul(x, y0.value(), x0); + y0.value() *= x0; + } +} +#line 25 "mixed-autodiff-taylor.cpp2" + return { std::move(y0.value()), std::move(y.value()) }; + +#line 28 "mixed-autodiff-taylor.cpp2" +} + +#line 30 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_div(cpp2::impl::in x0, cpp2::impl::in x) -> test_div_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 31 "mixed-autodiff-taylor.cpp2" + y0.construct(1.0); + y.construct(taylor()); + + y.value() = CPP2_UFCS(div)(y.value(), x, y0.value(), x0); + y0.value() /= CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y0.value()),x0); +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 38 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_sqrt(cpp2::impl::in x0, cpp2::impl::in x) -> test_sqrt_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 39 "mixed-autodiff-taylor.cpp2" + y0.construct(sqrt(x0)); + y.construct(CPP2_UFCS(sqrt)(x, x0)); +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 43 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_log(cpp2::impl::in x0, cpp2::impl::in x) -> test_log_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 44 "mixed-autodiff-taylor.cpp2" + y0.construct(log(x0)); + y.construct(CPP2_UFCS(log)(x, x0)); +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 48 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_exp(cpp2::impl::in x0, cpp2::impl::in x) -> test_exp_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 49 "mixed-autodiff-taylor.cpp2" + y0.construct(exp(x0)); + y.construct(CPP2_UFCS(exp)(x, x0)); +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 53 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_sin(cpp2::impl::in x0, cpp2::impl::in x) -> test_sin_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 54 "mixed-autodiff-taylor.cpp2" + y0.construct(sin(x0)); + y.construct(CPP2_UFCS(sin)(x, x0)); +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 58 "mixed-autodiff-taylor.cpp2" +[[nodiscard]] auto test_cos(cpp2::impl::in x0, cpp2::impl::in x) -> test_cos_ret{ + cpp2::impl::deferred_init y0; + cpp2::impl::deferred_init y; +#line 59 "mixed-autodiff-taylor.cpp2" + y0.construct(cos(x0)); + y.construct(CPP2_UFCS(cos)(x, x0)); +return { std::move(y0.value()), std::move(y.value()) }; } + +#line 63 "mixed-autodiff-taylor.cpp2" +auto write_output(cpp2::impl::in func, cpp2::impl::in x, cpp2::impl::in x_d, auto const& ret) -> void{ + static_cast(x); + static_cast(x_d); + std::cout << "" + cpp2::to_string(func) + " = " + cpp2::to_string(ret.y0) + "" << std::endl; +{ +auto i{1}; + +#line 68 "mixed-autodiff-taylor.cpp2" + for( ; cpp2::impl::cmp_less_eq(i,order); i += 1 ) { + std::cout << "" + cpp2::to_string(func) + " diff order " + cpp2::to_string(i) + " = " + cpp2::to_string(CPP2_ASSERT_IN_BOUNDS(ret.y, i)) + "" << std::endl; + } +} +#line 71 "mixed-autodiff-taylor.cpp2" +} + +#line 73 "mixed-autodiff-taylor.cpp2" +auto main() -> int{ + + double x {2.0}; + taylor x_d {1.0}; + + write_output("x + x", x, x_d, test_add(x, x_d)); + write_output("0 - x", x, x_d, test_sub(x, x_d)); + write_output("x^7", x, x_d, test_mul(x, x_d)); + write_output("1/x", x, x_d, test_div(x, x_d)); + write_output("sqrt(x)", x, x_d, test_sqrt(x, x_d)); + write_output("log(x)", x, x_d, test_log(x, x_d)); + write_output("exp(x)", x, x_d, test_exp(x, x_d)); + write_output("sin(x)", x, x_d, test_sin(x, x_d)); + write_output("cos(x)", x, x_d, test_cos(cpp2::move(x), cpp2::move(x_d))); +} + diff --git a/regression-tests/test-results/mixed-autodiff-taylor.cpp2.output b/regression-tests/test-results/mixed-autodiff-taylor.cpp2.output new file mode 100644 index 000000000..20bd4dd08 --- /dev/null +++ b/regression-tests/test-results/mixed-autodiff-taylor.cpp2.output @@ -0,0 +1,2 @@ +mixed-autodiff-taylor.cpp2... ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks) + diff --git a/regression-tests/test-results/msvc-2022-c++latest/mixed-autodiff-taylor.cpp.execution b/regression-tests/test-results/msvc-2022-c++latest/mixed-autodiff-taylor.cpp.execution new file mode 100644 index 000000000..0a486b06f --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/mixed-autodiff-taylor.cpp.execution @@ -0,0 +1,63 @@ +x + x = 4.000000 +x + x diff order 1 = 2.000000 +x + x diff order 2 = 0.000000 +x + x diff order 3 = 0.000000 +x + x diff order 4 = 0.000000 +x + x diff order 5 = 0.000000 +x + x diff order 6 = 0.000000 +0 - x = -2.000000 +0 - x diff order 1 = -1.000000 +0 - x diff order 2 = 0.000000 +0 - x diff order 3 = 0.000000 +0 - x diff order 4 = 0.000000 +0 - x diff order 5 = 0.000000 +0 - x diff order 6 = 0.000000 +x^7 = 128.000000 +x^7 diff order 1 = 448.000000 +x^7 diff order 2 = 1344.000000 +x^7 diff order 3 = 3360.000000 +x^7 diff order 4 = 6720.000000 +x^7 diff order 5 = 10080.000000 +x^7 diff order 6 = 10080.000000 +1/x = 0.500000 +1/x diff order 1 = -0.250000 +1/x diff order 2 = 0.250000 +1/x diff order 3 = -0.375000 +1/x diff order 4 = 0.750000 +1/x diff order 5 = -1.875000 +1/x diff order 6 = 5.625000 +sqrt(x) = 1.414214 +sqrt(x) diff order 1 = 0.353553 +sqrt(x) diff order 2 = -0.088388 +sqrt(x) diff order 3 = 0.066291 +sqrt(x) diff order 4 = -0.082864 +sqrt(x) diff order 5 = 0.145012 +sqrt(x) diff order 6 = -0.326277 +log(x) = 0.693147 +log(x) diff order 1 = 0.500000 +log(x) diff order 2 = -0.250000 +log(x) diff order 3 = 0.250000 +log(x) diff order 4 = -0.375000 +log(x) diff order 5 = 0.750000 +log(x) diff order 6 = -1.875000 +exp(x) = 7.389056 +exp(x) diff order 1 = 7.389056 +exp(x) diff order 2 = 7.389056 +exp(x) diff order 3 = 7.389056 +exp(x) diff order 4 = 7.389056 +exp(x) diff order 5 = 7.389056 +exp(x) diff order 6 = 7.389056 +sin(x) = 0.909297 +sin(x) diff order 1 = -0.416147 +sin(x) diff order 2 = -0.909297 +sin(x) diff order 3 = 0.416147 +sin(x) diff order 4 = 0.909297 +sin(x) diff order 5 = -0.416147 +sin(x) diff order 6 = -0.909297 +cos(x) = -0.416147 +cos(x) diff order 1 = -0.909297 +cos(x) diff order 2 = 0.416147 +cos(x) diff order 3 = 0.909297 +cos(x) diff order 4 = -0.416147 +cos(x) diff order 5 = -0.909297 +cos(x) diff order 6 = 0.416147 diff --git a/regression-tests/test-results/msvc-2022-c++latest/mixed-autodiff-taylor.cpp.output b/regression-tests/test-results/msvc-2022-c++latest/mixed-autodiff-taylor.cpp.output new file mode 100644 index 000000000..fac16efc8 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/mixed-autodiff-taylor.cpp.output @@ -0,0 +1 @@ +mixed-autodiff-taylor.cpp diff --git a/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff-higher-order.cpp.output b/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff-higher-order.cpp.output new file mode 100644 index 000000000..f066190e5 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff-higher-order.cpp.output @@ -0,0 +1,15 @@ +pure2-autodiff-higher-order.cpp +C:\github\cppfront\include\cpp2util.h(1250): error C7595: 'std::source_location::current': call to immediate function is not a constant expression +C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\source_location(37): note: failure was caused by attempting to access a member on an object of dynamic type 'std::source_location' in which the member is not defined +C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\source_location(37): note: see usage of 'std::source_location::source_location' +C:\github\cppfront\include\cpp2util.h(1250): note: the call stack of the evaluation (the oldest call first) is +C:\github\cppfront\include\cpp2util.h(1250): note: while evaluating function 'std::source_location std::source_location::current(const uint_least32_t,const uint_least32_t,const char *const ,const char *const ) noexcept' +C:\github\cppfront\include\cpp2util.h(1250): note: the template instantiation context (the oldest one first) is +pure2-autodiff-higher-order.cpp2(14): note: see reference to class template instantiation 'cpp2::taylor' being compiled +cpp2taylor.h2(16): note: while compiling class template member function 'cpp2::taylor::taylor(const std::initializer_list &)' + with + [ + R=double + ] +pure2-autodiff-higher-order.cpp2(25): note: see the first reference to 'cpp2::taylor::taylor' in 'ad_name::func_outer_d' +cpp2taylor.h2(35): note: while compiling class template member function 'void cpp2::taylor::set(const int,const double) &' diff --git a/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff.cpp.execution b/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff.cpp.execution new file mode 100644 index 000000000..863bd6bd5 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff.cpp.execution @@ -0,0 +1,46 @@ +diff(x + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y + x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 7.000000, r_d = 4.000000) +diff(x - y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -1.000000, r_d = -1.000000) +diff(x - y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -3.000000, r_d = -2.000000) +diff(x + y - x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 6.000000, r_d = 7.000000) +diff(x * y * x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 12.000000, r_d = 20.000000) +diff(x / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.666667, r_d = -0.111111) +diff(x / y / y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 0.222222, r_d = -0.185185) +diff(x * y / x) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 3.000000, r_d = 2.000000) +diff(x * (x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x + x * y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 8.000000) +diff(+x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(-x + y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 1.000000, r_d = 1.000000) +diff(x * func(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(x * func_outer(x, y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 10.000000, r_d = 11.000000) +diff(sin(x - y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = -0.841471, r_d = -0.540302) +diff(if branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(if else branch) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 2.000000, r_d = 1.000000) +diff(direct return) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate passive var) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate untyped) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate default init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(intermediate no init) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(do while loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 8.000000, r_d = 5.000000) +diff(for loop) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(tye_outer.a + y) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(type_outer.add(y)) at (x = 2.000000, x_d = 1.000000, y = 3.000000, y_d = 2.000000) = (r = 5.000000, r_d = 3.000000) +diff(x + y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 5.000000, x_b = 1.000000, y_b = 1.000000) +diff(x + y + x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 7.000000, x_b = 2.000000, y_b = 1.000000) +diff(x - y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -1.000000, x_b = 1.000000, y_b = -1.000000) +diff(x - y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -3.000000, x_b = 0.000000, y_b = -1.000000) +diff(x + y - x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 6.000000, x_b = 3.000000, y_b = 2.000000) +diff(x * y * x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 12.000000, x_b = 12.000000, y_b = 4.000000) +diff(x / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.666667, x_b = 0.333333, y_b = -0.222222) +diff(x / y / y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 0.222222, x_b = 0.111111, y_b = -0.148148) +diff(x * y / x) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 3.000000, x_b = 0.000000, y_b = 1.000000) +diff(x * (x + y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x + x * y) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 8.000000, x_b = 4.000000, y_b = 2.000000) +diff(sin(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = -0.841471, x_b = 0.540302, y_b = -0.540302) +diff(x * func(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +diff(x * func_outer(x-y)) at (x = 2.000000, y = 3.000000, r_b = 1.000000) = (r = 10.000000, x_b = 7.000000, y_b = 2.000000) +2nd order diff of x*x at 2.000000 = 2.000000 diff --git a/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff.cpp.output b/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff.cpp.output new file mode 100644 index 000000000..18a6df6f0 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/pure2-autodiff.cpp.output @@ -0,0 +1,15 @@ +pure2-autodiff.cpp +C:\github\cppfront\include\cpp2util.h(1250): error C7595: 'std::source_location::current': call to immediate function is not a constant expression +C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\source_location(37): note: failure was caused by attempting to access a member on an object of dynamic type 'std::source_location' in which the member is not defined +C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\source_location(37): note: see usage of 'std::source_location::source_location' +C:\github\cppfront\include\cpp2util.h(1250): note: the call stack of the evaluation (the oldest call first) is +C:\github\cppfront\include\cpp2util.h(1250): note: while evaluating function 'std::source_location std::source_location::current(const uint_least32_t,const uint_least32_t,const char *const ,const char *const ) noexcept' +C:\github\cppfront\include\cpp2util.h(1250): note: the template instantiation context (the oldest one first) is +pure2-autodiff.cpp2(282): note: see reference to class template instantiation 'cpp2::taylor' being compiled +cpp2taylor.h2(16): note: while compiling class template member function 'cpp2::taylor::taylor(const std::initializer_list &)' + with + [ + R=double + ] +pure2-autodiff.cpp2(298): note: see the first reference to 'cpp2::taylor::taylor' in 'ad_test_2::f_d' +cpp2taylor.h2(35): note: while compiling class template member function 'void cpp2::taylor::set(const int,const double) &' diff --git a/regression-tests/test-results/msvc-2022-c++latest/pure2-regex_20_lookbehind.cpp.execution b/regression-tests/test-results/msvc-2022-c++latest/pure2-regex_20_lookbehind.cpp.execution new file mode 100644 index 000000000..cd61d4f56 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/pure2-regex_20_lookbehind.cpp.execution @@ -0,0 +1,58 @@ +Running tests_20_lookbehind: +01_y: OK regex: (?<=a)b parsed_regex: (?<=a)b str: ab result_expr: $& expected_results b +02_y: OK regex: (?<=af?)b parsed_regex: (?<=af?)b str: ab result_expr: $& expected_results b +03_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: cb result_expr: - expected_results - +04_n: OK regex: (?<=a(?:fo)?)b parsed_regex: (?<=a(?:fo)?)b str: cb result_expr: - expected_results - +05_n: OK regex: (?<=a)b parsed_regex: (?<=a)b str: b result_expr: - expected_results - +06_n: OK regex: (?<=a(?:foo)?)b parsed_regex: (?<=a(?:foo)?)b str: b result_expr: - expected_results - +07_y: OK regex: (?)foo parsed_regex: (?<=bar>)foo str: bar>foo result_expr: $& expected_results foo +50_n: OK regex: (?)foo parsed_regex: (?)foo str: bar>foo result_expr: - expected_results - +51_y: OK regex: (?<=bar>ABC)foo parsed_regex: (?<=bar>ABC)foo str: bar>ABCfoo result_expr: $& expected_results foo +52_n: OK regex: (?ABC)foo parsed_regex: (?ABC)foo str: bar>ABCfoo result_expr: - expected_results - +53_y: OK regex: (?<=abcd(?<=(aaaabcd))) parsed_regex: (?<=abcd(?<=(aaaabcd))) str: ..aaaabcd.. result_expr: $1 expected_results aaaabcd +54_y: OK regex: (?=xy(?<=(aaxy))) parsed_regex: (?=xy(?<=(aaxy))) str: ..aaxy.. result_expr: $1 expected_results aaxy +55_y: OK regex: (?=xy(?<=(aaxyz?))) parsed_regex: (?=xy(?<=(aaxyz?))) str: ..aaxy.. result_expr: $1 expected_results aaxy +56_y: OK regex: (?<=(?=(aaxy))aa) parsed_regex: (?<=(?=(aaxy))aa) str: ..aaxy.. result_expr: $1 expected_results aaxy + diff --git a/regression-tests/test-results/msvc-2022-c++latest/pure2-regex_20_lookbehind.cpp.output b/regression-tests/test-results/msvc-2022-c++latest/pure2-regex_20_lookbehind.cpp.output new file mode 100644 index 000000000..14196f2d8 --- /dev/null +++ b/regression-tests/test-results/msvc-2022-c++latest/pure2-regex_20_lookbehind.cpp.output @@ -0,0 +1 @@ +pure2-regex_20_lookbehind.cpp diff --git a/regression-tests/test-results/pure2-autodiff-higher-order.cpp b/regression-tests/test-results/pure2-autodiff-higher-order.cpp new file mode 100644 index 000000000..118fe0fd0 --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff-higher-order.cpp @@ -0,0 +1,1079 @@ + +#define CPP2_IMPORT_STD Yes +#include "cpp2taylor.h" + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-autodiff-higher-order.cpp2" + +#line 4 "pure2-autodiff-higher-order.cpp2" +namespace ad_name { + +#line 10 "pure2-autodiff-higher-order.cpp2" +class type_outer; + + class type_outer_d; + + +#line 18 "pure2-autodiff-higher-order.cpp2" +class ad_test; + +#line 196 "pure2-autodiff-higher-order.cpp2" +} + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-autodiff-higher-order.cpp2" +int inline constexpr ad_order{ 6 }; +#line 2 "pure2-autodiff-higher-order.cpp2" +using ad_type = cpp2::taylor; + +namespace ad_name { +using func_outer_ret = double; + + +#line 6 "pure2-autodiff-higher-order.cpp2" +[[nodiscard]] auto func_outer(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_ret; + +#line 10 "pure2-autodiff-higher-order.cpp2" +class type_outer { + public: double a {0.0}; + + public: [[nodiscard]] auto add(cpp2::impl::in b) const& -> double; +struct add_d_ret { double r; cpp2::taylor r_d; }; + + + public: [[nodiscard]] auto add_d(cpp2::impl::in this_d, cpp2::impl::in b, cpp2::impl::in> b_d) const& -> add_d_ret; + + public: type_outer() = default; + public: type_outer(type_outer const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(type_outer const&) -> void = delete; + + +#line 16 "pure2-autodiff-higher-order.cpp2" +}; + +struct func_outer_d_ret { double ret; cpp2::taylor ret_d; }; + + +[[nodiscard]] auto func_outer_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_outer_d_ret; +class type_outer_d { +public: cpp2::taylor a_d {}; + public: type_outer_d() = default; + public: type_outer_d(type_outer_d const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(type_outer_d const&) -> void = delete; + +}; + +#line 18 "pure2-autodiff-higher-order.cpp2" +class ad_test { +using add_1_ret = double; + + +#line 20 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret; +using add_2_ret = double; + + +#line 24 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret; +using sub_1_ret = double; + + +#line 28 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret; +using sub_2_ret = double; + + +#line 32 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret; +using add_sub_2_ret = double; + + +#line 36 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret; +using mul_1_ret = double; + + +#line 40 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret; +using mul_2_ret = double; + + +#line 44 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret; +using div_1_ret = double; + + +#line 48 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret; +using div_2_ret = double; + + +#line 52 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret; +using mul_div_2_ret = double; + + +#line 56 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret; +using mul_add_ret = double; + + +#line 60 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret; +using add_mul_ret = double; + + +#line 64 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret; +using prefix_add_ret = double; + + +#line 68 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto prefix_add(cpp2::impl::in x, cpp2::impl::in y) -> prefix_add_ret; +using prefix_sub_ret = double; + + +#line 72 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto prefix_sub(cpp2::impl::in x, cpp2::impl::in y) -> prefix_sub_ret; +using func_ret = double; + + +#line 76 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret; +using func_call_ret = double; + + +#line 80 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret; +using func_outer_call_ret = double; + + +#line 84 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret; +using sin_call_ret = double; + + +#line 88 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret; +using if_branch_ret = double; + + +#line 92 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto if_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_branch_ret; +using if_else_branch_ret = double; + + +#line 100 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto if_else_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_else_branch_ret; + +#line 109 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto direct_return(cpp2::impl::in x, cpp2::impl::in y) -> double; +using intermediate_var_ret = double; + + +#line 113 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto intermediate_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_var_ret; +using intermediate_passive_var_ret = double; + + +#line 119 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto intermediate_passive_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_passive_var_ret; +using intermediate_untyped_ret = double; + + +#line 127 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto intermediate_untyped(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_untyped_ret; +using intermediate_default_init_ret = double; + + +#line 134 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto intermediate_default_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_default_init_ret; +using intermediate_no_init_ret = double; + + +#line 141 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto intermediate_no_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_no_init_ret; +using while_loop_ret = double; + + +#line 148 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto while_loop(cpp2::impl::in x, cpp2::impl::in y) -> while_loop_ret; +using do_while_loop_ret = double; + + +#line 157 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto do_while_loop(cpp2::impl::in x, cpp2::impl::in y) -> do_while_loop_ret; +using for_loop_ret = double; + + +#line 168 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto for_loop(cpp2::impl::in x, cpp2::impl::in y) -> for_loop_ret; +using type_outer_use_ret = double; + + +#line 182 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto type_outer_use(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_use_ret; +using type_outer_call_ret = double; + + +#line 189 "pure2-autodiff-higher-order.cpp2" + public: [[nodiscard]] static auto type_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_call_ret; +struct add_1_d_ret { double r; cpp2::taylor r_d; }; + + + public: [[nodiscard]] static auto add_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_1_d_ret; + +struct add_2_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto add_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_2_d_ret; + +struct sub_1_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto sub_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> sub_1_d_ret; + +struct sub_2_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto sub_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> sub_2_d_ret; + +struct add_sub_2_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto add_sub_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_sub_2_d_ret; + +struct mul_1_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto mul_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_1_d_ret; + +struct mul_2_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto mul_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_2_d_ret; + +struct div_1_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto div_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> div_1_d_ret; + +struct div_2_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto div_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> div_2_d_ret; + +struct mul_div_2_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto mul_div_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_div_2_d_ret; + +struct mul_add_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto mul_add_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_add_d_ret; + +struct add_mul_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto add_mul_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_mul_d_ret; + +struct prefix_add_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto prefix_add_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> prefix_add_d_ret; + +struct prefix_sub_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto prefix_sub_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> prefix_sub_d_ret; + +struct func_d_ret { double ret; cpp2::taylor ret_d; }; + +public: [[nodiscard]] static auto func_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_d_ret; + +struct func_call_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto func_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_call_d_ret; + +struct func_outer_call_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto func_outer_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_outer_call_d_ret; + +struct sin_call_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto sin_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> sin_call_d_ret; + +struct if_branch_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto if_branch_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> if_branch_d_ret; + +struct if_else_branch_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto if_else_branch_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> if_else_branch_d_ret; + +struct direct_return_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto direct_return_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> direct_return_d_ret; + +struct intermediate_var_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto intermediate_var_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_var_d_ret; + +struct intermediate_passive_var_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto intermediate_passive_var_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_passive_var_d_ret; + +struct intermediate_untyped_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto intermediate_untyped_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_untyped_d_ret; + +struct intermediate_default_init_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto intermediate_default_init_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_default_init_d_ret; + +struct intermediate_no_init_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto intermediate_no_init_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_no_init_d_ret; + +struct while_loop_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto while_loop_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> while_loop_d_ret; + +struct do_while_loop_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto do_while_loop_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> do_while_loop_d_ret; + +struct for_loop_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto for_loop_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> for_loop_d_ret; + +struct type_outer_use_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto type_outer_use_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> type_outer_use_d_ret; + +struct type_outer_call_d_ret { double r; cpp2::taylor r_d; }; + +public: [[nodiscard]] static auto type_outer_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> type_outer_call_d_ret; + + public: ad_test() = default; + public: ad_test(ad_test const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(ad_test const&) -> void = delete; + + +#line 195 "pure2-autodiff-higher-order.cpp2" +}; +} + +auto write_output(cpp2::impl::in func, cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d, auto const& ret) -> void; + +#line 207 "pure2-autodiff-higher-order.cpp2" +auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-autodiff-higher-order.cpp2" + +#line 4 "pure2-autodiff-higher-order.cpp2" +namespace ad_name { + +#line 6 "pure2-autodiff-higher-order.cpp2" +[[nodiscard]] auto func_outer(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_ret{ + cpp2::impl::deferred_init ret; +#line 7 "pure2-autodiff-higher-order.cpp2" + ret.construct(x + y); +return std::move(ret.value()); } + +#line 13 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto type_outer::add(cpp2::impl::in b) const& -> double{ + return a + b; + } + + [[nodiscard]] auto type_outer::add_d(cpp2::impl::in this_d, cpp2::impl::in b, cpp2::impl::in> b_d) const& -> add_d_ret{ + double r {}; + cpp2::taylor r_d {};r_d = this_d.a_d + b_d; + r = a + b; + return { std::move(r), std::move(r_d) }; } + + [[nodiscard]] auto func_outer_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_outer_d_ret{ + double ret {0.0}; + cpp2::taylor ret_d {0.0};ret_d = x_d + y_d; + ret = x + y; + return { std::move(ret), std::move(ret_d) }; + } + + + +#line 20 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret{ + cpp2::impl::deferred_init r; +#line 21 "pure2-autodiff-higher-order.cpp2" + r.construct(x + y); + return std::move(r.value()); } + +#line 24 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret{ + cpp2::impl::deferred_init r; +#line 25 "pure2-autodiff-higher-order.cpp2" + r.construct(x + y + x); + return std::move(r.value()); } + +#line 28 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret{ + cpp2::impl::deferred_init r; +#line 29 "pure2-autodiff-higher-order.cpp2" + r.construct(x - y); + return std::move(r.value()); } + +#line 32 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret{ + cpp2::impl::deferred_init r; +#line 33 "pure2-autodiff-higher-order.cpp2" + r.construct(x - y - x); + return std::move(r.value()); } + +#line 36 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret{ + cpp2::impl::deferred_init r; +#line 37 "pure2-autodiff-higher-order.cpp2" + r.construct(x + y - x); + return std::move(r.value()); } + +#line 40 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret{ + cpp2::impl::deferred_init r; +#line 41 "pure2-autodiff-higher-order.cpp2" + r.construct(x * y); + return std::move(r.value()); } + +#line 44 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret{ + cpp2::impl::deferred_init r; +#line 45 "pure2-autodiff-higher-order.cpp2" + r.construct(x * y * x); + return std::move(r.value()); } + +#line 48 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret{ + cpp2::impl::deferred_init r; +#line 49 "pure2-autodiff-higher-order.cpp2" + r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)); + return std::move(r.value()); } + +#line 52 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret{ + cpp2::impl::deferred_init r; +#line 53 "pure2-autodiff-higher-order.cpp2" + r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)); + return std::move(r.value()); } + +#line 56 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret{ + cpp2::impl::deferred_init r; +#line 57 "pure2-autodiff-higher-order.cpp2" + r.construct(x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)); + return std::move(r.value()); } + +#line 60 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret{ + cpp2::impl::deferred_init r; +#line 61 "pure2-autodiff-higher-order.cpp2" + r.construct(x * (x + y)); + return std::move(r.value()); } + +#line 64 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret{ + cpp2::impl::deferred_init r; +#line 65 "pure2-autodiff-higher-order.cpp2" + r.construct(x + x * y); + return std::move(r.value()); } + +#line 68 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::prefix_add(cpp2::impl::in x, cpp2::impl::in y) -> prefix_add_ret{ + cpp2::impl::deferred_init r; +#line 69 "pure2-autodiff-higher-order.cpp2" + r.construct(+x + y); + return std::move(r.value()); } + +#line 72 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::prefix_sub(cpp2::impl::in x, cpp2::impl::in y) -> prefix_sub_ret{ + cpp2::impl::deferred_init r; +#line 73 "pure2-autodiff-higher-order.cpp2" + r.construct(-x + y); + return std::move(r.value()); } + +#line 76 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret{ + cpp2::impl::deferred_init ret; +#line 77 "pure2-autodiff-higher-order.cpp2" + ret.construct(x + y); + return std::move(ret.value()); } + +#line 80 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret{ + cpp2::impl::deferred_init r; +#line 81 "pure2-autodiff-higher-order.cpp2" + r.construct(x * func(x, y)); + return std::move(r.value()); } + +#line 84 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret{ + cpp2::impl::deferred_init r; +#line 85 "pure2-autodiff-higher-order.cpp2" + r.construct(x * func_outer(x, y)); + return std::move(r.value()); } + +#line 88 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret{ + cpp2::impl::deferred_init r; +#line 89 "pure2-autodiff-higher-order.cpp2" + r.construct(sin(x - y)); + return std::move(r.value()); } + +#line 92 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::if_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_branch_ret{ + cpp2::impl::deferred_init r; +#line 93 "pure2-autodiff-higher-order.cpp2" + r.construct(x); + + if (cpp2::impl::cmp_less(x,0.0)) { + r.value() = y; + }return std::move(r.value()); + } + +#line 100 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::if_else_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_else_branch_ret{ + cpp2::impl::deferred_init r; +#line 101 "pure2-autodiff-higher-order.cpp2" + if (cpp2::impl::cmp_less(x,0.0)) { + r.construct(y); + } + else { + r.construct(x); + }return std::move(r.value()); + } + +#line 109 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::direct_return(cpp2::impl::in x, cpp2::impl::in y) -> double{ + return x + y; + } + +#line 113 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::intermediate_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_var_ret{ + cpp2::impl::deferred_init r; +#line 114 "pure2-autodiff-higher-order.cpp2" + double t {x + y}; + + r.construct(cpp2::move(t)); + return std::move(r.value()); } + +#line 119 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::intermediate_passive_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_passive_var_ret{ + cpp2::impl::deferred_init r; +#line 120 "pure2-autodiff-higher-order.cpp2" + int i {}; // TODO: Handle as passive when type information on call side is available. + r.construct(x + y); + i = 2; + + static_cast(cpp2::move(i)); + return std::move(r.value()); } + +#line 127 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::intermediate_untyped(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_untyped_ret{ + cpp2::impl::deferred_init r; +#line 128 "pure2-autodiff-higher-order.cpp2" + auto t {0.0}; + t = x + y; + + r.construct(cpp2::move(t)); + return std::move(r.value()); } + +#line 134 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::intermediate_default_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_default_init_ret{ + cpp2::impl::deferred_init r; +#line 135 "pure2-autodiff-higher-order.cpp2" + double t {}; + t = x + y; + + r.construct(cpp2::move(t)); + return std::move(r.value()); } + +#line 141 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::intermediate_no_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_no_init_ret{ + cpp2::impl::deferred_init r; +#line 142 "pure2-autodiff-higher-order.cpp2" + cpp2::impl::deferred_init t; + t.construct(x + y); + + r.construct(cpp2::move(t.value())); + return std::move(r.value()); } + +#line 148 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::while_loop(cpp2::impl::in x, cpp2::impl::in y) -> while_loop_ret{ + cpp2::impl::deferred_init r; +#line 149 "pure2-autodiff-higher-order.cpp2" + int i {0}; + + r.construct(x); + for( ; cpp2::impl::cmp_less(i,2); (i += 1) ) { + r.value() = r.value() + y; + }return std::move(r.value()); + } + +#line 157 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::do_while_loop(cpp2::impl::in x, cpp2::impl::in y) -> do_while_loop_ret{ + cpp2::impl::deferred_init r; +#line 158 "pure2-autodiff-higher-order.cpp2" + int i {0}; + + r.construct(x); + do { + r.value() = r.value() + y; + } while ( [&]{ + (i += 1) ; return true; }() && + cpp2::impl::cmp_less(i,2));return std::move(r.value()); + } + +#line 168 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::for_loop(cpp2::impl::in x, cpp2::impl::in y) -> for_loop_ret{ + cpp2::impl::deferred_init r; +#line 169 "pure2-autodiff-higher-order.cpp2" + std::vector v {}; + + CPP2_UFCS(push_back)(v, x); + CPP2_UFCS(push_back)(v, y); + + r.construct(0.0); + for ( + auto const& t : cpp2::move(v) ) + { + r.value() = r.value() + t; + }return std::move(r.value()); + } + +#line 182 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::type_outer_use(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_use_ret{ + cpp2::impl::deferred_init r; +#line 183 "pure2-autodiff-higher-order.cpp2" + type_outer t {}; + t.a = x; + + r.construct(cpp2::move(t).a + y); + return std::move(r.value()); } + +#line 189 "pure2-autodiff-higher-order.cpp2" + [[nodiscard]] auto ad_test::type_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_call_ret{ + cpp2::impl::deferred_init r; +#line 190 "pure2-autodiff-higher-order.cpp2" + type_outer t {}; + t.a = x; + + r.construct(CPP2_UFCS(add)(cpp2::move(t), y)); + return std::move(r.value()); } + + [[nodiscard]] auto ad_test::add_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_1_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = x_d + y_d; + r = x + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::add_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_2_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = x_d + y_d + x_d; + r = x + y + x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::sub_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> sub_1_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = x_d - y_d; + r = x - y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::sub_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> sub_2_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = x_d - y_d - x_d; + r = x - y - x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::add_sub_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_sub_2_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = x_d + y_d - x_d; + r = x + y - x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_1_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = x_d.mul(y_d, x, y); + r = x * y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_2_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +auto temp_1_d {x_d.mul(y_d, x, y)}; + + auto temp_1 {x * y}; + r_d = cpp2::move(temp_1_d).mul(x_d, temp_1, x); + r = cpp2::move(temp_1) * x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::div_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> div_1_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = CPP2_UFCS(div)(x_d, y_d, x, y); + r = x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::div_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> div_2_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +auto temp_1_d {CPP2_UFCS(div)(x_d, y_d, x, y)}; + + auto temp_1 {x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)}; + r_d = CPP2_UFCS(div)(cpp2::move(temp_1_d), y_d, temp_1, y); + r = cpp2::move(temp_1) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(cpp2::move(temp_1)),y); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_div_2_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_div_2_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +auto temp_1_d {x_d.mul(y_d, x, y)}; + + auto temp_1 {x * y}; + r_d = CPP2_UFCS(div)(cpp2::move(temp_1_d), x_d, temp_1, x); + r = cpp2::move(temp_1) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(cpp2::move(temp_1)),x); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_add_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> mul_add_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::taylor temp_1_d {x_d + y_d}; + + double temp_1 {x + y}; + r_d = x_d.mul(cpp2::move(temp_1_d), x, temp_1); + r = x * cpp2::move(temp_1); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::add_mul_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_mul_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::taylor temp_1_d {x_d.mul(y_d, x, y)}; + + double temp_1 {x * y}; + r_d = x_d + cpp2::move(temp_1_d); + r = x + cpp2::move(temp_1); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::prefix_add_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> prefix_add_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::taylor temp_1_d {+x_d}; + + double temp_1 {+x}; + r_d = cpp2::move(temp_1_d) + y_d; + r = cpp2::move(temp_1) + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::prefix_sub_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> prefix_sub_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::taylor temp_1_d {-x_d}; + + double temp_1 {-x}; + r_d = cpp2::move(temp_1_d) + y_d; + r = cpp2::move(temp_1) + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::func_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_d_ret{ + double ret {0.0}; + cpp2::taylor ret_d {0.0};ret_d = x_d + y_d; + ret = x + y; + return { std::move(ret), std::move(ret_d) }; + } + + [[nodiscard]] auto ad_test::func_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_call_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +auto temp_1 {func_d(x, x_d, y, y_d)}; + + cpp2::taylor temp_2_d {cpp2::move(temp_1).ret_d}; + + double temp_2 {func(x, y)}; + r_d = x_d.mul(cpp2::move(temp_2_d), x, temp_2); + r = x * cpp2::move(temp_2); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::func_outer_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> func_outer_call_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +auto temp_1 {func_outer_d(x, x_d, y, y_d)}; + + cpp2::taylor temp_2_d {cpp2::move(temp_1).ret_d}; + + double temp_2 {func_outer(x, y)}; + r_d = x_d.mul(cpp2::move(temp_2_d), x, temp_2); + r = x * cpp2::move(temp_2); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::sin_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> sin_call_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::taylor temp_1_d {x_d - y_d}; + + double temp_1 {x - y}; + r_d = CPP2_UFCS(sin)(cpp2::move(temp_1_d), temp_1); + r = sin(cpp2::move(temp_1)); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::if_branch_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> if_branch_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};r_d = x_d; + r = x; + if (cpp2::impl::cmp_less(x,0.0)) { + r_d = y_d; + r = y; + } + else { + } + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::if_else_branch_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> if_else_branch_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0};if (cpp2::impl::cmp_less(x,0.0)) { + r_d = y_d; + r = y; + } + else { + r_d = x_d; + r = x; + } + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::direct_return_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> direct_return_d_ret{ + double r {}; + cpp2::taylor r_d {};r_d = x_d + y_d; + r = x + y; + return { std::move(r), std::move(r_d) }; } + + [[nodiscard]] auto ad_test::intermediate_var_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_var_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::taylor t_d {x_d + y_d}; + + double t {x + y}; + r_d = cpp2::move(t_d); + r = cpp2::move(t); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_passive_var_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_passive_var_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +int i {}; + r_d = x_d + y_d; + r = x + y; + i = 2; + static_cast(cpp2::move(i)); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_untyped_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_untyped_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +auto t_d {cpp2::taylor()}; + + auto t {0.0}; + t_d = x_d + y_d; + t = x + y; + r_d = cpp2::move(t_d); + r = cpp2::move(t); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_default_init_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_default_init_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::taylor t_d {}; + + double t {}; + t_d = x_d + y_d; + t = x + y; + r_d = cpp2::move(t_d); + r = cpp2::move(t); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_no_init_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> intermediate_no_init_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +cpp2::impl::deferred_init> t_d; + + cpp2::impl::deferred_init t; + t_d.construct(x_d + y_d); + t.construct(x + y); + r_d = cpp2::move(t_d.value()); + r = cpp2::move(t.value()); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::while_loop_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> while_loop_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +int i {0}; + r_d = x_d; + r = x; + for( ; cpp2::impl::cmp_less(i,2); (i += 1) ) { + r_d = r_d + y_d; + r = r + y; + } + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::do_while_loop_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> do_while_loop_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +int i {0}; + r_d = x_d; + r = x; + do { + r_d = r_d + y_d; + r = r + y; + } + while ( [&]{ + (i += 1) + ; return true; }() && + cpp2::impl::cmp_less(i,2) + ); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::for_loop_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> for_loop_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +std::vector> v_d {}; + + std::vector v {}; + CPP2_UFCS(push_back)(v_d, x_d); + CPP2_UFCS(push_back)(v, x); + CPP2_UFCS(push_back)(v_d, y_d); + CPP2_UFCS(push_back)(v, y); + r_d = { }; + r = 0.0; +{ +auto t_d_iter{CPP2_UFCS(begin)(cpp2::move(v_d))}; + for ( auto const& t : cpp2::move(v) ) { do { +{ +auto const& t_d{*cpp2::impl::assert_not_null(t_d_iter)}; + { + r_d = r_d + t_d; + r = r + t; + } +} + } + while (false); (++t_d_iter); } +} + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::type_outer_use_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> type_outer_use_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +type_outer_d t_d {}; + + type_outer t {}; + t_d.a_d = x_d; + t.a = x; + + cpp2::taylor temp_1_d {cpp2::move(t_d).a_d}; + + double temp_1 {cpp2::move(t).a}; + r_d = cpp2::move(temp_1_d) + y_d; + r = cpp2::move(temp_1) + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::type_outer_call_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> type_outer_call_d_ret{ + double r {0.0}; + cpp2::taylor r_d {0.0}; +type_outer_d t_d {}; + + type_outer t {}; + t_d.a_d = x_d; + t.a = x; + + auto temp_1 {CPP2_UFCS(add_d)(t, cpp2::move(t_d), y, y_d)}; + r_d = cpp2::move(temp_1).r_d; + r = CPP2_UFCS(add)(cpp2::move(t), y); + return { std::move(r), std::move(r_d) }; + } + +#line 196 "pure2-autodiff-higher-order.cpp2" +} + +#line 198 "pure2-autodiff-higher-order.cpp2" +auto write_output(cpp2::impl::in func, cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d, auto const& ret) -> void{ + std::cout << "diff(" + cpp2::to_string(func) + ") at (x = " + cpp2::to_string(x) + ", x_d = " + cpp2::to_string(x_d) + ", y = " + cpp2::to_string(y) + ", y_d = " + cpp2::to_string(y_d) + "):" << std::endl; + std::cout << " r = " + cpp2::to_string(ret.r) + "" << std::endl; +{ +auto i{1}; + +#line 202 "pure2-autodiff-higher-order.cpp2" + for( ; cpp2::impl::cmp_less_eq(i,ad_order); i += 1 ) { + std::cout << " d" + cpp2::to_string(i) + " = " + cpp2::to_string(CPP2_ASSERT_IN_BOUNDS(ret.r_d, i)) + "" << std::endl; + } +} +#line 205 "pure2-autodiff-higher-order.cpp2" +} + +#line 207 "pure2-autodiff-higher-order.cpp2" +auto main() -> int{ + +#line 210 "pure2-autodiff-higher-order.cpp2" + double x {2.0}; + ad_type x_d {1.0}; + double y {3.0}; + ad_type y_d {2.0}; + + write_output("x + y", x, x_d, y, y_d, ad_name::ad_test::add_1_d(x, x_d, y, y_d)); + write_output("x + y + x", x, x_d, y, y_d, ad_name::ad_test::add_2_d(x, x_d, y, y_d)); + write_output("x - y", x, x_d, y, y_d, ad_name::ad_test::sub_1_d(x, x_d, y, y_d)); + write_output("x - y - x", x, x_d, y, y_d, ad_name::ad_test::sub_2_d(x, x_d, y, y_d)); + write_output("x + y - x", x, x_d, y, y_d, ad_name::ad_test::add_sub_2_d(x, x_d, y, y_d)); + write_output("x * y", x, x_d, y, y_d, ad_name::ad_test::mul_1_d(x, x_d, y, y_d)); + write_output("x * y * x", x, x_d, y, y_d, ad_name::ad_test::mul_2_d(x, x_d, y, y_d)); + write_output("x / y", x, x_d, y, y_d, ad_name::ad_test::div_1_d(x, x_d, y, y_d)); + write_output("x / y / y", x, x_d, y, y_d, ad_name::ad_test::div_2_d(x, x_d, y, y_d)); + write_output("x * y / x", x, x_d, y, y_d, ad_name::ad_test::mul_div_2_d(x, x_d, y, y_d)); + write_output("x * (x + y)", x, x_d, y, y_d, ad_name::ad_test::mul_add_d(x, x_d, y, y_d)); + write_output("x + x * y", x, x_d, y, y_d, ad_name::ad_test::add_mul_d(x, x_d, y, y_d)); + write_output("+x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_add_d(x, x_d, y, y_d)); + write_output("-x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_sub_d(x, x_d, y, y_d)); + write_output("x * func(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_call_d(x, x_d, y, y_d)); + write_output("x * func_outer(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_outer_call_d(x, x_d, y, y_d)); + write_output("sin(x - y)", x, x_d, y, y_d, ad_name::ad_test::sin_call_d(x, x_d, y, y_d)); + write_output("if branch", x, x_d, y, y_d, ad_name::ad_test::if_branch_d(x, x_d, y, y_d)); + write_output("if else branch", x, x_d, y, y_d, ad_name::ad_test::if_else_branch_d(x, x_d, y, y_d)); + write_output("direct return", x, x_d, y, y_d, ad_name::ad_test::direct_return_d(x, x_d, y, y_d)); + write_output("intermediate var", x, x_d, y, y_d, ad_name::ad_test::intermediate_var_d(x, x_d, y, y_d)); + write_output("intermediate passive var", x, x_d, y, y_d, ad_name::ad_test::intermediate_passive_var_d(x, x_d, y, y_d)); + write_output("intermediate untyped", x, x_d, y, y_d, ad_name::ad_test::intermediate_untyped_d(x, x_d, y, y_d)); + write_output("intermediate default init", x, x_d, y, y_d, ad_name::ad_test::intermediate_default_init_d(x, x_d, y, y_d)); + write_output("intermediate no init", x, x_d, y, y_d, ad_name::ad_test::intermediate_no_init_d(x, x_d, y, y_d)); + write_output("while loop", x, x_d, y, y_d, ad_name::ad_test::while_loop_d(x, x_d, y, y_d)); + write_output("do while loop", x, x_d, y, y_d, ad_name::ad_test::do_while_loop_d(x, x_d, y, y_d)); + write_output("for loop", x, x_d, y, y_d, ad_name::ad_test::for_loop_d(x, x_d, y, y_d)); + write_output("tye_outer.a + y", x, x_d, y, y_d, ad_name::ad_test::type_outer_use_d(x, x_d, y, y_d)); + write_output("type_outer.add(y)", x, x_d, y, y_d, ad_name::ad_test::type_outer_call_d(cpp2::move(x), cpp2::move(x_d), cpp2::move(y), cpp2::move(y_d))); +} + diff --git a/regression-tests/test-results/pure2-autodiff-higher-order.cpp2.output b/regression-tests/test-results/pure2-autodiff-higher-order.cpp2.output new file mode 100644 index 000000000..17c5f140c --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff-higher-order.cpp2.output @@ -0,0 +1,893 @@ +pure2-autodiff-higher-order.cpp2... + +ad_test:/* @autodiff<"order=6"> @print */ type = +{ + add_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y; + return; + } + + add_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y + x; + return; + } + + sub_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x - y; + return; + } + + sub_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x - y - x; + return; + } + + add_sub_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y - x; + return; + } + + mul_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y; + return; + } + + mul_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y * x; + return; + } + + div_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x / y; + return; + } + + div_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x / y / y; + return; + } + + mul_div_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y / x; + return; + } + + mul_add:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * (x + y); + return; + } + + add_mul:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + x * y; + return; + } + + prefix_add:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = +x + y; + return; + } + + prefix_sub:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = -x + y; + return; + } + + func:( + in x: double, + in y: double, + ) -> (out ret: double, ) = + { + ret = x + y; + return; + } + + func_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * func(x, y); + return; + } + + func_outer_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * func_outer(x, y); + return; + } + + sin_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = sin(x - y); + return; + } + + if_branch:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x; + if x < 0.0 + { + r = y; + } + return; + } + + if_else_branch:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + if x < 0.0 + { + r = y; + } + else + { + r = x; + } + return; + } + + direct_return:( + in x: double, + in y: double, + ) -> move double = + { + return x + y; + } + + intermediate_var:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: double = x + y; + r = t; + return; + } + + intermediate_passive_var:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + i: int = (); + r = x + y; + i = 2; + _ = i; + return; + } + + intermediate_untyped:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: _ = 0.0; + t = x + y; + r = t; + return; + } + + intermediate_default_init:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: double = (); + t = x + y; + r = t; + return; + } + + intermediate_no_init:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: double; + t = x + y; + r = t; + return; + } + + while_loop:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + i: int = 0; + r = x; + while i < 2 + next (i += 1) + { + r = r + y; + } + return; + } + + do_while_loop:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + i: int = 0; + r = x; + do + { + r = r + y; + } + next (i += 1) + while i < 2; + return; + } + + for_loop:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + v: std::vector = (); + v.push_back(x); + v.push_back(y); + r = 0.0; + for v + do (in t: _) + { + r = r + t; + } + return; + } + + type_outer_use:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: type_outer = (); + t.a = x; + r = t.a + y; + return; + } + + type_outer_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: type_outer = (); + t.a = x; + r = t.add(y); + return; + } + + add_1_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d + y_d; + r = x + y; + return; + } + + add_2_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d + y_d + x_d; + r = x + y + x; + return; + } + + sub_1_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d - y_d; + r = x - y; + return; + } + + sub_2_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d - y_d - x_d; + r = x - y - x; + return; + } + + add_sub_2_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d + y_d - x_d; + r = x + y - x; + return; + } + + mul_1_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d..mul(y_d, x, y); + r = x * y; + return; + } + + mul_2_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: _ = x_d..mul(y_d, x, y); + temp_1: _ = x * y; + r_d = temp_1_d..mul(x_d, temp_1, x); + r = temp_1 * x; + return; + } + + div_1_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d.div(y_d, x, y); + r = x / y; + return; + } + + div_2_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: _ = x_d.div(y_d, x, y); + temp_1: _ = x / y; + r_d = temp_1_d.div(y_d, temp_1, y); + r = temp_1 / y; + return; + } + + mul_div_2_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: _ = x_d..mul(y_d, x, y); + temp_1: _ = x * y; + r_d = temp_1_d.div(x_d, temp_1, x); + r = temp_1 / x; + return; + } + + mul_add_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: cpp2::taylor = x_d + y_d; + temp_1: double = x + y; + r_d = x_d..mul(temp_1_d, x, temp_1); + r = x * temp_1; + return; + } + + add_mul_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: cpp2::taylor = x_d..mul(y_d, x, y); + temp_1: double = x * y; + r_d = x_d + temp_1_d; + r = x + temp_1; + return; + } + + prefix_add_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: cpp2::taylor = +x_d; + temp_1: double = +x; + r_d = temp_1_d + y_d; + r = temp_1 + y; + return; + } + + prefix_sub_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: cpp2::taylor = -x_d; + temp_1: double = -x; + r_d = temp_1_d + y_d; + r = temp_1 + y; + return; + } + + func_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out ret: double = 0.0, + out ret_d: cpp2::taylor = 0.0, + ) = + { + ret_d = x_d + y_d; + ret = x + y; + return; + } + + func_call_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1: _ = func_d(x, x_d, y, y_d); + temp_2_d: cpp2::taylor = temp_1.ret_d; + temp_2: double = func(x, y); + r_d = x_d..mul(temp_2_d, x, temp_2); + r = x * temp_2; + return; + } + + func_outer_call_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1: _ = func_outer_d(x, x_d, y, y_d); + temp_2_d: cpp2::taylor = temp_1.ret_d; + temp_2: double = func_outer(x, y); + r_d = x_d..mul(temp_2_d, x, temp_2); + r = x * temp_2; + return; + } + + sin_call_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + temp_1_d: cpp2::taylor = x_d - y_d; + temp_1: double = x - y; + r_d = temp_1_d.sin(temp_1); + r = sin(temp_1); + return; + } + + if_branch_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + r_d = x_d; + r = x; + if x < 0.0 + { + r_d = y_d; + r = y; + } + else + { + } + return; + } + + if_else_branch_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + if x < 0.0 + { + r_d = y_d; + r = y; + } + else + { + r_d = x_d; + r = x; + } + return; + } + + direct_return_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = (), + out r_d: cpp2::taylor = (), + ) = + { + r_d = x_d + y_d; + r = x + y; + return; + } + + intermediate_var_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + t_d: cpp2::taylor = x_d + y_d; + t: double = x + y; + r_d = t_d; + r = t; + return; + } + + intermediate_passive_var_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + i: int = (); + r_d = x_d + y_d; + r = x + y; + i = 2; + _ = i; + return; + } + + intermediate_untyped_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + t_d: _ = cpp2::taylor(); + t: _ = 0.0; + t_d = x_d + y_d; + t = x + y; + r_d = t_d; + r = t; + return; + } + + intermediate_default_init_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + t_d: cpp2::taylor = (); + t: double = (); + t_d = x_d + y_d; + t = x + y; + r_d = t_d; + r = t; + return; + } + + intermediate_no_init_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + t_d: cpp2::taylor; + t: double; + t_d = x_d + y_d; + t = x + y; + r_d = t_d; + r = t; + return; + } + + while_loop_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + i: int = 0; + r_d = x_d; + r = x; + while i < 2 + next (i += 1) + { + r_d = r_d + y_d; + r = r + y; + } + return; + } + + do_while_loop_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + i: int = 0; + r_d = x_d; + r = x; + do + { + r_d = r_d + y_d; + r = r + y; + } + next (i += 1) + while i < 2; + return; + } + + for_loop_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + v_d: std::vector> = (); + v: std::vector = (); + v_d.push_back(x_d); + v.push_back(x); + v_d.push_back(y_d); + v.push_back(y); + r_d = (); + r = 0.0; + (copy t_d_iter: _ = v_d.begin(), ) + for v + next (t_d_iter++) + do (in t: _) + { + (in t_d: _ = t_d_iter*, ) + { + r_d = r_d + t_d; + r = r + t; + } + } + return; + } + + type_outer_use_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + t_d: type_outer_d = (); + t: type_outer = (); + t_d.a_d = x_d; + t.a = x; + temp_1_d: cpp2::taylor = t_d.a_d; + temp_1: double = t.a; + r_d = temp_1_d + y_d; + r = temp_1 + y; + return; + } + + type_outer_call_d:( + in x: double, + in x_d: cpp2::taylor, + in y: double, + in y_d: cpp2::taylor, + ) -> ( + out r: double = 0.0, + out r_d: cpp2::taylor = 0.0, + ) = + { + t_d: type_outer_d = (); + t: type_outer = (); + t_d.a_d = x_d; + t.a = x; + temp_1: _ = t.add_d(t_d, y, y_d); + r_d = temp_1.r_d; + r = t.add(y); + return; + } +} + ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-autodiff.cpp b/regression-tests/test-results/pure2-autodiff.cpp new file mode 100644 index 000000000..f4c551bd4 --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff.cpp @@ -0,0 +1,1693 @@ + +#define CPP2_IMPORT_STD Yes +#include "cpp2ad_stack.h" +#include "cpp2taylor.h" + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-autodiff.cpp2" +namespace ad_name { + +#line 7 "pure2-autodiff.cpp2" +class type_outer; + + class type_outer_d; + + +#line 15 "pure2-autodiff.cpp2" +class ad_test; + +#line 195 "pure2-autodiff.cpp2" +class ad_test_reverse; + +#line 261 "pure2-autodiff.cpp2" +} + +class ad_test_twice; + + +#line 280 "pure2-autodiff.cpp2" +class ad_test_2; + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-autodiff.cpp2" +namespace ad_name { +using func_outer_ret = double; + + +#line 3 "pure2-autodiff.cpp2" +[[nodiscard]] auto func_outer(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_ret; + +#line 7 "pure2-autodiff.cpp2" +class type_outer { + public: double a {0.0}; + + public: [[nodiscard]] auto add(cpp2::impl::in b) const& -> double; +struct add_d_ret { double r; double r_d; }; + + + public: [[nodiscard]] auto add_d(cpp2::impl::in this_d, cpp2::impl::in b, cpp2::impl::in b_d) const& -> add_d_ret; + + public: type_outer() = default; + public: type_outer(type_outer const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(type_outer const&) -> void = delete; + + +#line 13 "pure2-autodiff.cpp2" +}; + +struct func_outer_d_ret { double ret; double ret_d; }; + + +[[nodiscard]] auto func_outer_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_outer_d_ret; +class type_outer_d { +public: double a_d {}; + public: type_outer_d() = default; + public: type_outer_d(type_outer_d const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(type_outer_d const&) -> void = delete; + +}; + +#line 15 "pure2-autodiff.cpp2" +class ad_test { +using add_1_ret = double; + + +#line 17 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret; +using add_2_ret = double; + + +#line 21 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret; +using sub_1_ret = double; + + +#line 25 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret; +using sub_2_ret = double; + + +#line 29 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret; +using add_sub_2_ret = double; + + +#line 33 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret; +using mul_1_ret = double; + + +#line 37 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret; +using mul_2_ret = double; + + +#line 41 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret; +using div_1_ret = double; + + +#line 45 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret; +using div_2_ret = double; + + +#line 49 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret; +using mul_div_2_ret = double; + + +#line 53 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret; +using mul_add_ret = double; + + +#line 57 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret; +using add_mul_ret = double; + + +#line 61 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret; +using prefix_add_ret = double; + + +#line 65 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto prefix_add(cpp2::impl::in x, cpp2::impl::in y) -> prefix_add_ret; +using prefix_sub_ret = double; + + +#line 69 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto prefix_sub(cpp2::impl::in x, cpp2::impl::in y) -> prefix_sub_ret; +using func_ret = double; + + +#line 73 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret; +using func_call_ret = double; + + +#line 77 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret; +using func_outer_call_ret = double; + + +#line 81 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret; +using sin_call_ret = double; + + +#line 85 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret; +using if_branch_ret = double; + + +#line 89 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto if_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_branch_ret; +using if_else_branch_ret = double; + + +#line 97 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto if_else_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_else_branch_ret; + +#line 106 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto direct_return(cpp2::impl::in x, cpp2::impl::in y) -> double; +using intermediate_var_ret = double; + + +#line 110 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto intermediate_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_var_ret; +using intermediate_passive_var_ret = double; + + +#line 116 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto intermediate_passive_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_passive_var_ret; +using intermediate_untyped_ret = double; + + +#line 124 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto intermediate_untyped(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_untyped_ret; +using intermediate_default_init_ret = double; + + +#line 131 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto intermediate_default_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_default_init_ret; +using intermediate_no_init_ret = double; + + +#line 138 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto intermediate_no_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_no_init_ret; +using while_loop_ret = double; + + +#line 145 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto while_loop(cpp2::impl::in x, cpp2::impl::in y) -> while_loop_ret; +using do_while_loop_ret = double; + + +#line 155 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto do_while_loop(cpp2::impl::in x, cpp2::impl::in y) -> do_while_loop_ret; +using for_loop_ret = double; + + +#line 166 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto for_loop(cpp2::impl::in x, cpp2::impl::in y) -> for_loop_ret; +using type_outer_use_ret = double; + + +#line 180 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto type_outer_use(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_use_ret; +using type_outer_call_ret = double; + + +#line 187 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto type_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_call_ret; +struct add_1_d_ret { double r; double r_d; }; + + + public: [[nodiscard]] static auto add_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_1_d_ret; + +struct add_2_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto add_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_2_d_ret; + +struct sub_1_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto sub_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> sub_1_d_ret; + +struct sub_2_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto sub_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> sub_2_d_ret; + +struct add_sub_2_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto add_sub_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_sub_2_d_ret; + +struct mul_1_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto mul_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_1_d_ret; + +struct mul_2_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto mul_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_2_d_ret; + +struct div_1_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto div_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> div_1_d_ret; + +struct div_2_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto div_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> div_2_d_ret; + +struct mul_div_2_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto mul_div_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_div_2_d_ret; + +struct mul_add_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto mul_add_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_add_d_ret; + +struct add_mul_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto add_mul_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_mul_d_ret; + +struct prefix_add_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto prefix_add_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> prefix_add_d_ret; + +struct prefix_sub_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto prefix_sub_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> prefix_sub_d_ret; + +struct func_d_ret { double ret; double ret_d; }; + +public: [[nodiscard]] static auto func_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_d_ret; + +struct func_call_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto func_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_call_d_ret; + +struct func_outer_call_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto func_outer_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_outer_call_d_ret; + +struct sin_call_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto sin_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> sin_call_d_ret; + +struct if_branch_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto if_branch_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> if_branch_d_ret; + +struct if_else_branch_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto if_else_branch_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> if_else_branch_d_ret; + +struct direct_return_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto direct_return_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> direct_return_d_ret; + +struct intermediate_var_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto intermediate_var_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_var_d_ret; + +struct intermediate_passive_var_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto intermediate_passive_var_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_passive_var_d_ret; + +struct intermediate_untyped_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto intermediate_untyped_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_untyped_d_ret; + +struct intermediate_default_init_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto intermediate_default_init_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_default_init_d_ret; + +struct intermediate_no_init_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto intermediate_no_init_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_no_init_d_ret; + +struct while_loop_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto while_loop_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> while_loop_d_ret; + +struct do_while_loop_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto do_while_loop_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> do_while_loop_d_ret; + +struct for_loop_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto for_loop_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> for_loop_d_ret; + +struct type_outer_use_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto type_outer_use_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> type_outer_use_d_ret; + +struct type_outer_call_d_ret { double r; double r_d; }; + +public: [[nodiscard]] static auto type_outer_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> type_outer_call_d_ret; + + public: ad_test() = default; + public: ad_test(ad_test const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(ad_test const&) -> void = delete; + + +#line 193 "pure2-autodiff.cpp2" +}; + +using func_outer_b_ret = double; + +[[nodiscard]] auto func_outer_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& ret_b) -> func_outer_b_ret; + +#line 195 "pure2-autodiff.cpp2" +class ad_test_reverse { +using add_1_ret = double; + + +#line 197 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret; +using add_2_ret = double; + + +#line 201 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret; +using sub_1_ret = double; + + +#line 205 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret; +using sub_2_ret = double; + + +#line 209 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret; +using add_sub_2_ret = double; + + +#line 213 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret; +using mul_1_ret = double; + + +#line 217 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret; +using mul_2_ret = double; + + +#line 221 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret; +using div_1_ret = double; + + +#line 225 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret; +using div_2_ret = double; + + +#line 229 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret; +using mul_div_2_ret = double; + + +#line 233 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret; +using mul_add_ret = double; + + +#line 237 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret; +using add_mul_ret = double; + + +#line 241 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret; +using sin_call_ret = double; + + +#line 245 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret; +using func_ret = double; + + +#line 249 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret; +using func_call_ret = double; + + +#line 253 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret; +using func_outer_call_ret = double; + + +#line 257 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret; +using add_1_b_ret = double; + + public: [[nodiscard]] static auto add_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_1_b_ret; + +using add_2_b_ret = double; +public: [[nodiscard]] static auto add_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_2_b_ret; + +using sub_1_b_ret = double; +public: [[nodiscard]] static auto sub_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> sub_1_b_ret; + +using sub_2_b_ret = double; +public: [[nodiscard]] static auto sub_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> sub_2_b_ret; + +using add_sub_2_b_ret = double; +public: [[nodiscard]] static auto add_sub_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_sub_2_b_ret; + +using mul_1_b_ret = double; +public: [[nodiscard]] static auto mul_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_1_b_ret; + +using mul_2_b_ret = double; +public: [[nodiscard]] static auto mul_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_2_b_ret; + +using div_1_b_ret = double; +public: [[nodiscard]] static auto div_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> div_1_b_ret; + +using div_2_b_ret = double; +public: [[nodiscard]] static auto div_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> div_2_b_ret; + +using mul_div_2_b_ret = double; +public: [[nodiscard]] static auto mul_div_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_div_2_b_ret; + +using mul_add_b_ret = double; +public: [[nodiscard]] static auto mul_add_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_add_b_ret; + +using add_mul_b_ret = double; +public: [[nodiscard]] static auto add_mul_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_mul_b_ret; + +using sin_call_b_ret = double; +public: [[nodiscard]] static auto sin_call_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> sin_call_b_ret; + +using func_b_ret = double; +public: [[nodiscard]] static auto func_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& ret_b) -> func_b_ret; + +using func_call_b_ret = double; +public: [[nodiscard]] static auto func_call_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> func_call_b_ret; + +using func_outer_call_b_ret = double; +public: [[nodiscard]] static auto func_outer_call_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> func_outer_call_b_ret; + + public: ad_test_reverse() = default; + public: ad_test_reverse(ad_test_reverse const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(ad_test_reverse const&) -> void = delete; + + +#line 260 "pure2-autodiff.cpp2" +}; +} + +class ad_test_twice { +using mul_1_ret = double; + +#line 264 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto mul_1(cpp2::impl::in x) -> mul_1_ret; +struct mul_1_d_ret { double r; double r_d; }; + + + public: [[nodiscard]] static auto mul_1_d(cpp2::impl::in x, cpp2::impl::in x_d) -> mul_1_d_ret; + +struct mul_1_d2_ret { double r; double r_d2; }; + +public: [[nodiscard]] static auto mul_1_d2(cpp2::impl::in x, cpp2::impl::in x_d2) -> mul_1_d2_ret; + +struct mul_1_d_d2_ret { double r; double r_d2; double r_d; double r_d_d2; }; + +public: [[nodiscard]] static auto mul_1_d_d2(cpp2::impl::in x, cpp2::impl::in x_d2, cpp2::impl::in x_d, cpp2::impl::in x_d_d2) -> mul_1_d_d2_ret; + + public: ad_test_twice() = default; + public: ad_test_twice(ad_test_twice const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(ad_test_twice const&) -> void = delete; + + +#line 267 "pure2-autodiff.cpp2" +}; + +auto write_output(cpp2::impl::in func, cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d, auto const& ret) -> void; + +#line 273 "pure2-autodiff.cpp2" +auto write_output_reverse(cpp2::impl::in func, cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b, auto const& ret) -> void; + +#line 280 "pure2-autodiff.cpp2" +class ad_test_2 { +using f_ret = double; + +#line 281 "pure2-autodiff.cpp2" + public: [[nodiscard]] static auto f(cpp2::impl::in x) -> f_ret; +struct f_d_ret { double y; cpp2::taylor y_d; }; + + + public: [[nodiscard]] static auto f_d(cpp2::impl::in x, cpp2::impl::in> x_d) -> f_d_ret; + + public: ad_test_2() = default; + public: ad_test_2(ad_test_2 const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(ad_test_2 const&) -> void = delete; + + +#line 295 "pure2-autodiff.cpp2" +}; + +auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-autodiff.cpp2" +namespace ad_name { + +#line 3 "pure2-autodiff.cpp2" +[[nodiscard]] auto func_outer(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_ret{ + cpp2::impl::deferred_init ret; +#line 4 "pure2-autodiff.cpp2" + ret.construct(x + y); +return std::move(ret.value()); } + +#line 10 "pure2-autodiff.cpp2" + [[nodiscard]] auto type_outer::add(cpp2::impl::in b) const& -> double{ + return a + b; + } + + [[nodiscard]] auto type_outer::add_d(cpp2::impl::in this_d, cpp2::impl::in b, cpp2::impl::in b_d) const& -> add_d_ret{ + double r {}; + double r_d {};r_d = this_d.a_d + b_d; + r = a + b; + return { std::move(r), std::move(r_d) }; } + + [[nodiscard]] auto func_outer_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_outer_d_ret{ + double ret {0.0}; + double ret_d {0.0};ret_d = x_d + y_d; + ret = x + y; + return { std::move(ret), std::move(ret_d) }; + } + + + +#line 17 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret{ + cpp2::impl::deferred_init r; +#line 18 "pure2-autodiff.cpp2" + r.construct(x + y); + return std::move(r.value()); } + +#line 21 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret{ + cpp2::impl::deferred_init r; +#line 22 "pure2-autodiff.cpp2" + r.construct(x + y + x); + return std::move(r.value()); } + +#line 25 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret{ + cpp2::impl::deferred_init r; +#line 26 "pure2-autodiff.cpp2" + r.construct(x - y); + return std::move(r.value()); } + +#line 29 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret{ + cpp2::impl::deferred_init r; +#line 30 "pure2-autodiff.cpp2" + r.construct(x - y - x); + return std::move(r.value()); } + +#line 33 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret{ + cpp2::impl::deferred_init r; +#line 34 "pure2-autodiff.cpp2" + r.construct(x + y - x); + return std::move(r.value()); } + +#line 37 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret{ + cpp2::impl::deferred_init r; +#line 38 "pure2-autodiff.cpp2" + r.construct(x * y); + return std::move(r.value()); } + +#line 41 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret{ + cpp2::impl::deferred_init r; +#line 42 "pure2-autodiff.cpp2" + r.construct(x * y * x); + return std::move(r.value()); } + +#line 45 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret{ + cpp2::impl::deferred_init r; +#line 46 "pure2-autodiff.cpp2" + r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)); + return std::move(r.value()); } + +#line 49 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret{ + cpp2::impl::deferred_init r; +#line 50 "pure2-autodiff.cpp2" + r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)); + return std::move(r.value()); } + +#line 53 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret{ + cpp2::impl::deferred_init r; +#line 54 "pure2-autodiff.cpp2" + r.construct(x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)); + return std::move(r.value()); } + +#line 57 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret{ + cpp2::impl::deferred_init r; +#line 58 "pure2-autodiff.cpp2" + r.construct(x * (x + y)); + return std::move(r.value()); } + +#line 61 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret{ + cpp2::impl::deferred_init r; +#line 62 "pure2-autodiff.cpp2" + r.construct(x + x * y); + return std::move(r.value()); } + +#line 65 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::prefix_add(cpp2::impl::in x, cpp2::impl::in y) -> prefix_add_ret{ + cpp2::impl::deferred_init r; +#line 66 "pure2-autodiff.cpp2" + r.construct(+x + y); + return std::move(r.value()); } + +#line 69 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::prefix_sub(cpp2::impl::in x, cpp2::impl::in y) -> prefix_sub_ret{ + cpp2::impl::deferred_init r; +#line 70 "pure2-autodiff.cpp2" + r.construct(-x + y); + return std::move(r.value()); } + +#line 73 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret{ + cpp2::impl::deferred_init ret; +#line 74 "pure2-autodiff.cpp2" + ret.construct(x + y); + return std::move(ret.value()); } + +#line 77 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret{ + cpp2::impl::deferred_init r; +#line 78 "pure2-autodiff.cpp2" + r.construct(x * func(x, y)); + return std::move(r.value()); } + +#line 81 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret{ + cpp2::impl::deferred_init r; +#line 82 "pure2-autodiff.cpp2" + r.construct(x * func_outer(x, y)); + return std::move(r.value()); } + +#line 85 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret{ + cpp2::impl::deferred_init r; +#line 86 "pure2-autodiff.cpp2" + r.construct(sin(x - y)); + return std::move(r.value()); } + +#line 89 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::if_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_branch_ret{ + cpp2::impl::deferred_init r; +#line 90 "pure2-autodiff.cpp2" + r.construct(x); + + if (cpp2::impl::cmp_less(x,0.0)) { + r.value() = y; + }return std::move(r.value()); + } + +#line 97 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::if_else_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_else_branch_ret{ + cpp2::impl::deferred_init r; +#line 98 "pure2-autodiff.cpp2" + if (cpp2::impl::cmp_less(x,0.0)) { + r.construct(y); + } + else { + r.construct(x); + }return std::move(r.value()); + } + +#line 106 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::direct_return(cpp2::impl::in x, cpp2::impl::in y) -> double{ + return x + y; + } + +#line 110 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::intermediate_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_var_ret{ + cpp2::impl::deferred_init r; +#line 111 "pure2-autodiff.cpp2" + double t {x + y}; + + r.construct(cpp2::move(t)); + return std::move(r.value()); } + +#line 116 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::intermediate_passive_var(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_passive_var_ret{ + cpp2::impl::deferred_init r; +#line 117 "pure2-autodiff.cpp2" + int i {}; + r.construct(x + y); + i = 2; + + static_cast(cpp2::move(i)); + return std::move(r.value()); } + +#line 124 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::intermediate_untyped(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_untyped_ret{ + cpp2::impl::deferred_init r; +#line 125 "pure2-autodiff.cpp2" + auto t {0.0}; + t = x + y; + + r.construct(cpp2::move(t)); + return std::move(r.value()); } + +#line 131 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::intermediate_default_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_default_init_ret{ + cpp2::impl::deferred_init r; +#line 132 "pure2-autodiff.cpp2" + double t {}; + t = x + y; + + r.construct(cpp2::move(t)); + return std::move(r.value()); } + +#line 138 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::intermediate_no_init(cpp2::impl::in x, cpp2::impl::in y) -> intermediate_no_init_ret{ + cpp2::impl::deferred_init r; +#line 139 "pure2-autodiff.cpp2" + cpp2::impl::deferred_init t; + t.construct(x + y); + + r.construct(cpp2::move(t.value())); + return std::move(r.value()); } + +#line 145 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::while_loop(cpp2::impl::in x, cpp2::impl::in y) -> while_loop_ret{ + cpp2::impl::deferred_init r; +#line 146 "pure2-autodiff.cpp2" + r.construct(x); +{ +int i{0}; +double t{0.0}; + +#line 149 "pure2-autodiff.cpp2" + for( ; cpp2::impl::cmp_less(i,2); (i += 1) ) { + t = y; + r.value() = r.value() + t; + } +} +#line 150 "pure2-autodiff.cpp2" + return std::move(r.value()); + +#line 153 "pure2-autodiff.cpp2" + } + +#line 155 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::do_while_loop(cpp2::impl::in x, cpp2::impl::in y) -> do_while_loop_ret{ + cpp2::impl::deferred_init r; +#line 156 "pure2-autodiff.cpp2" + r.construct(x); +{ +auto i{0}; + +#line 159 "pure2-autodiff.cpp2" + do { + r.value() = r.value() + y; + } while ( [&]{ + (i += 1) ; return true; }() && + cpp2::impl::cmp_less(i,2)); +} +#line 160 "pure2-autodiff.cpp2" + return std::move(r.value()); + +#line 164 "pure2-autodiff.cpp2" + } + +#line 166 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::for_loop(cpp2::impl::in x, cpp2::impl::in y) -> for_loop_ret{ + cpp2::impl::deferred_init r; +#line 167 "pure2-autodiff.cpp2" + std::vector v {}; + + CPP2_UFCS(push_back)(v, x); + CPP2_UFCS(push_back)(v, y); + + r.construct(0.0); + for ( + auto const& t : cpp2::move(v) ) + { + r.value() = r.value() + t; + }return std::move(r.value()); + } + +#line 180 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::type_outer_use(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_use_ret{ + cpp2::impl::deferred_init r; +#line 181 "pure2-autodiff.cpp2" + type_outer t {}; + t.a = x; + + r.construct(cpp2::move(t).a + y); + return std::move(r.value()); } + +#line 187 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test::type_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> type_outer_call_ret{ + cpp2::impl::deferred_init r; +#line 188 "pure2-autodiff.cpp2" + type_outer t {}; + t.a = x; + + r.construct(CPP2_UFCS(add)(cpp2::move(t), y)); + return std::move(r.value()); } + + [[nodiscard]] auto ad_test::add_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_1_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d + y_d; + r = x + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::add_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_2_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d + y_d + x_d; + r = x + y + x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::sub_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> sub_1_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d - y_d; + r = x - y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::sub_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> sub_2_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d - y_d - x_d; + r = x - y - x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::add_sub_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_sub_2_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d + y_d - x_d; + r = x + y - x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_1_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = y * x_d + x * y_d; + r = x * y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_2_d_ret{ + double r {0.0}; + double r_d {0.0}; +auto temp_1_d {y * x_d + x * y_d}; + + auto temp_1 {x * y}; + r_d = x * cpp2::move(temp_1_d) + temp_1 * x_d; + r = cpp2::move(temp_1) * x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::div_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> div_1_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x_d),y) + -x * y_d / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y_d),(y * y)); + r = x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::div_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> div_2_d_ret{ + double r {0.0}; + double r_d {0.0}; +auto temp_1_d {x_d / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x_d),y) + -x * y_d / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y_d),(y * y))}; + + auto temp_1 {x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)}; + r_d = cpp2::move(temp_1_d) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(cpp2::move(temp_1_d)),y) + -temp_1 * y_d / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y_d),(y * y)); + r = cpp2::move(temp_1) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(cpp2::move(temp_1)),y); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_div_2_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_div_2_d_ret{ + double r {0.0}; + double r_d {0.0}; +auto temp_1_d {y * x_d + x * y_d}; + + auto temp_1 {x * y}; + r_d = cpp2::move(temp_1_d) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(cpp2::move(temp_1_d)),x) + -temp_1 * x_d / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x_d),(x * x)); + r = cpp2::move(temp_1) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(cpp2::move(temp_1)),x); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::mul_add_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> mul_add_d_ret{ + double r {0.0}; + double r_d {0.0}; +double temp_1_d {x_d + y_d}; + + double temp_1 {x + y}; + r_d = temp_1 * x_d + x * cpp2::move(temp_1_d); + r = x * cpp2::move(temp_1); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::add_mul_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_mul_d_ret{ + double r {0.0}; + double r_d {0.0}; +double temp_1_d {y * x_d + x * y_d}; + + double temp_1 {x * y}; + r_d = x_d + cpp2::move(temp_1_d); + r = x + cpp2::move(temp_1); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::prefix_add_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> prefix_add_d_ret{ + double r {0.0}; + double r_d {0.0}; +double temp_1_d {+x_d}; + + double temp_1 {+x}; + r_d = cpp2::move(temp_1_d) + y_d; + r = cpp2::move(temp_1) + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::prefix_sub_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> prefix_sub_d_ret{ + double r {0.0}; + double r_d {0.0}; +double temp_1_d {-x_d}; + + double temp_1 {-x}; + r_d = cpp2::move(temp_1_d) + y_d; + r = cpp2::move(temp_1) + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::func_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_d_ret{ + double ret {0.0}; + double ret_d {0.0};ret_d = x_d + y_d; + ret = x + y; + return { std::move(ret), std::move(ret_d) }; + } + + [[nodiscard]] auto ad_test::func_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_call_d_ret{ + double r {0.0}; + double r_d {0.0}; +auto temp_1 {func_d(x, x_d, y, y_d)}; + + double temp_2_d {cpp2::move(temp_1).ret_d}; + + double temp_2 {func(x, y)}; + r_d = temp_2 * x_d + x * cpp2::move(temp_2_d); + r = x * cpp2::move(temp_2); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::func_outer_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> func_outer_call_d_ret{ + double r {0.0}; + double r_d {0.0}; +auto temp_1 {func_outer_d(x, x_d, y, y_d)}; + + double temp_2_d {cpp2::move(temp_1).ret_d}; + + double temp_2 {func_outer(x, y)}; + r_d = temp_2 * x_d + x * cpp2::move(temp_2_d); + r = x * cpp2::move(temp_2); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::sin_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> sin_call_d_ret{ + double r {0.0}; + double r_d {0.0}; +double temp_1_d {x_d - y_d}; + + double temp_1 {x - y}; + r_d = cos(temp_1) * cpp2::move(temp_1_d); + r = sin(cpp2::move(temp_1)); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::if_branch_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> if_branch_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d; + r = x; + if (cpp2::impl::cmp_less(x,0.0)) { + r_d = y_d; + r = y; + } + else { + } + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::if_else_branch_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> if_else_branch_d_ret{ + double r {0.0}; + double r_d {0.0};if (cpp2::impl::cmp_less(x,0.0)) { + r_d = y_d; + r = y; + } + else { + r_d = x_d; + r = x; + } + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::direct_return_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> direct_return_d_ret{ + double r {}; + double r_d {};r_d = x_d + y_d; + r = x + y; + return { std::move(r), std::move(r_d) }; } + + [[nodiscard]] auto ad_test::intermediate_var_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_var_d_ret{ + double r {0.0}; + double r_d {0.0}; +double t_d {x_d + y_d}; + + double t {x + y}; + r_d = cpp2::move(t_d); + r = cpp2::move(t); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_passive_var_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_passive_var_d_ret{ + double r {0.0}; + double r_d {0.0}; +int i {}; + r_d = x_d + y_d; + r = x + y; + i = 2; + static_cast(cpp2::move(i)); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_untyped_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_untyped_d_ret{ + double r {0.0}; + double r_d {0.0}; +auto t_d {double()}; + + auto t {0.0}; + t_d = x_d + y_d; + t = x + y; + r_d = cpp2::move(t_d); + r = cpp2::move(t); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_default_init_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_default_init_d_ret{ + double r {0.0}; + double r_d {0.0}; +double t_d {}; + + double t {}; + t_d = x_d + y_d; + t = x + y; + r_d = cpp2::move(t_d); + r = cpp2::move(t); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::intermediate_no_init_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> intermediate_no_init_d_ret{ + double r {0.0}; + double r_d {0.0}; +cpp2::impl::deferred_init t_d; + + cpp2::impl::deferred_init t; + t_d.construct(x_d + y_d); + t.construct(x + y); + r_d = cpp2::move(t_d.value()); + r = cpp2::move(t.value()); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::while_loop_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> while_loop_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d; + r = x; +{ +int i{0}; +double t{0.0}; +double t_d{}; + for( ; cpp2::impl::cmp_less(i,2); (i += 1) ) { + t_d = y_d; + t = y; + r_d = r_d + t_d; + r = r + t; + } +} + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::do_while_loop_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> do_while_loop_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x_d; + r = x; +{ +auto i{0}; + do { + r_d = r_d + y_d; + r = r + y; + } + while ( [&]{ + (i += 1) + ; return true; }() && + cpp2::impl::cmp_less(i,2) + ); +} + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::for_loop_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> for_loop_d_ret{ + double r {0.0}; + double r_d {0.0}; +std::vector v_d {}; + + std::vector v {}; + CPP2_UFCS(push_back)(v_d, x_d); + CPP2_UFCS(push_back)(v, x); + CPP2_UFCS(push_back)(v_d, y_d); + CPP2_UFCS(push_back)(v, y); + r_d = { }; + r = 0.0; +{ +auto t_d_iter{CPP2_UFCS(begin)(cpp2::move(v_d))}; + for ( auto const& t : cpp2::move(v) ) { do { +{ +auto const& t_d{*cpp2::impl::assert_not_null(t_d_iter)}; + { + r_d = r_d + t_d; + r = r + t; + } +} + } + while (false); (++t_d_iter); } +} + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::type_outer_use_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> type_outer_use_d_ret{ + double r {0.0}; + double r_d {0.0}; +type_outer_d t_d {}; + + type_outer t {}; + t_d.a_d = x_d; + t.a = x; + + double temp_1_d {cpp2::move(t_d).a_d}; + + double temp_1 {cpp2::move(t).a}; + r_d = cpp2::move(temp_1_d) + y_d; + r = cpp2::move(temp_1) + y; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test::type_outer_call_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> type_outer_call_d_ret{ + double r {0.0}; + double r_d {0.0}; +type_outer_d t_d {}; + + type_outer t {}; + t_d.a_d = x_d; + t.a = x; + + auto temp_1 {CPP2_UFCS(add_d)(t, cpp2::move(t_d), y, y_d)}; + r_d = cpp2::move(temp_1).r_d; + r = CPP2_UFCS(add)(cpp2::move(t), y); + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto func_outer_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& ret_b) -> func_outer_b_ret{ + double ret {0.0};ret = x + y; + x_b += ret_b; + y_b += ret_b; + ret_b = 0.0; + return ret; } + +#line 197 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret{ + cpp2::impl::deferred_init r; +#line 198 "pure2-autodiff.cpp2" + r.construct(x + y); + return std::move(r.value()); } + +#line 201 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret{ + cpp2::impl::deferred_init r; +#line 202 "pure2-autodiff.cpp2" + r.construct(x + y + x); + return std::move(r.value()); } + +#line 205 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret{ + cpp2::impl::deferred_init r; +#line 206 "pure2-autodiff.cpp2" + r.construct(x - y); + return std::move(r.value()); } + +#line 209 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret{ + cpp2::impl::deferred_init r; +#line 210 "pure2-autodiff.cpp2" + r.construct(x - y - x); + return std::move(r.value()); } + +#line 213 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret{ + cpp2::impl::deferred_init r; +#line 214 "pure2-autodiff.cpp2" + r.construct(x + y - x); + return std::move(r.value()); } + +#line 217 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret{ + cpp2::impl::deferred_init r; +#line 218 "pure2-autodiff.cpp2" + r.construct(x * y); + return std::move(r.value()); } + +#line 221 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret{ + cpp2::impl::deferred_init r; +#line 222 "pure2-autodiff.cpp2" + r.construct(x * y * x); + return std::move(r.value()); } + +#line 225 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret{ + cpp2::impl::deferred_init r; +#line 226 "pure2-autodiff.cpp2" + r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)); + return std::move(r.value()); } + +#line 229 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret{ + cpp2::impl::deferred_init r; +#line 230 "pure2-autodiff.cpp2" + r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)); + return std::move(r.value()); } + +#line 233 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret{ + cpp2::impl::deferred_init r; +#line 234 "pure2-autodiff.cpp2" + r.construct(x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)); + return std::move(r.value()); } + +#line 237 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret{ + cpp2::impl::deferred_init r; +#line 238 "pure2-autodiff.cpp2" + r.construct(x * (x + y)); + return std::move(r.value()); } + +#line 241 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret{ + cpp2::impl::deferred_init r; +#line 242 "pure2-autodiff.cpp2" + r.construct(x + x * y); + return std::move(r.value()); } + +#line 245 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret{ + cpp2::impl::deferred_init r; +#line 246 "pure2-autodiff.cpp2" + r.construct(sin(x - y)); + return std::move(r.value()); } + +#line 249 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret{ + cpp2::impl::deferred_init ret; +#line 250 "pure2-autodiff.cpp2" + ret.construct(x + y); + return std::move(ret.value()); } + +#line 253 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret{ + cpp2::impl::deferred_init r; +#line 254 "pure2-autodiff.cpp2" + r.construct(x * func(x, y)); + return std::move(r.value()); } + +#line 257 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_reverse::func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret{ + cpp2::impl::deferred_init r; +#line 258 "pure2-autodiff.cpp2" + r.construct(x * func_outer(x, y)); + return std::move(r.value()); } + + [[nodiscard]] auto ad_test_reverse::add_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_1_b_ret{ + double r {0.0};r = x + y; + x_b += r_b; + y_b += r_b; + r_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::add_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_2_b_ret{ + double r {0.0};r = x + y + x; + x_b += r_b; + y_b += r_b; + x_b += r_b; + r_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::sub_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> sub_1_b_ret{ + double r {0.0};r = x - y; + x_b += r_b; + y_b -= r_b; + r_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::sub_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> sub_2_b_ret{ + double r {0.0};r = x - y - x; + x_b += r_b; + y_b -= r_b; + x_b -= r_b; + r_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::add_sub_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_sub_2_b_ret{ + double r {0.0};r = x + y - x; + x_b += r_b; + y_b += r_b; + x_b -= r_b; + r_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::mul_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_1_b_ret{ + double r {0.0};r = x * y; + x_b += y * r_b; + y_b += x * r_b; + r_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::mul_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_2_b_ret{ + double r {0.0}; +auto temp_1_b {0.0}; + + auto temp_1 {x * y}; + r = temp_1 * x; + temp_1_b += x * r_b; + x_b += cpp2::move(temp_1) * r_b; + r_b = 0.0; + x_b += y * temp_1_b; + y_b += x * temp_1_b; + temp_1_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::div_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> div_1_b_ret{ + double r {0.0};r = x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y); + x_b += r_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(r_b),y); + y_b -= x * r_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(r_b),(y * y)); + r_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::div_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> div_2_b_ret{ + double r {0.0}; +auto temp_1_b {0.0}; + + auto temp_1 {x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)}; + r = temp_1 / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(temp_1),y); + temp_1_b += r_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(r_b),y); + y_b -= cpp2::move(temp_1) * r_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(r_b),(y * y)); + r_b = 0.0; + x_b += temp_1_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(temp_1_b),y); + y_b -= x * temp_1_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(temp_1_b),(y * y)); + temp_1_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::mul_div_2_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_div_2_b_ret{ + double r {0.0}; +auto temp_1_b {0.0}; + + auto temp_1 {x * y}; + r = temp_1 / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(temp_1),x); + temp_1_b += r_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(r_b),x); + x_b -= cpp2::move(temp_1) * r_b / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(r_b),(x * x)); + r_b = 0.0; + x_b += y * temp_1_b; + y_b += x * temp_1_b; + temp_1_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::mul_add_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> mul_add_b_ret{ + double r {0.0}; +double temp_1_b {0.0}; + + double temp_1 {x + y}; + r = x * temp_1; + x_b += cpp2::move(temp_1) * r_b; + temp_1_b += x * r_b; + r_b = 0.0; + x_b += temp_1_b; + y_b += temp_1_b; + temp_1_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::add_mul_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_mul_b_ret{ + double r {0.0}; +double temp_1_b {0.0}; + + double temp_1 {x * y}; + r = x + cpp2::move(temp_1); + x_b += r_b; + temp_1_b += r_b; + r_b = 0.0; + x_b += y * temp_1_b; + y_b += x * temp_1_b; + temp_1_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::sin_call_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> sin_call_b_ret{ + double r {0.0}; +double temp_1_b {0.0}; + + double temp_1 {x - y}; + r = sin(temp_1); + temp_1_b += cos(cpp2::move(temp_1)) * r_b; + r_b = 0.0; + x_b += temp_1_b; + y_b -= temp_1_b; + temp_1_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::func_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& ret_b) -> func_b_ret{ + double ret {0.0};ret = x + y; + x_b += ret_b; + y_b += ret_b; + ret_b = 0.0; + return ret; } + + [[nodiscard]] auto ad_test_reverse::func_call_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> func_call_b_ret{ + double r {0.0}; +double temp_2_b {0.0}; + + double temp_2 {func(x, y)}; + r = x * temp_2; + x_b += cpp2::move(temp_2) * r_b; + temp_2_b += x * r_b; + r_b = 0.0; + static_cast(func_b(x, x_b, y, y_b, temp_2_b)); + temp_2_b = 0.0; + return r; } + + [[nodiscard]] auto ad_test_reverse::func_outer_call_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> func_outer_call_b_ret{ + double r {0.0}; +double temp_2_b {0.0}; + + double temp_2 {func_outer(x, y)}; + r = x * temp_2; + x_b += cpp2::move(temp_2) * r_b; + temp_2_b += x * r_b; + r_b = 0.0; + static_cast(func_outer_b(x, x_b, y, y_b, temp_2_b)); + temp_2_b = 0.0; + return r; } + +#line 261 "pure2-autodiff.cpp2" +} + +#line 264 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_twice::mul_1(cpp2::impl::in x) -> mul_1_ret{ + cpp2::impl::deferred_init r; +#line 265 "pure2-autodiff.cpp2" + r.construct(x * x); + return std::move(r.value()); } + + [[nodiscard]] auto ad_test_twice::mul_1_d(cpp2::impl::in x, cpp2::impl::in x_d) -> mul_1_d_ret{ + double r {0.0}; + double r_d {0.0};r_d = x * x_d + x * x_d; + r = x * x; + return { std::move(r), std::move(r_d) }; + } + + [[nodiscard]] auto ad_test_twice::mul_1_d2(cpp2::impl::in x, cpp2::impl::in x_d2) -> mul_1_d2_ret{ + double r {0.0}; + double r_d2 {0.0};r_d2 = x * x_d2 + x * x_d2; + r = x * x; + return { std::move(r), std::move(r_d2) }; + } + + [[nodiscard]] auto ad_test_twice::mul_1_d_d2(cpp2::impl::in x, cpp2::impl::in x_d2, cpp2::impl::in x_d, cpp2::impl::in x_d_d2) -> mul_1_d_d2_ret{ + double r {0.0}; + double r_d2 {0.0}; + double r_d {0.0}; + double r_d_d2 {0.0}; +double temp_1_d2 {x_d * x_d2 + x * x_d_d2}; + + double temp_1 {x * x_d}; + + double temp_2_d2 {x_d * x_d2 + x * x_d_d2}; + + double temp_2 {x * x_d}; + r_d_d2 = cpp2::move(temp_1_d2) + cpp2::move(temp_2_d2); + r_d = cpp2::move(temp_1) + cpp2::move(temp_2); + r_d2 = x * x_d2 + x * x_d2; + r = x * x; + return { std::move(r), std::move(r_d2), std::move(r_d), std::move(r_d_d2) }; + } + +#line 269 "pure2-autodiff.cpp2" +auto write_output(cpp2::impl::in func, cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d, auto const& ret) -> void{ + std::cout << "diff(" + cpp2::to_string(func) + ") at (x = " + cpp2::to_string(x) + ", x_d = " + cpp2::to_string(x_d) + ", y = " + cpp2::to_string(y) + ", y_d = " + cpp2::to_string(y_d) + ") = (r = " + cpp2::to_string(ret.r) + ", r_d = " + cpp2::to_string(ret.r_d) + ")" << std::endl; +} + +#line 273 "pure2-autodiff.cpp2" +auto write_output_reverse(cpp2::impl::in func, cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b, auto const& ret) -> void{ + r_b = 1.0; + std::cout << "diff(" + cpp2::to_string(func) + ") at (x = " + cpp2::to_string(x) + ", y = " + cpp2::to_string(y) + ", r_b = " + cpp2::to_string(r_b) + ") = (r = " + cpp2::to_string(ret) + ", x_b = " + cpp2::to_string(x_b) + ", y_b = " + cpp2::to_string(y_b) + ")" << std::endl; + x_b = 0.0; + y_b = 0.0; +} + +#line 281 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_2::f(cpp2::impl::in x) -> f_ret{ + cpp2::impl::deferred_init y; +#line 282 "pure2-autodiff.cpp2" + if (cpp2::impl::cmp_less(x,-3)) + { + y.construct(x * x); + } + else {if (cpp2::impl::cmp_less(x,3)) + { + y.construct(x + sin(x) + 10); + } + else + { + y.construct(sin(x) * x * x); + }}return std::move(y.value()); + } + + [[nodiscard]] auto ad_test_2::f_d(cpp2::impl::in x, cpp2::impl::in> x_d) -> f_d_ret{ + double y {0.0}; + cpp2::taylor y_d {0.0};if (cpp2::impl::cmp_less(x,-3)) { + y_d = x_d.mul(x_d, x, x); + y = x * x; + } + else { + if (cpp2::impl::cmp_less(x,3)) { + + cpp2::taylor temp_1_d {CPP2_UFCS(sin)(x_d, x)}; + + double temp_1 {sin(x)}; + y_d = x_d + cpp2::move(temp_1_d); + y = x + cpp2::move(temp_1) + 10; + } + else { + + cpp2::taylor temp_3_d {CPP2_UFCS(sin)(x_d, x)}; + + double temp_3 {sin(x)}; + + auto temp_4_d {cpp2::move(temp_3_d).mul(x_d, temp_3, x)}; + + auto temp_4 {cpp2::move(temp_3) * x}; + y_d = cpp2::move(temp_4_d).mul(x_d, temp_4, x); + y = cpp2::move(temp_4) * x; + } + } + return { std::move(y), std::move(y_d) }; + } + +#line 297 "pure2-autodiff.cpp2" +auto main() -> int{ + + double x {2.0}; + double x_d {1.0}; + double y {3.0}; + double y_d {2.0}; + + write_output("x + y", x, x_d, y, y_d, ad_name::ad_test::add_1_d(x, x_d, y, y_d)); + write_output("x + y + x", x, x_d, y, y_d, ad_name::ad_test::add_2_d(x, x_d, y, y_d)); + write_output("x - y", x, x_d, y, y_d, ad_name::ad_test::sub_1_d(x, x_d, y, y_d)); + write_output("x - y - x", x, x_d, y, y_d, ad_name::ad_test::sub_2_d(x, x_d, y, y_d)); + write_output("x + y - x", x, x_d, y, y_d, ad_name::ad_test::add_sub_2_d(x, x_d, y, y_d)); + write_output("x * y", x, x_d, y, y_d, ad_name::ad_test::mul_1_d(x, x_d, y, y_d)); + write_output("x * y * x", x, x_d, y, y_d, ad_name::ad_test::mul_2_d(x, x_d, y, y_d)); + write_output("x / y", x, x_d, y, y_d, ad_name::ad_test::div_1_d(x, x_d, y, y_d)); + write_output("x / y / y", x, x_d, y, y_d, ad_name::ad_test::div_2_d(x, x_d, y, y_d)); + write_output("x * y / x", x, x_d, y, y_d, ad_name::ad_test::mul_div_2_d(x, x_d, y, y_d)); + write_output("x * (x + y)", x, x_d, y, y_d, ad_name::ad_test::mul_add_d(x, x_d, y, y_d)); + write_output("x + x * y", x, x_d, y, y_d, ad_name::ad_test::add_mul_d(x, x_d, y, y_d)); + write_output("+x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_add_d(x, x_d, y, y_d)); + write_output("-x + y)", x, x_d, y, y_d, ad_name::ad_test::prefix_sub_d(x, x_d, y, y_d)); + write_output("x * func(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_call_d(x, x_d, y, y_d)); + write_output("x * func_outer(x, y)", x, x_d, y, y_d, ad_name::ad_test::func_outer_call_d(x, x_d, y, y_d)); + write_output("sin(x - y)", x, x_d, y, y_d, ad_name::ad_test::sin_call_d(x, x_d, y, y_d)); + write_output("if branch", x, x_d, y, y_d, ad_name::ad_test::if_branch_d(x, x_d, y, y_d)); + write_output("if else branch", x, x_d, y, y_d, ad_name::ad_test::if_else_branch_d(x, x_d, y, y_d)); + write_output("direct return", x, x_d, y, y_d, ad_name::ad_test::direct_return_d(x, x_d, y, y_d)); + write_output("intermediate var", x, x_d, y, y_d, ad_name::ad_test::intermediate_var_d(x, x_d, y, y_d)); + write_output("intermediate passive var", x, x_d, y, y_d, ad_name::ad_test::intermediate_passive_var_d(x, x_d, y, y_d)); + write_output("intermediate untyped", x, x_d, y, y_d, ad_name::ad_test::intermediate_untyped_d(x, x_d, y, y_d)); + write_output("intermediate default init", x, x_d, y, y_d, ad_name::ad_test::intermediate_default_init_d(x, x_d, y, y_d)); + write_output("intermediate no init", x, x_d, y, y_d, ad_name::ad_test::intermediate_no_init_d(x, x_d, y, y_d)); + write_output("while loop", x, x_d, y, y_d, ad_name::ad_test::while_loop_d(x, x_d, y, y_d)); + write_output("do while loop", x, x_d, y, y_d, ad_name::ad_test::do_while_loop_d(x, x_d, y, y_d)); + write_output("for loop", x, x_d, y, y_d, ad_name::ad_test::for_loop_d(x, x_d, y, y_d)); + write_output("tye_outer.a + y", x, x_d, y, y_d, ad_name::ad_test::type_outer_use_d(x, x_d, y, y_d)); + write_output("type_outer.add(y)", x, x_d, y, y_d, ad_name::ad_test::type_outer_call_d(x, x_d, y, cpp2::move(y_d))); + + double x_b {0.0}; + double y_b {0.0}; + double w_b {1.0}; + + write_output_reverse("x + y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x + y + x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x - y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::sub_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x - y - x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::sub_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x + y - x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_sub_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * y * x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x / y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::div_1_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x / y / y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::div_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * y / x", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_div_2_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * (x + y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::mul_add_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x + x * y", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::add_mul_b(x, x_b, y, y_b, w_b)); + write_output_reverse("sin(x-y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::sin_call_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * func(x-y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::func_call_b(x, x_b, y, y_b, w_b)); + write_output_reverse("x * func_outer(x-y)", x, x_b, y, y_b, w_b, ad_name::ad_test_reverse::func_outer_call_b(x, x_b, cpp2::move(y), y_b, w_b)); + + static_cast(cpp2::move(x_b)); + static_cast(cpp2::move(y_b)); + static_cast(cpp2::move(w_b)); + + auto r_twice {ad_test_twice::mul_1_d_d2(x, x_d, cpp2::move(x_d), 0.0)}; + std::cout << "2nd order diff of x*x at " + cpp2::to_string(cpp2::move(x)) + " = " + cpp2::to_string(cpp2::move(r_twice).r_d_d2) + "" << std::endl; +} + diff --git a/regression-tests/test-results/pure2-autodiff.cpp2.output b/regression-tests/test-results/pure2-autodiff.cpp2.output new file mode 100644 index 000000000..9ac7a9233 --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff.cpp2.output @@ -0,0 +1,1449 @@ +pure2-autodiff.cpp2... + +ad_test:/* @autodiff @print */ type = +{ + add_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y; + return; + } + + add_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y + x; + return; + } + + sub_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x - y; + return; + } + + sub_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x - y - x; + return; + } + + add_sub_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y - x; + return; + } + + mul_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y; + return; + } + + mul_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y * x; + return; + } + + div_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x / y; + return; + } + + div_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x / y / y; + return; + } + + mul_div_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y / x; + return; + } + + mul_add:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * (x + y); + return; + } + + add_mul:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + x * y; + return; + } + + prefix_add:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = +x + y; + return; + } + + prefix_sub:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = -x + y; + return; + } + + func:( + in x: double, + in y: double, + ) -> (out ret: double, ) = + { + ret = x + y; + return; + } + + func_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * func(x, y); + return; + } + + func_outer_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * func_outer(x, y); + return; + } + + sin_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = sin(x - y); + return; + } + + if_branch:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x; + if x < 0.0 + { + r = y; + } + return; + } + + if_else_branch:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + if x < 0.0 + { + r = y; + } + else + { + r = x; + } + return; + } + + direct_return:( + in x: double, + in y: double, + ) -> move double = + { + return x + y; + } + + intermediate_var:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: double = x + y; + r = t; + return; + } + + intermediate_passive_var:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + i: int = (); + r = x + y; + i = 2; + _ = i; + return; + } + + intermediate_untyped:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: _ = 0.0; + t = x + y; + r = t; + return; + } + + intermediate_default_init:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: double = (); + t = x + y; + r = t; + return; + } + + intermediate_no_init:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: double; + t = x + y; + r = t; + return; + } + + while_loop:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x; + ( + copy i: int = 0, + copy t: double = 0.0, + ) + while i < 2 + next (i += 1) + { + t = y; + r = r + t; + } + return; + } + + do_while_loop:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x; + (copy i: _ = 0, ) + do + { + r = r + y; + } + next (i += 1) + while i < 2; + return; + } + + for_loop:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + v: std::vector = (); + v.push_back(x); + v.push_back(y); + r = 0.0; + for v + do (in t: _) + { + r = r + t; + } + return; + } + + type_outer_use:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: type_outer = (); + t.a = x; + r = t.a + y; + return; + } + + type_outer_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + t: type_outer = (); + t.a = x; + r = t.add(y); + return; + } + + add_1_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d + y_d; + r = x + y; + return; + } + + add_2_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d + y_d + x_d; + r = x + y + x; + return; + } + + sub_1_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d - y_d; + r = x - y; + return; + } + + sub_2_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d - y_d - x_d; + r = x - y - x; + return; + } + + add_sub_2_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d + y_d - x_d; + r = x + y - x; + return; + } + + mul_1_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = y * x_d + x * y_d; + r = x * y; + return; + } + + mul_2_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: _ = y * x_d + x * y_d; + temp_1: _ = x * y; + r_d = x * temp_1_d + temp_1 * x_d; + r = temp_1 * x; + return; + } + + div_1_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d / y + -x * y_d / (y * y); + r = x / y; + return; + } + + div_2_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: _ = x_d / y + -x * y_d / (y * y); + temp_1: _ = x / y; + r_d = temp_1_d / y + -temp_1 * y_d / (y * y); + r = temp_1 / y; + return; + } + + mul_div_2_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: _ = y * x_d + x * y_d; + temp_1: _ = x * y; + r_d = temp_1_d / x + -temp_1 * x_d / (x * x); + r = temp_1 / x; + return; + } + + mul_add_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: double = x_d + y_d; + temp_1: double = x + y; + r_d = temp_1 * x_d + x * temp_1_d; + r = x * temp_1; + return; + } + + add_mul_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: double = y * x_d + x * y_d; + temp_1: double = x * y; + r_d = x_d + temp_1_d; + r = x + temp_1; + return; + } + + prefix_add_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: double = +x_d; + temp_1: double = +x; + r_d = temp_1_d + y_d; + r = temp_1 + y; + return; + } + + prefix_sub_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: double = -x_d; + temp_1: double = -x; + r_d = temp_1_d + y_d; + r = temp_1 + y; + return; + } + + func_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out ret: double = 0.0, + out ret_d: double = 0.0, + ) = + { + ret_d = x_d + y_d; + ret = x + y; + return; + } + + func_call_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1: _ = func_d(x, x_d, y, y_d); + temp_2_d: double = temp_1.ret_d; + temp_2: double = func(x, y); + r_d = temp_2 * x_d + x * temp_2_d; + r = x * temp_2; + return; + } + + func_outer_call_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1: _ = func_outer_d(x, x_d, y, y_d); + temp_2_d: double = temp_1.ret_d; + temp_2: double = func_outer(x, y); + r_d = temp_2 * x_d + x * temp_2_d; + r = x * temp_2; + return; + } + + sin_call_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + temp_1_d: double = x_d - y_d; + temp_1: double = x - y; + r_d = cos(temp_1) * temp_1_d; + r = sin(temp_1); + return; + } + + if_branch_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d; + r = x; + if x < 0.0 + { + r_d = y_d; + r = y; + } + else + { + } + return; + } + + if_else_branch_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + if x < 0.0 + { + r_d = y_d; + r = y; + } + else + { + r_d = x_d; + r = x; + } + return; + } + + direct_return_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = (), + out r_d: double = (), + ) = + { + r_d = x_d + y_d; + r = x + y; + return; + } + + intermediate_var_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + t_d: double = x_d + y_d; + t: double = x + y; + r_d = t_d; + r = t; + return; + } + + intermediate_passive_var_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + i: int = (); + r_d = x_d + y_d; + r = x + y; + i = 2; + _ = i; + return; + } + + intermediate_untyped_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + t_d: _ = double(); + t: _ = 0.0; + t_d = x_d + y_d; + t = x + y; + r_d = t_d; + r = t; + return; + } + + intermediate_default_init_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + t_d: double = (); + t: double = (); + t_d = x_d + y_d; + t = x + y; + r_d = t_d; + r = t; + return; + } + + intermediate_no_init_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + t_d: double; + t: double; + t_d = x_d + y_d; + t = x + y; + r_d = t_d; + r = t; + return; + } + + while_loop_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d; + r = x; + ( + copy i: int = 0, + copy t: double = 0.0, + copy t_d: double = (), + ) + while i < 2 + next (i += 1) + { + t_d = y_d; + t = y; + r_d = r_d + t_d; + r = r + t; + } + return; + } + + do_while_loop_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x_d; + r = x; + (copy i: _ = 0, ) + do + { + r_d = r_d + y_d; + r = r + y; + } + next (i += 1) + while i < 2; + return; + } + + for_loop_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + v_d: std::vector = (); + v: std::vector = (); + v_d.push_back(x_d); + v.push_back(x); + v_d.push_back(y_d); + v.push_back(y); + r_d = (); + r = 0.0; + (copy t_d_iter: _ = v_d.begin(), ) + for v + next (t_d_iter++) + do (in t: _) + { + (in t_d: _ = t_d_iter*, ) + { + r_d = r_d + t_d; + r = r + t; + } + } + return; + } + + type_outer_use_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + t_d: type_outer_d = (); + t: type_outer = (); + t_d.a_d = x_d; + t.a = x; + temp_1_d: double = t_d.a_d; + temp_1: double = t.a; + r_d = temp_1_d + y_d; + r = temp_1 + y; + return; + } + + type_outer_call_d:( + in x: double, + in x_d: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + t_d: type_outer_d = (); + t: type_outer = (); + t_d.a_d = x_d; + t.a = x; + temp_1: _ = t.add_d(t_d, y, y_d); + r_d = temp_1.r_d; + r = t.add(y); + return; + } +} + + +ad_test_reverse:/* @autodiff<"reverse"> @print */ type = +{ + add_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y; + return; + } + + add_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y + x; + return; + } + + sub_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x - y; + return; + } + + sub_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x - y - x; + return; + } + + add_sub_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + y - x; + return; + } + + mul_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y; + return; + } + + mul_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y * x; + return; + } + + div_1:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x / y; + return; + } + + div_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x / y / y; + return; + } + + mul_div_2:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * y / x; + return; + } + + mul_add:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * (x + y); + return; + } + + add_mul:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x + x * y; + return; + } + + sin_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = sin(x - y); + return; + } + + func:( + in x: double, + in y: double, + ) -> (out ret: double, ) = + { + ret = x + y; + return; + } + + func_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * func(x, y); + return; + } + + func_outer_call:( + in x: double, + in y: double, + ) -> (out r: double, ) = + { + r = x * func_outer(x, y); + return; + } + + add_1_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + r = x + y; + x_b += r_b; + y_b += r_b; + r_b = 0.0; + return; + } + + add_2_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + r = x + y + x; + x_b += r_b; + y_b += r_b; + x_b += r_b; + r_b = 0.0; + return; + } + + sub_1_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + r = x - y; + x_b += r_b; + y_b -= r_b; + r_b = 0.0; + return; + } + + sub_2_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + r = x - y - x; + x_b += r_b; + y_b -= r_b; + x_b -= r_b; + r_b = 0.0; + return; + } + + add_sub_2_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + r = x + y - x; + x_b += r_b; + y_b += r_b; + x_b -= r_b; + r_b = 0.0; + return; + } + + mul_1_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + r = x * y; + x_b += y * r_b; + y_b += x * r_b; + r_b = 0.0; + return; + } + + mul_2_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_1_b: _ = 0.0; + temp_1: _ = x * y; + r = temp_1 * x; + temp_1_b += x * r_b; + x_b += temp_1 * r_b; + r_b = 0.0; + x_b += y * temp_1_b; + y_b += x * temp_1_b; + temp_1_b = 0.0; + return; + } + + div_1_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + r = x / y; + x_b += r_b / y; + y_b -= x * r_b / (y * y); + r_b = 0.0; + return; + } + + div_2_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_1_b: _ = 0.0; + temp_1: _ = x / y; + r = temp_1 / y; + temp_1_b += r_b / y; + y_b -= temp_1 * r_b / (y * y); + r_b = 0.0; + x_b += temp_1_b / y; + y_b -= x * temp_1_b / (y * y); + temp_1_b = 0.0; + return; + } + + mul_div_2_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_1_b: _ = 0.0; + temp_1: _ = x * y; + r = temp_1 / x; + temp_1_b += r_b / x; + x_b -= temp_1 * r_b / (x * x); + r_b = 0.0; + x_b += y * temp_1_b; + y_b += x * temp_1_b; + temp_1_b = 0.0; + return; + } + + mul_add_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_1_b: double = 0.0; + temp_1: double = x + y; + r = x * temp_1; + x_b += temp_1 * r_b; + temp_1_b += x * r_b; + r_b = 0.0; + x_b += temp_1_b; + y_b += temp_1_b; + temp_1_b = 0.0; + return; + } + + add_mul_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_1_b: double = 0.0; + temp_1: double = x * y; + r = x + temp_1; + x_b += r_b; + temp_1_b += r_b; + r_b = 0.0; + x_b += y * temp_1_b; + y_b += x * temp_1_b; + temp_1_b = 0.0; + return; + } + + sin_call_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_1_b: double = 0.0; + temp_1: double = x - y; + r = sin(temp_1); + temp_1_b += cos(temp_1) * r_b; + r_b = 0.0; + x_b += temp_1_b; + y_b -= temp_1_b; + temp_1_b = 0.0; + return; + } + + func_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout ret_b: double, + ) -> (out ret: double = 0.0, ) = + { + ret = x + y; + x_b += ret_b; + y_b += ret_b; + ret_b = 0.0; + return; + } + + func_call_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_2_b: double = 0.0; + temp_2: double = func(x, y); + r = x * temp_2; + x_b += temp_2 * r_b; + temp_2_b += x * r_b; + r_b = 0.0; + _ = func_b(x, x_b, y, y_b, temp_2_b); + temp_2_b = 0.0; + return; + } + + func_outer_call_b:( + in x: double, + inout x_b: double, + in y: double, + inout y_b: double, + inout r_b: double, + ) -> (out r: double = 0.0, ) = + { + temp_2_b: double = 0.0; + temp_2: double = func_outer(x, y); + r = x * temp_2; + x_b += temp_2 * r_b; + temp_2_b += x * r_b; + r_b = 0.0; + _ = func_outer_b(x, x_b, y, y_b, temp_2_b); + temp_2_b = 0.0; + return; + } +} + + +ad_test_twice:/* @autodiff @autodiff<"suffix=_d2"> @print */ type = +{ + mul_1:(in x: double, ) -> (out r: double, ) = + { + r = x * x; + return; + } + + mul_1_d:( + in x: double, + in x_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + r_d = x * x_d + x * x_d; + r = x * x; + return; + } + + mul_1_d2:( + in x: double, + in x_d2: double, + ) -> ( + out r: double = 0.0, + out r_d2: double = 0.0, + ) = + { + r_d2 = x * x_d2 + x * x_d2; + r = x * x; + return; + } + + mul_1_d_d2:( + in x: double, + in x_d2: double, + in x_d: double, + in x_d_d2: double, + ) -> ( + out r: double = 0.0, + out r_d2: double = 0.0, + out r_d: double = 0.0, + out r_d_d2: double = 0.0, + ) = + { + temp_1_d2: double = x_d * x_d2 + x * x_d_d2; + temp_1: double = x * x_d; + temp_2_d2: double = x_d * x_d2 + x * x_d_d2; + temp_2: double = x * x_d; + r_d_d2 = temp_1_d2 + temp_2_d2; + r_d = temp_1 + temp_2; + r_d2 = x * x_d2 + x * x_d2; + r = x * x; + return; + } +} + + +ad_test_2:/* @autodiff<"order=2"> @print */ type = +{ + f:(in x: double, ) -> (out y: double, ) = + { + if x < -3 + { + y = x * x; + } + else + { + if x < 3 + { + y = x + sin(x) + 10; + } + else + { + y = sin(x) * x * x; + } + } + return; + } + + f_d:( + in x: double, + in x_d: cpp2::taylor, + ) -> ( + out y: double = 0.0, + out y_d: cpp2::taylor = 0.0, + ) = + { + if x < -3 + { + y_d = x_d..mul(x_d, x, x); + y = x * x; + } + else + { + if x < 3 + { + temp_1_d: cpp2::taylor = x_d.sin(x); + temp_1: double = sin(x); + y_d = x_d + temp_1_d; + y = x + temp_1 + 10; + } + else + { + temp_3_d: cpp2::taylor = x_d.sin(x); + temp_3: double = sin(x); + temp_4_d: _ = temp_3_d..mul(x_d, temp_3, x); + temp_4: _ = temp_3 * x; + y_d = temp_4_d..mul(x_d, temp_4, x); + y = temp_4 * x; + } + } + return; + } +} + ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/pure2-regex_20_lookbehind.cpp b/regression-tests/test-results/pure2-regex_20_lookbehind.cpp similarity index 99% rename from regression-tests/pure2-regex_20_lookbehind.cpp rename to regression-tests/test-results/pure2-regex_20_lookbehind.cpp index 1f549a346..674d9ada9 100644 --- a/regression-tests/pure2-regex_20_lookbehind.cpp +++ b/regression-tests/test-results/pure2-regex_20_lookbehind.cpp @@ -1,4 +1,5 @@ +#define CPP2_IMPORT_STD Yes #include "cpp2regex.h" //=== Cpp2 type declarations ==================================================== @@ -6,28 +7,28 @@ #include "cpp2util.h" -#line 1 "build/20_lookbehind.cpp2" +#line 1 "pure2-regex_20_lookbehind.cpp2" -#line 166 "build/20_lookbehind.cpp2" +#line 166 "pure2-regex_20_lookbehind.cpp2" class test_tests_20_lookbehind; //=== Cpp2 type definitions and function declarations =========================== -#line 1 "build/20_lookbehind.cpp2" +#line 1 "pure2-regex_20_lookbehind.cpp2" [[nodiscard]] auto create_result(cpp2::impl::in resultExpr, auto const& r) -> std::string; -#line 113 "build/20_lookbehind.cpp2" +#line 113 "pure2-regex_20_lookbehind.cpp2" [[nodiscard]] auto sanitize(std::string str) -> std::string; -#line 125 "build/20_lookbehind.cpp2" +#line 125 "pure2-regex_20_lookbehind.cpp2" template auto test(M const& regex, cpp2::impl::in id, cpp2::impl::in regex_str, cpp2::impl::in str, cpp2::impl::in kind, cpp2::impl::in resultExpr, cpp2::impl::in resultExpected) -> void; -#line 166 "build/20_lookbehind.cpp2" +#line 166 "pure2-regex_20_lookbehind.cpp2" class test_tests_20_lookbehind { -#line 223 "build/20_lookbehind.cpp2" +#line 223 "pure2-regex_20_lookbehind.cpp2" public: auto run() const& -> void; public: template class regex_01_matcher { public: template using context = cpp2::regex::match_context; @@ -1905,15 +1906,15 @@ public: [[nodiscard]] static auto to_string() -> std::string; public: auto operator=(test_tests_20_lookbehind const&) -> void = delete; -#line 283 "build/20_lookbehind.cpp2" +#line 283 "pure2-regex_20_lookbehind.cpp2" }; auto main() -> int; //=== Cpp2 function definitions ================================================= -#line 1 "build/20_lookbehind.cpp2" +#line 1 "pure2-regex_20_lookbehind.cpp2" [[nodiscard]] auto create_result(cpp2::impl::in resultExpr, auto const& r) -> std::string{ -#line 2 "build/20_lookbehind.cpp2" +#line 2 "pure2-regex_20_lookbehind.cpp2" std::string result {""}; auto get_next {[_0 = (&resultExpr)](auto const& iter) mutable -> auto{ @@ -2025,7 +2026,7 @@ auto main() -> int; return result; } -#line 113 "build/20_lookbehind.cpp2" +#line 113 "pure2-regex_20_lookbehind.cpp2" [[nodiscard]] auto sanitize(std::string str) -> std::string { str = cpp2::string_util::replace_all(str, "\a", "\\a"); @@ -2038,7 +2039,7 @@ auto main() -> int; return cpp2::move(str); } -#line 125 "build/20_lookbehind.cpp2" +#line 125 "pure2-regex_20_lookbehind.cpp2" template auto test(M const& regex, cpp2::impl::in id, cpp2::impl::in regex_str, cpp2::impl::in str, cpp2::impl::in kind, cpp2::impl::in resultExpr, cpp2::impl::in resultExpected) -> void{ @@ -2079,7 +2080,7 @@ template auto test(M const& regex, cpp2::impl::in id, c std::cout << "" + cpp2::to_string(id) + "_" + cpp2::to_string(kind) + ": " + cpp2::to_string(cpp2::move(status)) + " " + cpp2::to_string(cpp2::move(warning)) + "regex: " + cpp2::to_string(regex_str) + " parsed_regex: " + cpp2::to_string(CPP2_UFCS(to_string)(regex)) + " str: " + cpp2::to_string(sanitize(str)) + " result_expr: " + cpp2::to_string(resultExpr) + " expected_results " + cpp2::to_string(sanitize(resultExpected)) + "" << std::endl; } -#line 223 "build/20_lookbehind.cpp2" +#line 223 "pure2-regex_20_lookbehind.cpp2" auto test_tests_20_lookbehind::run() const& -> void{ std::cout << "Running tests_20_lookbehind:" << std::endl; test(regex_01, "01", R"((?<=a)b)", "ab", "y", R"($&)", "b"); @@ -8982,7 +8983,7 @@ int i{0}; template [[nodiscard]] auto test_tests_20_lookbehind::regex_56_matcher::to_string() -> std::string{return R"((?<=(?=(aaxy))aa))"; } -#line 284 "build/20_lookbehind.cpp2" +#line 284 "pure2-regex_20_lookbehind.cpp2" auto main() -> int{ CPP2_UFCS(run)(test_tests_20_lookbehind()); } diff --git a/regression-tests/test-results/pure2-regex_20_lookbehind.cpp2.output b/regression-tests/test-results/pure2-regex_20_lookbehind.cpp2.output new file mode 100644 index 000000000..4bb5f4259 --- /dev/null +++ b/regression-tests/test-results/pure2-regex_20_lookbehind.cpp2.output @@ -0,0 +1,2 @@ +pure2-regex_20_lookbehind.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/source/parse.h b/source/parse.h index d7f2ba5a0..e72e2c9d5 100644 --- a/source/parse.h +++ b/source/parse.h @@ -2196,7 +2196,9 @@ auto postfix_expression_node::to_string() const for (auto const& x : ops) { assert (x.op); - ret += x.op->as_string_view(); + if(x.op->as_string_view() != "(") { // Brackets are handled by the expression list. + ret += x.op->as_string_view(); + } if (x.id_expr) { ret += x.id_expr->to_string(); } diff --git a/source/reflect.h b/source/reflect.h index e438a13be..b6a74a96c 100644 --- a/source/reflect.h +++ b/source/reflect.h @@ -24,161 +24,196 @@ class compiler_services; #line 212 "reflect.h2" template class reflection_base; -#line 245 "reflect.h2" +#line 248 "reflect.h2" class declaration; -#line 330 "reflect.h2" +#line 333 "reflect.h2" class function_declaration; -#line 435 "reflect.h2" +#line 438 "reflect.h2" class object_declaration; -#line 471 "reflect.h2" +#line 474 "reflect.h2" class type_or_namespace_declaration; -#line 581 "reflect.h2" +#line 585 "reflect.h2" class type_declaration; -#line 625 "reflect.h2" +#line 629 "reflect.h2" class namespace_declaration; -#line 644 "reflect.h2" +#line 648 "reflect.h2" class alias_declaration; -#line 663 "reflect.h2" +#line 667 "reflect.h2" class parameter_declaration; -#line 709 "reflect.h2" +#line 713 "reflect.h2" template class binary_expression; -#line 836 "reflect.h2" +#line 840 "reflect.h2" class expression_list; -#line 869 "reflect.h2" +#line 873 "reflect.h2" class prefix_expression; -#line 911 "reflect.h2" +#line 915 "reflect.h2" class postfix_expression; -#line 982 "reflect.h2" +#line 986 "reflect.h2" class template_arg; -#line 1008 "reflect.h2" +#line 1012 "reflect.h2" class unqualified_id; -#line 1040 "reflect.h2" +#line 1044 "reflect.h2" class qualified_id; -#line 1084 "reflect.h2" +#line 1088 "reflect.h2" class type_id; -#line 1127 "reflect.h2" +#line 1131 "reflect.h2" class primary_expression; -#line 1166 "reflect.h2" +#line 1170 "reflect.h2" class id_expression; -#line 1202 "reflect.h2" +#line 1206 "reflect.h2" class expression; -#line 1253 "reflect.h2" +#line 1257 "reflect.h2" class is_as_expression; -#line 1314 "reflect.h2" +#line 1318 "reflect.h2" class statement; -#line 1366 "reflect.h2" +#line 1370 "reflect.h2" class expression_statement; -#line 1388 "reflect.h2" +#line 1392 "reflect.h2" class compound_statement; -#line 1427 "reflect.h2" +#line 1431 "reflect.h2" class selection_statement; -#line 1453 "reflect.h2" +#line 1457 "reflect.h2" class return_statement; -#line 1475 "reflect.h2" +#line 1479 "reflect.h2" class iteration_statement; -#line 1972 "reflect.h2" +#line 1976 "reflect.h2" class value_member_info; -#line 3398 "reflect.h2" -class autodiff_impl; +#line 2617 "reflect.h2" +class simple_traverser; + +#line 4109 "reflect.h2" +class autodiff_special_func; + +#line 4153 "reflect.h2" +class autodiff_declared_variable; + +#line 4171 "reflect.h2" +class autodiff_declaration_stack_item; + +#line 4215 "reflect.h2" +class autodiff_context; + + +#line 4605 "reflect.h2" +class autodiff_diff_code; + + +#line 4654 "reflect.h2" +class autodiff_activity_check; + + +#line 4752 "reflect.h2" +class autodiff_handler_base; + + +#line 4770 "reflect.h2" +class autodiff_expression_handler; + + +#line 5413 "reflect.h2" +class autodiff_stmt_handler; + +#line 5883 "reflect.h2" +class autodiff_declaration_handler; -#line 3814 "reflect.h2" +#line 6231 "reflect.h2" class expression_flags; -#line 3830 "reflect.h2" +#line 6247 "reflect.h2" class regex_token; -#line 3857 "reflect.h2" +#line 6274 "reflect.h2" class regex_token_check; -#line 3878 "reflect.h2" +#line 6295 "reflect.h2" class regex_token_code; -#line 3899 "reflect.h2" +#line 6316 "reflect.h2" class regex_token_empty; -#line 3917 "reflect.h2" +#line 6334 "reflect.h2" class regex_token_list; -#line 3969 "reflect.h2" +#line 6386 "reflect.h2" class parse_context_group_state; -#line 4030 "reflect.h2" +#line 6447 "reflect.h2" class parse_context_branch_reset_state; -#line 4073 "reflect.h2" +#line 6490 "reflect.h2" class parse_context; -#line 4474 "reflect.h2" +#line 6891 "reflect.h2" class generation_function_context; -#line 4492 "reflect.h2" +#line 6909 "reflect.h2" class generation_context; -#line 4691 "reflect.h2" +#line 7108 "reflect.h2" class alternative_token; -#line 4706 "reflect.h2" +#line 7123 "reflect.h2" class alternative_token_gen; -#line 4771 "reflect.h2" +#line 7188 "reflect.h2" class any_token; -#line 4788 "reflect.h2" +#line 7205 "reflect.h2" class atomic_group_token; -#line 4818 "reflect.h2" +#line 7235 "reflect.h2" class char_token; -#line 4933 "reflect.h2" +#line 7350 "reflect.h2" class class_token; -#line 5157 "reflect.h2" +#line 7574 "reflect.h2" class group_ref_token; -#line 5294 "reflect.h2" +#line 7711 "reflect.h2" class group_token; -#line 5641 "reflect.h2" +#line 8058 "reflect.h2" class lookahead_lookbehind_token; -#line 5736 "reflect.h2" +#line 8153 "reflect.h2" class range_token; -#line 5893 "reflect.h2" +#line 8310 "reflect.h2" class special_range_token; -#line 5979 "reflect.h2" +#line 8396 "reflect.h2" template class regex_generator; -#line 6242 "reflect.h2" +#line 8659 "reflect.h2" } } @@ -307,25 +342,28 @@ template class reflection_base public: [[nodiscard]] auto position() const -> source_position override; public: [[nodiscard]] auto print() const& -> std::string; + + public: [[nodiscard]] auto is_same(cpp2::impl::in o) const& -> bool; + public: template [[nodiscard]] auto is_same([[maybe_unused]] reflection_base const& unnamed_param_2) const& -> bool; public: virtual ~reflection_base() noexcept; public: reflection_base(reflection_base const& that); public: reflection_base(reflection_base&& that) noexcept; -#line 232 "reflect.h2" +#line 235 "reflect.h2" }; -#line 245 "reflect.h2" +#line 248 "reflect.h2" class declaration : public reflection_base { -#line 249 "reflect.h2" +#line 252 "reflect.h2" public: declaration( cpp2::impl::in n_, cpp2::impl::in s ); -#line 258 "reflect.h2" +#line 261 "reflect.h2" public: [[nodiscard]] auto is_public() const& -> bool; public: [[nodiscard]] auto is_protected() const& -> bool; public: [[nodiscard]] auto is_private() const& -> bool; @@ -344,7 +382,7 @@ class declaration public: [[nodiscard]] auto name() const& -> std::string_view; -#line 279 "reflect.h2" +#line 282 "reflect.h2" public: [[nodiscard]] auto has_initializer() const& -> bool; public: [[nodiscard]] auto get_initializer() const& -> statement; @@ -390,21 +428,21 @@ public: declaration(declaration const& that); public: declaration(declaration&& that) noexcept; -#line 324 "reflect.h2" +#line 327 "reflect.h2" }; -#line 330 "reflect.h2" +#line 333 "reflect.h2" class function_declaration : public declaration { -#line 334 "reflect.h2" +#line 337 "reflect.h2" public: function_declaration( cpp2::impl::in n_, cpp2::impl::in s ); -#line 344 "reflect.h2" +#line 347 "reflect.h2" public: [[nodiscard]] auto index_of_parameter_named(cpp2::impl::in s) const& -> int; public: [[nodiscard]] auto has_parameter_named(cpp2::impl::in s) const& -> bool; public: [[nodiscard]] auto has_return_named(cpp2::impl::in s) const& -> bool; @@ -454,10 +492,10 @@ class function_declaration public: [[nodiscard]] auto get_parameters() const& -> std::vector; -#line 401 "reflect.h2" +#line 404 "reflect.h2" public: [[nodiscard]] auto get_returns() const& -> std::vector; -#line 413 "reflect.h2" +#line 416 "reflect.h2" public: [[nodiscard]] auto default_to_virtual() & -> decltype(auto); public: [[nodiscard]] auto make_virtual() & -> bool; @@ -467,88 +505,88 @@ class function_declaration public: function_declaration(function_declaration&& that) noexcept; -#line 429 "reflect.h2" +#line 432 "reflect.h2" }; -#line 435 "reflect.h2" +#line 438 "reflect.h2" class object_declaration : public declaration { -#line 439 "reflect.h2" +#line 442 "reflect.h2" public: object_declaration( cpp2::impl::in n_, cpp2::impl::in s ); -#line 449 "reflect.h2" +#line 452 "reflect.h2" public: [[nodiscard]] auto is_const() const& -> bool; public: [[nodiscard]] auto has_wildcard_type() const& -> bool; public: [[nodiscard]] auto type() const& -> std::string; -#line 459 "reflect.h2" +#line 462 "reflect.h2" public: [[nodiscard]] auto initializer() const& -> std::string; public: object_declaration(object_declaration const& that); public: object_declaration(object_declaration&& that) noexcept; -#line 465 "reflect.h2" +#line 468 "reflect.h2" }; -#line 471 "reflect.h2" +#line 474 "reflect.h2" class type_or_namespace_declaration : public declaration { -#line 475 "reflect.h2" +#line 478 "reflect.h2" public: type_or_namespace_declaration( cpp2::impl::in n_, cpp2::impl::in s ); -#line 485 "reflect.h2" +#line 488 "reflect.h2" public: auto reserve_names(cpp2::impl::in name, auto&& ...etc) const& -> void; -#line 499 "reflect.h2" +#line 502 "reflect.h2" public: [[nodiscard]] auto get_member_functions() const& -> std::vector; -#line 510 "reflect.h2" +#line 513 "reflect.h2" public: [[nodiscard]] auto get_member_functions_needing_initializer() const& -> std::vector; -#line 525 "reflect.h2" +#line 528 "reflect.h2" public: [[nodiscard]] auto get_member_objects() const& -> std::vector; -#line 535 "reflect.h2" +#line 538 "reflect.h2" public: [[nodiscard]] auto get_member_types() const& -> std::vector; -#line 545 "reflect.h2" +#line 548 "reflect.h2" public: [[nodiscard]] auto get_member_aliases() const& -> std::vector; -#line 555 "reflect.h2" +#line 558 "reflect.h2" public: [[nodiscard]] auto get_members() const& -> std::vector; -#line 565 "reflect.h2" +#line 568 "reflect.h2" public: auto add_member(cpp2::impl::in source) & -> void; public: type_or_namespace_declaration(type_or_namespace_declaration const& that); public: type_or_namespace_declaration(type_or_namespace_declaration&& that) noexcept; -#line 578 "reflect.h2" +#line 582 "reflect.h2" }; -#line 581 "reflect.h2" +#line 585 "reflect.h2" class type_declaration : public type_or_namespace_declaration { -#line 585 "reflect.h2" +#line 589 "reflect.h2" public: type_declaration( cpp2::impl::in n_, cpp2::impl::in s ); -#line 596 "reflect.h2" +#line 600 "reflect.h2" public: [[nodiscard]] auto is_polymorphic() const& -> bool; public: [[nodiscard]] auto is_final() const& -> bool; public: [[nodiscard]] auto make_final() & -> bool; @@ -556,27 +594,27 @@ struct query_declared_value_set_functions_ret { bool out_this_in_that; bool out_ -#line 600 "reflect.h2" +#line 604 "reflect.h2" public: [[nodiscard]] auto query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret; -#line 616 "reflect.h2" +#line 620 "reflect.h2" public: [[nodiscard]] auto disable_member_function_generation() & -> decltype(auto); public: [[nodiscard]] auto disable_ref_qualifier_generation() & -> decltype(auto); -#line 620 "reflect.h2" +#line 624 "reflect.h2" public: [[nodiscard]] auto remove_marked_members() & -> decltype(auto); public: [[nodiscard]] auto remove_all_members() & -> decltype(auto); public: type_declaration(type_declaration const& that); public: type_declaration(type_declaration&& that) noexcept; -#line 622 "reflect.h2" +#line 626 "reflect.h2" }; -#line 625 "reflect.h2" +#line 629 "reflect.h2" class namespace_declaration : public type_or_namespace_declaration { -#line 629 "reflect.h2" +#line 633 "reflect.h2" public: namespace_declaration( cpp2::impl::in n_, @@ -586,14 +624,14 @@ class namespace_declaration public: namespace_declaration(namespace_declaration&& that) noexcept; -#line 638 "reflect.h2" +#line 642 "reflect.h2" }; -#line 644 "reflect.h2" +#line 648 "reflect.h2" class alias_declaration : public declaration { -#line 648 "reflect.h2" +#line 652 "reflect.h2" public: alias_declaration( cpp2::impl::in n_, @@ -603,21 +641,21 @@ class alias_declaration public: alias_declaration(alias_declaration&& that) noexcept; -#line 657 "reflect.h2" +#line 661 "reflect.h2" }; -#line 663 "reflect.h2" +#line 667 "reflect.h2" class parameter_declaration : public reflection_base { -#line 667 "reflect.h2" +#line 671 "reflect.h2" public: parameter_declaration( cpp2::impl::in n_, cpp2::impl::in s ); -#line 676 "reflect.h2" +#line 680 "reflect.h2" public: [[nodiscard]] auto get_declaration() const& -> object_declaration; public: [[nodiscard]] auto get_passing_style() const& -> passing_style; @@ -628,10 +666,10 @@ class parameter_declaration public: parameter_declaration(parameter_declaration const& that); public: parameter_declaration(parameter_declaration&& that) noexcept; -#line 683 "reflect.h2" +#line 687 "reflect.h2" }; -#line 696 "reflect.h2" +#line 700 "reflect.h2" using multiplicative_expression = binary_expression<"multiplicative",is_as_expression_node>; using additive_expression = binary_expression<"additive",multiplicative_expression_node>; using shift_expression = binary_expression<"shift",additive_expression_node>; @@ -648,14 +686,14 @@ using assignment_expression = binary_expression<"assignment",logical_or_expressi template class binary_expression : public reflection_base> { -#line 713 "reflect.h2" +#line 717 "reflect.h2" public: binary_expression( binary_expression_node* const& n_, cpp2::impl::in s ); -#line 722 "reflect.h2" +#line 726 "reflect.h2" public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto lhs_is_id_expression() const& -> bool; public: [[nodiscard]] auto is_standalone_expression() const& -> bool; @@ -680,16 +718,16 @@ public: auto operator=(term_t const& that) -> term_t& ; public: term_t(term_t&& that) noexcept; public: auto operator=(term_t&& that) noexcept -> term_t& ; -#line 740 "reflect.h2" +#line 744 "reflect.h2" }; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 817 "reflect.h2" +#line 821 "reflect.h2" public: [[nodiscard]] auto as_expression_list() const& -> expression_list; public: [[nodiscard]] auto as_literal() const& -> std::string; -#line 821 "reflect.h2" +#line 825 "reflect.h2" public: [[nodiscard]] auto get_if_only_a_postfix_expression() const& -> postfix_expression; public: [[nodiscard]] auto get_lhs_postfix_expression() const& -> postfix_expression; @@ -702,49 +740,49 @@ public: auto operator=(term_t&& that) noexcept -> term_t& ; public: binary_expression(binary_expression const& that); public: binary_expression(binary_expression&& that) noexcept; -#line 830 "reflect.h2" +#line 834 "reflect.h2" }; -#line 836 "reflect.h2" +#line 840 "reflect.h2" class expression_list : public reflection_base { -#line 840 "reflect.h2" +#line 844 "reflect.h2" public: expression_list( cpp2::impl::in n_, cpp2::impl::in s ); -#line 849 "reflect.h2" +#line 853 "reflect.h2" public: [[nodiscard]] auto is_empty() const& -> bool; public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto get_expressions() const& -> std::vector; -#line 862 "reflect.h2" +#line 866 "reflect.h2" public: [[nodiscard]] auto to_string() const& -> std::string; public: expression_list(expression_list const& that); public: expression_list(expression_list&& that) noexcept; -#line 863 "reflect.h2" +#line 867 "reflect.h2" }; -#line 869 "reflect.h2" +#line 873 "reflect.h2" class prefix_expression : public reflection_base { -#line 873 "reflect.h2" +#line 877 "reflect.h2" public: prefix_expression( cpp2::impl::in n_, cpp2::impl::in s ); -#line 882 "reflect.h2" +#line 886 "reflect.h2" public: [[nodiscard]] auto get_ops() const& -> std::vector; -#line 890 "reflect.h2" +#line 894 "reflect.h2" public: [[nodiscard]] auto get_postfix_expression() const& -> postfix_expression; public: [[nodiscard]] auto is_fold_expression() const& -> bool; @@ -764,21 +802,21 @@ class prefix_expression public: prefix_expression(prefix_expression const& that); public: prefix_expression(prefix_expression&& that) noexcept; -#line 905 "reflect.h2" +#line 909 "reflect.h2" }; -#line 911 "reflect.h2" +#line 915 "reflect.h2" class postfix_expression : public reflection_base { -#line 915 "reflect.h2" +#line 919 "reflect.h2" public: postfix_expression( cpp2::impl::in n_, cpp2::impl::in s ); -#line 924 "reflect.h2" +#line 928 "reflect.h2" public: [[nodiscard]] auto get_primary_expression() const& -> primary_expression; public: class term_t { @@ -789,7 +827,7 @@ class postfix_expression public: [[nodiscard]] auto get_op() const& -> std::string_view; -#line 940 "reflect.h2" +#line 944 "reflect.h2" public: [[nodiscard]] auto is_id_expression() const& -> bool; public: [[nodiscard]] auto is_expression_list() const& -> bool; public: [[nodiscard]] auto is_expression() const& -> bool; @@ -800,12 +838,12 @@ class postfix_expression public: term_t(term_t const& that); public: term_t(term_t&& that) noexcept; -#line 947 "reflect.h2" +#line 951 "reflect.h2" }; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 955 "reflect.h2" +#line 959 "reflect.h2" public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto is_identifier() const& -> bool; public: [[nodiscard]] auto is_id_expression() const& -> bool; @@ -819,7 +857,7 @@ public: term_t(term_t&& that) noexcept; public: [[nodiscard]] auto get_first_token_ignoring_this() const& -> std::string_view; -#line 972 "reflect.h2" +#line 976 "reflect.h2" public: [[nodiscard]] auto starts_with_function_call_with_num_parameters(cpp2::impl::in num) const& -> bool; public: [[nodiscard]] auto is_result_a_temporary_variable() const& -> bool; @@ -827,21 +865,21 @@ public: term_t(term_t&& that) noexcept; public: postfix_expression(postfix_expression const& that); public: postfix_expression(postfix_expression&& that) noexcept; -#line 976 "reflect.h2" +#line 980 "reflect.h2" }; -#line 982 "reflect.h2" +#line 986 "reflect.h2" class template_arg : public reflection_base { -#line 986 "reflect.h2" +#line 990 "reflect.h2" public: template_arg( cpp2::impl::in n_, cpp2::impl::in s ); -#line 995 "reflect.h2" +#line 999 "reflect.h2" public: [[nodiscard]] auto is_expression() const& -> bool; public: [[nodiscard]] auto is_type_id() const& -> bool; @@ -852,47 +890,47 @@ class template_arg public: template_arg(template_arg const& that); public: template_arg(template_arg&& that) noexcept; -#line 1002 "reflect.h2" +#line 1006 "reflect.h2" }; -#line 1008 "reflect.h2" +#line 1012 "reflect.h2" class unqualified_id : public reflection_base { -#line 1012 "reflect.h2" +#line 1016 "reflect.h2" public: unqualified_id( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1021 "reflect.h2" +#line 1025 "reflect.h2" public: [[nodiscard]] auto is_identifier() const& -> bool; public: [[nodiscard]] auto get_identifier() const& -> std::string; -#line 1031 "reflect.h2" +#line 1035 "reflect.h2" public: [[nodiscard]] auto as_token() const& -> std::string; public: [[nodiscard]] auto to_string() const& -> std::string; public: unqualified_id(unqualified_id const& that); public: unqualified_id(unqualified_id&& that) noexcept; -#line 1034 "reflect.h2" +#line 1038 "reflect.h2" }; -#line 1040 "reflect.h2" +#line 1044 "reflect.h2" class qualified_id : public reflection_base { -#line 1044 "reflect.h2" +#line 1048 "reflect.h2" public: qualified_id( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1053 "reflect.h2" +#line 1057 "reflect.h2" public: class term_t { private: std::string op; private: unqualified_id unqualified; @@ -904,33 +942,33 @@ class qualified_id public: term_t(term_t const& that); public: term_t(term_t&& that) noexcept; -#line 1061 "reflect.h2" +#line 1065 "reflect.h2" }; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 1075 "reflect.h2" +#line 1079 "reflect.h2" public: [[nodiscard]] auto as_token() const& -> std::string; public: [[nodiscard]] auto to_string() const& -> std::string; public: qualified_id(qualified_id const& that); public: qualified_id(qualified_id&& that) noexcept; -#line 1078 "reflect.h2" +#line 1082 "reflect.h2" }; -#line 1084 "reflect.h2" +#line 1088 "reflect.h2" class type_id : public reflection_base { -#line 1088 "reflect.h2" +#line 1092 "reflect.h2" public: type_id( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1103 "reflect.h2" +#line 1107 "reflect.h2" public: [[nodiscard]] auto is_postfix_expression() const& -> bool; public: [[nodiscard]] auto is_qualified_id() const& -> bool; public: [[nodiscard]] auto is_unqualified_id() const& -> bool; @@ -944,7 +982,7 @@ class type_id public: [[nodiscard]] auto as_qualified_id() const& -> qualified_id; public: [[nodiscard]] auto as_unqualified_id() const& -> unqualified_id; -#line 1117 "reflect.h2" +#line 1121 "reflect.h2" public: [[nodiscard]] auto as_keyword() const& -> std::string; public: [[nodiscard]] auto as_token() const& -> std::string; @@ -952,21 +990,21 @@ class type_id public: type_id(type_id const& that); public: type_id(type_id&& that) noexcept; -#line 1121 "reflect.h2" +#line 1125 "reflect.h2" }; -#line 1127 "reflect.h2" +#line 1131 "reflect.h2" class primary_expression : public reflection_base { -#line 1131 "reflect.h2" +#line 1135 "reflect.h2" public: primary_expression( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1146 "reflect.h2" +#line 1150 "reflect.h2" public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto is_identifier() const& -> bool; public: [[nodiscard]] auto is_id_expression() const& -> bool; @@ -984,21 +1022,21 @@ class primary_expression public: primary_expression(primary_expression const& that); public: primary_expression(primary_expression&& that) noexcept; -#line 1160 "reflect.h2" +#line 1164 "reflect.h2" }; -#line 1166 "reflect.h2" +#line 1170 "reflect.h2" class id_expression : public reflection_base { -#line 1170 "reflect.h2" +#line 1174 "reflect.h2" public: id_expression( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1185 "reflect.h2" +#line 1189 "reflect.h2" public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto is_empty() const& -> bool; public: [[nodiscard]] auto is_identifier() const& -> bool; @@ -1014,21 +1052,21 @@ class id_expression public: id_expression(id_expression const& that); public: id_expression(id_expression&& that) noexcept; -#line 1196 "reflect.h2" +#line 1200 "reflect.h2" }; -#line 1202 "reflect.h2" +#line 1206 "reflect.h2" class expression : public reflection_base { -#line 1206 "reflect.h2" +#line 1210 "reflect.h2" public: expression( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1215 "reflect.h2" +#line 1219 "reflect.h2" public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto is_standalone_expression() const& -> bool; public: [[nodiscard]] auto subexpression_count() const& -> int; @@ -1045,10 +1083,10 @@ struct get_lhs_rhs_if_simple_assignment_ret { postfix_expression lhs; logical_or -#line 1231 "reflect.h2" +#line 1235 "reflect.h2" public: [[nodiscard]] auto get_lhs_rhs_if_simple_assignment() const& -> get_lhs_rhs_if_simple_assignment_ret; -#line 1242 "reflect.h2" +#line 1246 "reflect.h2" public: [[nodiscard]] auto as_assignment_expression() const& -> assignment_expression; public: [[nodiscard]] auto as_expression_list() const& -> expression_list; public: [[nodiscard]] auto as_literal() const& -> std::string; @@ -1058,21 +1096,21 @@ struct get_lhs_rhs_if_simple_assignment_ret { postfix_expression lhs; logical_or public: expression(expression const& that); public: expression(expression&& that) noexcept; -#line 1247 "reflect.h2" +#line 1251 "reflect.h2" }; -#line 1253 "reflect.h2" +#line 1257 "reflect.h2" class is_as_expression : public reflection_base { -#line 1257 "reflect.h2" +#line 1261 "reflect.h2" public: is_as_expression( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1266 "reflect.h2" +#line 1270 "reflect.h2" public: class term_t { private: std::string op; private: expression expr; @@ -1084,14 +1122,14 @@ class is_as_expression public: term_t(term_t const& that); public: term_t(term_t&& that) noexcept; -#line 1274 "reflect.h2" +#line 1278 "reflect.h2" }; public: [[nodiscard]] auto get_expression() const& -> prefix_expression; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 1284 "reflect.h2" +#line 1288 "reflect.h2" public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto is_identifier() const& -> bool; public: [[nodiscard]] auto is_id_expression() const& -> bool; @@ -1104,30 +1142,30 @@ public: term_t(term_t&& that) noexcept; public: [[nodiscard]] auto get_identifier() const& -> std::string_view; -#line 1300 "reflect.h2" +#line 1304 "reflect.h2" public: [[nodiscard]] auto to_string() const& -> std::string; public: virtual ~is_as_expression() noexcept; public: is_as_expression(is_as_expression const& that); public: is_as_expression(is_as_expression&& that) noexcept; -#line 1301 "reflect.h2" +#line 1305 "reflect.h2" }; -#line 1314 "reflect.h2" +#line 1318 "reflect.h2" class statement : public reflection_base { -#line 1318 "reflect.h2" +#line 1322 "reflect.h2" public: statement( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1327 "reflect.h2" +#line 1331 "reflect.h2" public: [[nodiscard]] auto get_parameters() const& -> std::vector; -#line 1337 "reflect.h2" +#line 1341 "reflect.h2" public: [[nodiscard]] auto is_expression_statement() const& -> bool; public: [[nodiscard]] auto is_compound_statement() const& -> bool; public: [[nodiscard]] auto is_selection_statement() const& -> bool; @@ -1146,71 +1184,71 @@ class statement public: [[nodiscard]] auto as_return_statement() const& -> return_statement; public: [[nodiscard]] auto as_iteration_statement() const& -> iteration_statement; -#line 1359 "reflect.h2" +#line 1363 "reflect.h2" public: [[nodiscard]] auto to_string() const& -> std::string; public: virtual ~statement() noexcept; public: statement(statement const& that); public: statement(statement&& that) noexcept; -#line 1360 "reflect.h2" +#line 1364 "reflect.h2" }; -#line 1366 "reflect.h2" +#line 1370 "reflect.h2" class expression_statement : public reflection_base { -#line 1370 "reflect.h2" +#line 1374 "reflect.h2" public: expression_statement( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1379 "reflect.h2" +#line 1383 "reflect.h2" public: [[nodiscard]] auto get_expression() const& -> expression; public: [[nodiscard]] auto to_string() const& -> std::string; public: expression_statement(expression_statement const& that); public: expression_statement(expression_statement&& that) noexcept; -#line 1382 "reflect.h2" +#line 1386 "reflect.h2" }; -#line 1388 "reflect.h2" +#line 1392 "reflect.h2" class compound_statement : public reflection_base { -#line 1392 "reflect.h2" +#line 1396 "reflect.h2" public: compound_statement( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1401 "reflect.h2" +#line 1405 "reflect.h2" public: [[nodiscard]] auto get_statements() const& -> std::vector; -#line 1411 "reflect.h2" +#line 1415 "reflect.h2" public: auto add_statement(cpp2::impl::in source, cpp2::impl::in before_position = 0) & -> void; public: compound_statement(compound_statement const& that); public: compound_statement(compound_statement&& that) noexcept; -#line 1421 "reflect.h2" +#line 1425 "reflect.h2" }; -#line 1427 "reflect.h2" +#line 1431 "reflect.h2" class selection_statement : public reflection_base { -#line 1431 "reflect.h2" +#line 1435 "reflect.h2" public: selection_statement( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1440 "reflect.h2" +#line 1444 "reflect.h2" public: [[nodiscard]] auto has_false_branch_in_source_code() const& -> bool; public: [[nodiscard]] auto has_false_branch() const& -> bool; @@ -1221,42 +1259,42 @@ class selection_statement public: selection_statement(selection_statement const& that); public: selection_statement(selection_statement&& that) noexcept; -#line 1447 "reflect.h2" +#line 1451 "reflect.h2" }; -#line 1453 "reflect.h2" +#line 1457 "reflect.h2" class return_statement : public reflection_base { -#line 1457 "reflect.h2" +#line 1461 "reflect.h2" public: return_statement( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1466 "reflect.h2" +#line 1470 "reflect.h2" public: [[nodiscard]] auto has_expression() const& -> bool; public: [[nodiscard]] auto get_expression() const& -> expression; public: return_statement(return_statement const& that); public: return_statement(return_statement&& that) noexcept; -#line 1469 "reflect.h2" +#line 1473 "reflect.h2" }; -#line 1475 "reflect.h2" +#line 1479 "reflect.h2" class iteration_statement : public reflection_base { -#line 1479 "reflect.h2" +#line 1483 "reflect.h2" public: iteration_statement( cpp2::impl::in n_, cpp2::impl::in s ); -#line 1488 "reflect.h2" +#line 1492 "reflect.h2" public: [[nodiscard]] auto is_do() const& -> bool; public: [[nodiscard]] auto is_while() const& -> bool; public: [[nodiscard]] auto is_for() const& -> bool; @@ -1272,68 +1310,68 @@ class iteration_statement public: iteration_statement(iteration_statement const& that); public: iteration_statement(iteration_statement&& that) noexcept; -#line 1500 "reflect.h2" +#line 1504 "reflect.h2" }; -#line 1515 "reflect.h2" +#line 1519 "reflect.h2" auto add_virtual_destructor(meta::type_declaration& t) -> void; -#line 1535 "reflect.h2" +#line 1539 "reflect.h2" auto interface(meta::type_declaration& t) -> void; -#line 1583 "reflect.h2" +#line 1587 "reflect.h2" auto polymorphic_base(meta::type_declaration& t) -> void; -#line 1628 "reflect.h2" +#line 1632 "reflect.h2" auto ordered_impl( meta::type_declaration& t, cpp2::impl::in ordering ) -> void; -#line 1657 "reflect.h2" +#line 1661 "reflect.h2" auto ordered(meta::type_declaration& t) -> void; -#line 1665 "reflect.h2" +#line 1669 "reflect.h2" auto weakly_ordered(meta::type_declaration& t) -> void; -#line 1673 "reflect.h2" +#line 1677 "reflect.h2" auto partially_ordered(meta::type_declaration& t) -> void; -#line 1695 "reflect.h2" +#line 1699 "reflect.h2" auto copyable(meta::type_declaration& t) -> void; -#line 1727 "reflect.h2" +#line 1731 "reflect.h2" auto copy_constructible(meta::type_declaration& t) -> void; -#line 1759 "reflect.h2" +#line 1763 "reflect.h2" auto hashable(meta::type_declaration& t) -> void; -#line 1792 "reflect.h2" +#line 1796 "reflect.h2" auto basic_value(meta::type_declaration& t) -> void; -#line 1820 "reflect.h2" +#line 1824 "reflect.h2" auto value(meta::type_declaration& t) -> void; -#line 1826 "reflect.h2" +#line 1830 "reflect.h2" auto weakly_ordered_value(meta::type_declaration& t) -> void; -#line 1832 "reflect.h2" +#line 1836 "reflect.h2" auto partially_ordered_value(meta::type_declaration& t) -> void; -#line 1861 "reflect.h2" +#line 1865 "reflect.h2" auto cpp1_rule_of_zero(meta::type_declaration& t) -> void; -#line 1903 "reflect.h2" +#line 1907 "reflect.h2" auto cpp2_struct(meta::type_declaration& t) -> void; -#line 1972 "reflect.h2" +#line 1976 "reflect.h2" class value_member_info { public: std::string name; public: std::string type; public: std::string value; public: value_member_info(auto const& name_, auto const& type_, auto const& value_); -#line 1976 "reflect.h2" +#line 1980 "reflect.h2" }; auto basic_enum( @@ -1342,163 +1380,893 @@ auto basic_enum( cpp2::impl::in bitwise ) -> void; -#line 2242 "reflect.h2" +#line 2246 "reflect.h2" auto cpp2_enum(meta::type_declaration& t) -> void; -#line 2269 "reflect.h2" +#line 2273 "reflect.h2" auto flag_enum(meta::type_declaration& t) -> void; -#line 2315 "reflect.h2" +#line 2319 "reflect.h2" auto cpp2_union(meta::type_declaration& t) -> void; -#line 2466 "reflect.h2" +#line 2470 "reflect.h2" auto print(cpp2::impl::in t) -> void; -#line 2477 "reflect.h2" +#line 2481 "reflect.h2" auto noisy(cpp2::impl::in t) -> void; struct python_param_names_and_types_ret { std::string names; std::string types; }; -#line 2501 "reflect.h2" +#line 2505 "reflect.h2" [[nodiscard]] auto python_param_names_and_types(cpp2::impl::in mf) -> python_param_names_and_types_ret; -#line 2521 "reflect.h2" +#line 2525 "reflect.h2" auto python(meta::type_declaration& t) -> void; -#line 2564 "reflect.h2" +#line 2568 "reflect.h2" auto javascript(meta::type_declaration& t) -> void; -#line 2605 "reflect.h2" +#line 2609 "reflect.h2" auto sample_print(cpp2::impl::in s, cpp2::impl::in indent) -> void; -#line 2624 "reflect.h2" +#line 2617 "reflect.h2" +class simple_traverser { + + public: virtual auto pre_traverse(cpp2::impl::in decl) -> void; + +#line 2623 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in decl) -> void; + +#line 2643 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in f) -> void; + +#line 2647 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in f) -> void; + +#line 2668 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in o) -> void; + +#line 2672 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in o) -> void; + +#line 2680 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in t) -> void; + +#line 2684 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in t) -> void; + +#line 2692 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in t) -> void; + +#line 2696 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in t) -> void; + +#line 2701 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2705 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2740 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2744 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2754 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2758 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2766 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2770 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2789 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2793 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2804 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in expr) -> void; + +#line 2810 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in expr) -> void; + +#line 2824 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2841 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2852 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2869 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2881 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2898 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2909 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2926 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2937 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2954 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2966 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2983 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2995 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 3012 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 3023 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 3040 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 3051 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 3068 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 3079 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 3096 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 3107 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 3124 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 3136 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 3153 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 3164 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in isas) -> void; + +#line 3180 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in isas) -> void; + +#line 3191 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in exprs) -> void; + +#line 3198 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in prefix) -> void; + +#line 3214 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in prefix) -> void; + +#line 3219 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in postfix) -> void; + +#line 3235 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in postfix) -> void; + +#line 3254 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in uid) -> void; + +#line 3260 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in qid) -> void; + +#line 3270 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in tid) -> void; + +#line 3287 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in primary) -> void; + +#line 3307 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in idexpr) -> void; + public: simple_traverser() = default; + public: simple_traverser(simple_traverser const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(simple_traverser const&) -> void = delete; + + +#line 3322 "reflect.h2" +}; + +#line 3335 "reflect.h2" auto sample_traverser(cpp2::impl::in decl, cpp2::impl::in indent) -> void; -#line 2646 "reflect.h2" +#line 3357 "reflect.h2" auto sample_traverser(cpp2::impl::in f, cpp2::impl::in indent = 0) -> void; -#line 2676 "reflect.h2" +#line 3387 "reflect.h2" auto sample_traverser(cpp2::impl::in o, cpp2::impl::in indent) -> void; -#line 2686 "reflect.h2" +#line 3397 "reflect.h2" auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent = 0) -> void; -#line 2707 "reflect.h2" +#line 3418 "reflect.h2" auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent = 0) -> void; -#line 2726 "reflect.h2" +#line 3437 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2781 "reflect.h2" +#line 3492 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2798 "reflect.h2" +#line 3509 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2808 "reflect.h2" +#line 3519 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2840 "reflect.h2" +#line 3551 "reflect.h2" auto sample_traverser(cpp2::impl::in expr, cpp2::impl::in indent) -> void; -#line 2854 "reflect.h2" +#line 3565 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2884 "reflect.h2" +#line 3595 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2914 "reflect.h2" +#line 3625 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2944 "reflect.h2" +#line 3655 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2974 "reflect.h2" +#line 3685 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3004 "reflect.h2" +#line 3715 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3034 "reflect.h2" +#line 3745 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3064 "reflect.h2" +#line 3775 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3094 "reflect.h2" +#line 3805 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3124 "reflect.h2" +#line 3835 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3154 "reflect.h2" +#line 3865 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3184 "reflect.h2" +#line 3895 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3214 "reflect.h2" +#line 3925 "reflect.h2" auto sample_traverser(cpp2::impl::in isas, cpp2::impl::in indent) -> void; -#line 3240 "reflect.h2" +#line 3951 "reflect.h2" auto sample_traverser(cpp2::impl::in exprs, cpp2::impl::in indent) -> void; -#line 3255 "reflect.h2" +#line 3966 "reflect.h2" auto sample_traverser(cpp2::impl::in prefix, cpp2::impl::in indent) -> void; -#line 3279 "reflect.h2" +#line 3990 "reflect.h2" auto sample_traverser(cpp2::impl::in postfix, cpp2::impl::in indent) -> void; -#line 3312 "reflect.h2" +#line 4023 "reflect.h2" auto sample_traverser(cpp2::impl::in uid, cpp2::impl::in indent) -> void; -#line 3323 "reflect.h2" +#line 4034 "reflect.h2" auto sample_traverser(cpp2::impl::in qid, cpp2::impl::in indent) -> void; -#line 3339 "reflect.h2" +#line 4050 "reflect.h2" auto sample_traverser(cpp2::impl::in tid, cpp2::impl::in indent) -> void; -#line 3356 "reflect.h2" +#line 4067 "reflect.h2" auto sample_traverser(cpp2::impl::in primary, cpp2::impl::in indent) -> void; -#line 3376 "reflect.h2" +#line 4087 "reflect.h2" auto sample_traverser(cpp2::impl::in idexpr, cpp2::impl::in indent) -> void; -#line 3398 "reflect.h2" -class autodiff_impl { +#line 4109 "reflect.h2" +class autodiff_special_func { + public: std::string name; + public: int n_args; + public: bool is_member; + + public: std::string code_primal; + public: std::string code_fwd; + public: std::string code_rws; + public: std::string code_primal_higher_order; + public: std::string code_fwd_higher_order; + public: std::string code_rws_higher_order; + + public: autodiff_special_func(cpp2::impl::in name_, cpp2::impl::in n_args_, cpp2::impl::in is_member_, cpp2::impl::in code_primal_ = "", cpp2::impl::in code_fwd_ = "", + cpp2::impl::in code_rws_ = "", cpp2::impl::in code_primal_higher_order_ = "", cpp2::impl::in code_fwd_higher_order_ = "", + cpp2::impl::in code_rws_higher_order_ = ""); + +#line 4146 "reflect.h2" + public: autodiff_special_func(autodiff_special_func const& that); +#line 4146 "reflect.h2" + public: auto operator=(autodiff_special_func const& that) -> autodiff_special_func& ; +#line 4146 "reflect.h2" + public: autodiff_special_func(autodiff_special_func&& that) noexcept; +#line 4146 "reflect.h2" + public: auto operator=(autodiff_special_func&& that) noexcept -> autodiff_special_func& ; + + public: [[nodiscard]] auto is_match(cpp2::impl::in o) const& -> bool; + +#line 4151 "reflect.h2" +}; - private: int temporary_count {0}; +class autodiff_declared_variable { + public: std::string name {""}; + public: std::string decl {""}; + public: bool is_active {false}; + public: bool is_member {false}; - public: std::string diff {""}; + public: explicit autodiff_declared_variable(); - public: [[nodiscard]] auto gen_temporary() & -> std::string; + public: autodiff_declared_variable(cpp2::impl::in name_, cpp2::impl::in decl_, cpp2::impl::in is_active_, cpp2::impl::in is_member_); -#line 3409 "reflect.h2" - public: [[nodiscard]] auto handle_expression_term([[maybe_unused]] auto& unnamed_param_2, auto const& term) & -> std::string; +#line 4168 "reflect.h2" + public: autodiff_declared_variable(autodiff_declared_variable const& that); +#line 4168 "reflect.h2" + public: auto operator=(autodiff_declared_variable const& that) -> autodiff_declared_variable& ; +#line 4168 "reflect.h2" + public: autodiff_declared_variable(autodiff_declared_variable&& that) noexcept; +#line 4168 "reflect.h2" + public: auto operator=(autodiff_declared_variable&& that) noexcept -> autodiff_declared_variable& ; +}; + +class autodiff_declaration_stack_item { + public: std::string full_name; + public: meta::type_or_namespace_declaration decl; + + public: std::vector diff_request {}; + public: std::vector diff_done {}; + + public: std::vector> declared_variables_stack {1}; + + public: autodiff_declaration_stack_item(cpp2::impl::in full_name_, cpp2::impl::in decl_); +using lookup_declaration_ret = std::vector; + + +#line 4185 "reflect.h2" + public: [[nodiscard]] auto lookup_declaration(cpp2::impl::in decl_name) const& -> lookup_declaration_ret; +struct lookup_variable_declaration_ret { bool found; autodiff_declared_variable r; }; -#line 3421 "reflect.h2" - public: auto handle_expression_terms(auto& mf, cpp2::impl::in lhs, auto const& terms) & -> void; -#line 3714 "reflect.h2" - public: auto handle_expression_statement(auto& mf, auto const& expr) & -> void; - public: autodiff_impl() = default; - public: autodiff_impl(autodiff_impl const&) = delete; /* No 'that' constructor, suppress copy */ - public: auto operator=(autodiff_impl const&) -> void = delete; +#line 4195 "reflect.h2" + public: [[nodiscard]] auto lookup_variable_declaration(cpp2::impl::in decl_name) const& -> lookup_variable_declaration_ret; + public: autodiff_declaration_stack_item(autodiff_declaration_stack_item const& that); +public: autodiff_declaration_stack_item(autodiff_declaration_stack_item&& that) noexcept; -#line 3739 "reflect.h2" + +#line 4213 "reflect.h2" }; -auto autodiff(meta::type_declaration& t) -> void; +class autodiff_context { + private: int temporary_count {0}; -#line 3810 "reflect.h2" -using error_func = std::function x)>; +#line 4225 "reflect.h2" + public: std::vector special_funcs { + autodiff_special_func("sin", 1, false, + "sin(_a1_)", + "cos(_a1_) * _ad1_", + "_ab1_ += cos(_a1_) * _rb_;\n", + "sin(_a1_)", + "_ad1_.sin(_a1_)", + "TODO" + + ), + autodiff_special_func("cos", 1, false, + "cos(_a1_)", + "-sin(_a1_) * _ad1_", + "_ab1_ += -sin(_a1_) * _rb_;\n", + "cos(_a1_)", + "_ad1_.cos(_a1_)", + "TODO" + ), + autodiff_special_func("exp", 1, false, + "exp(_a1_)", + "exp(_a1_) * _ad1_", + "_ab1_ += exp(_a1_) * _rb_;\n", + "exp(_a1_)", + "_ad1_.exp(_a1_)", + "TODO" + ), + autodiff_special_func("sqrt", 1, false, + "sqrt(_a1_)", + "0.5 * _ad1_ / sqrt(_a1_)", + "_ab1_ += 0.5 * _rb_ / sqrt(_a1_);\n", + "sqrt(_a1_)", + "_ad1_.sqrt(_a1_)", + "TODO" + ), + autodiff_special_func("push_back", 1, true, + "_o_.push_back(_a1_);", + "_od_.push_back(_ad1_);", + "TODO")}; + +#line 4265 "reflect.h2" + public: std::string fwd_suffix {"_d"}; + public: std::string rws_suffix {"_b"}; + private: int order {1}; + public: bool reverse {false}; + +#line 4271 "reflect.h2" + public: std::string fwd_ad_type {"double"}; + public: std::string rws_ad_type {"double"}; + + public: std::map> declaration_map {}; + public: std::vector declaration_stack {}; + + public: explicit autodiff_context(); + public: autodiff_context(cpp2::impl::in order_, cpp2::impl::in reverse_); + +#line 4294 "reflect.h2" + public: auto add_variable_declaration(cpp2::impl::in name, cpp2::impl::in type, cpp2::impl::in is_active, cpp2::impl::in is_member = false) & -> void; + +#line 4298 "reflect.h2" + public: [[nodiscard]] auto is_variable_active(cpp2::impl::in name) & -> bool; + +#line 4302 "reflect.h2" + public: auto create_namespace_stack(cpp2::impl::in t) & -> void; + +#line 4319 "reflect.h2" + public: [[nodiscard]] auto is_forward() const& -> decltype(auto); + public: [[nodiscard]] auto is_reverse() const& -> decltype(auto); + public: [[nodiscard]] auto is_taylor() const& -> decltype(auto); -#line 3814 "reflect.h2" -class expression_flags - { -private: cpp2::u8 _value; private: constexpr expression_flags(cpp2::impl::in _val); + public: [[nodiscard]] auto gen_temporary() & -> std::string; + +#line 4328 "reflect.h2" + public: [[nodiscard]] auto is_type_active(cpp2::impl::in type) & -> bool; + +#line 4349 "reflect.h2" + public: [[nodiscard]] auto get_fwd_ad_type(cpp2::impl::in type) & -> std::string; + +#line 4367 "reflect.h2" + public: [[nodiscard]] auto get_rws_ad_type(cpp2::impl::in type) & -> std::string; + +#line 4385 "reflect.h2" + public: [[nodiscard]] auto get_reverse_passing_style(cpp2::impl::in p) const& -> passing_style; +using lookup_declaration_ret = std::vector; + + +#line 4413 "reflect.h2" + public: [[nodiscard]] auto lookup_declaration(cpp2::impl::in decl_name) & -> lookup_declaration_ret; + +#line 4440 "reflect.h2" + public: [[nodiscard]] auto lookup_variable_declaration(cpp2::impl::in name) & -> autodiff_declared_variable; +using lookup_function_declaration_ret = std::vector; + + +#line 4462 "reflect.h2" + public: [[nodiscard]] auto lookup_function_declaration(cpp2::impl::in decl_name) & -> lookup_function_declaration_ret; +using lookup_member_function_declaration_ret = std::vector; + + +#line 4472 "reflect.h2" + public: [[nodiscard]] auto lookup_member_function_declaration(cpp2::impl::in obj_type, cpp2::impl::in decl_name) & -> lookup_member_function_declaration_ret; +using lookup_type_declaration_ret = std::vector; + + +#line 4482 "reflect.h2" + public: [[nodiscard]] auto lookup_type_declaration(cpp2::impl::in decl_name) & -> lookup_type_declaration_ret; +struct lookup_special_function_handling_ret { bool m; std::string code_primal; std::string code_fwd; std::string code_rws; }; + + + +#line 4492 "reflect.h2" + public: [[nodiscard]] auto lookup_special_function_handling(cpp2::impl::in func_name, cpp2::impl::in n_args, cpp2::impl::in is_member) const& -> lookup_special_function_handling_ret; + +#line 4517 "reflect.h2" + public: auto add_as_differentiated(cpp2::impl::in t) & -> void; + +#line 4525 "reflect.h2" + public: auto add_for_differentiation(cpp2::impl::in t) & -> void; + +#line 4551 "reflect.h2" + public: [[nodiscard]] static auto is_in_list(cpp2::impl::in v, cpp2::impl::in> list) -> bool; + +#line 4561 "reflect.h2" + public: auto enter_function() & -> void; + +#line 4566 "reflect.h2" + public: auto leave_function() & -> void; + +#line 4570 "reflect.h2" + public: auto push_stack(cpp2::impl::in decl) & -> void; + +#line 4583 "reflect.h2" + public: auto pop_stack() & -> void; + +#line 4598 "reflect.h2" + public: auto finish() & -> void; + public: autodiff_context(autodiff_context const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(autodiff_context const&) -> void = delete; + + +#line 4603 "reflect.h2" +}; + +class autodiff_diff_code { + public: autodiff_context* ctx; + + public: std::string fwd {""}; + public: std::string rws_primal {""}; + public: std::string rws_backprop {""}; + + public: autodiff_diff_code(cpp2::impl::in ctx_); +#line 4612 "reflect.h2" + public: auto operator=(cpp2::impl::in ctx_) -> autodiff_diff_code& ; + +#line 4615 "reflect.h2" + public: autodiff_diff_code(autodiff_diff_code const& that); +#line 4615 "reflect.h2" + public: auto operator=(autodiff_diff_code const& that) -> autodiff_diff_code& ; +#line 4615 "reflect.h2" + public: autodiff_diff_code(autodiff_diff_code&& that) noexcept; +#line 4615 "reflect.h2" + public: auto operator=(autodiff_diff_code&& that) noexcept -> autodiff_diff_code& ; + + public: auto add_forward(cpp2::impl::in v) & -> void; + public: auto add_reverse_primal(cpp2::impl::in v) & -> void; + public: auto add_reverse_backprop(cpp2::impl::in v) & -> void; + + public: auto reset() & -> void; + +#line 4628 "reflect.h2" + public: auto operator=(cpp2::impl::in v) -> autodiff_diff_code& ; + +#line 4634 "reflect.h2" + public: auto operator+=(cpp2::impl::in v) & -> void; + +#line 4639 "reflect.h2" + public: auto operator+=(cpp2::impl::in v) & -> void; + +#line 4644 "reflect.h2" + public: [[nodiscard]] auto empty() const& -> bool; + +#line 4647 "reflect.h2" +}; + +#line 4654 "reflect.h2" +class autodiff_activity_check: public simple_traverser { + +#line 4657 "reflect.h2" + public: autodiff_context* ctx; + public: bool active {false}; + + public: autodiff_activity_check(cpp2::impl::in ctx_); + +#line 4664 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 4676 "reflect.h2" + public: auto traverse(cpp2::impl::in o) -> void override; + +#line 4694 "reflect.h2" + public: auto traverse(cpp2::impl::in primary) -> void override; + +#line 4718 "reflect.h2" + public: auto traverse(cpp2::impl::in postfix) -> void override; + public: autodiff_activity_check(autodiff_activity_check const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(autodiff_activity_check const&) -> void = delete; + + +#line 4750 "reflect.h2" +}; + +class autodiff_handler_base { + public: autodiff_context* ctx; + + public: autodiff_diff_code diff; + + public: autodiff_handler_base(cpp2::impl::in ctx_); +#line 4757 "reflect.h2" + public: auto operator=(cpp2::impl::in ctx_) -> autodiff_handler_base& ; + +#line 4763 "reflect.h2" + public: auto append(autodiff_handler_base const& o) & -> void; + public: autodiff_handler_base(autodiff_handler_base const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(autodiff_handler_base const&) -> void = delete; + + +#line 4768 "reflect.h2" +}; + +class autodiff_expression_handler: public simple_traverser, public autodiff_handler_base { + +#line 4774 "reflect.h2" + public: using base = simple_traverser; + + public: std::string primal_expr {""}; + public: std::string fwd_expr {""}; + public: std::string rws_expr {""}; + + public: autodiff_expression_handler(cpp2::impl::in ctx_); + +#line 4784 "reflect.h2" + public: [[nodiscard]] auto add_suffix_if_not_wildcard(cpp2::impl::in lhs, cpp2::impl::in suffix) const& -> std::string; + +#line 4793 "reflect.h2" + public: [[nodiscard]] auto prepare_backprop(cpp2::impl::in rhs_b, cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b) const& -> std::string; + +#line 4801 "reflect.h2" + public: [[nodiscard]] auto prepare_backprop(cpp2::impl::in rhs_b, cpp2::impl::in lhs) const& -> std::string; + + public: auto gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in rhs_b) & -> void; + +#line 4814 "reflect.h2" + public: [[nodiscard]] auto gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b) & -> decltype(auto); + + public: [[nodiscard]] auto gen_assignment(cpp2::impl::in lhs) & -> decltype(auto); + +#line 4820 "reflect.h2" + public: auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in rhs_b, cpp2::impl::in type, cpp2::impl::in type_d, cpp2::impl::in type_b) & -> void; + +#line 4832 "reflect.h2" + public: [[nodiscard]] auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in rhs_b, cpp2::impl::in type) & -> decltype(auto); + + public: [[nodiscard]] auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in type) & -> decltype(auto); + + public: [[nodiscard]] auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in type) & -> decltype(auto); + +#line 4841 "reflect.h2" + public: class primal_fwd_rws_name { + public: std::string primal {""}; + public: std::string fwd {""}; + public: std::string rws {""}; + public: bool active {false}; + public: primal_fwd_rws_name(auto const& primal_, auto const& fwd_, auto const& rws_, auto const& active_); +public: primal_fwd_rws_name(); + +#line 4846 "reflect.h2" + }; + + public: [[nodiscard]] auto handle_expression_list(cpp2::impl::in list) & -> std::vector; + +#line 4857 "reflect.h2" + public: [[nodiscard]] auto handle_expression_term(auto const& term) & -> primal_fwd_rws_name; + +#line 4918 "reflect.h2" + public: auto handle_function_call(cpp2::impl::in postfix, cpp2::impl::in has_return) & -> void; + +#line 5098 "reflect.h2" + public: [[nodiscard]] auto handle_special_function(cpp2::impl::in object, cpp2::impl::in object_d, cpp2::impl::in object_b, cpp2::impl::in function_name, cpp2::impl::in> args) & -> bool; + +#line 5143 "reflect.h2" + public: auto traverse(cpp2::impl::in expr) -> void override; + +#line 5147 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5151 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5155 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5159 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5163 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5167 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5171 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5175 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5179 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5183 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5187 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5229 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5316 "reflect.h2" + public: auto traverse(cpp2::impl::in isas) -> void override; + +#line 5320 "reflect.h2" + public: auto traverse(cpp2::impl::in prefix) -> void override; + +#line 5336 "reflect.h2" + public: auto traverse(cpp2::impl::in postfix) -> void override; + +#line 5376 "reflect.h2" + public: auto traverse(cpp2::impl::in primary) -> void override; + public: autodiff_expression_handler(autodiff_expression_handler const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(autodiff_expression_handler const&) -> void = delete; + + +#line 5411 "reflect.h2" +}; + +class autodiff_stmt_handler: public simple_traverser, public autodiff_handler_base { + +#line 5417 "reflect.h2" + public: using base = simple_traverser; + + private: meta::function_declaration mf; + + private: std::vector last_params {}; + private: std::vector overwritten {}; + + private: bool overwrite_push_pop {false}; + + public: autodiff_stmt_handler(cpp2::impl::in ctx_, cpp2::impl::in mf_); + +#line 5431 "reflect.h2" + public: [[nodiscard]] auto handle_stmt_parameters(cpp2::impl::in> params) & -> autodiff_diff_code; + +#line 5473 "reflect.h2" + public: auto traverse(cpp2::impl::in decl) -> void override; + +#line 5478 "reflect.h2" + public: auto traverse(cpp2::impl::in f) -> void override; + +#line 5483 "reflect.h2" + public: auto traverse(cpp2::impl::in o) -> void override; + +#line 5545 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 5550 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 5555 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 5562 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 5597 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 5613 "reflect.h2" + public: [[nodiscard]] auto reverse_next(cpp2::impl::in expr) const& -> std::string; + +#line 5628 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 5726 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 5737 "reflect.h2" + public: auto traverse(cpp2::impl::in expr) -> void override; + +#line 5741 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5792 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5796 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5800 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5804 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5808 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5812 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5816 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5820 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5824 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5828 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5832 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5836 "reflect.h2" + public: auto traverse(cpp2::impl::in isas) -> void override; + +#line 5840 "reflect.h2" + public: auto traverse(cpp2::impl::in prefix) -> void override; + +#line 5845 "reflect.h2" + public: auto traverse(cpp2::impl::in postfix) -> void override; + +#line 5877 "reflect.h2" + public: auto traverse(cpp2::impl::in primary) -> void override; + public: autodiff_stmt_handler(autodiff_stmt_handler const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(autodiff_stmt_handler const&) -> void = delete; + + +#line 5881 "reflect.h2" +}; + +class autodiff_declaration_handler: public simple_traverser, public autodiff_handler_base { + +#line 5887 "reflect.h2" + public: using base = simple_traverser; + + private: meta::type_or_namespace_declaration decl; + + private: bool is_type_context {false}; + private: std::string diff_ad_type {""}; + + public: autodiff_declaration_handler(cpp2::impl::in ctx_, cpp2::impl::in decl_); + +#line 5899 "reflect.h2" + public: auto traverse(cpp2::impl::in decl_) -> void override; + +#line 5904 "reflect.h2" + public: auto traverse(cpp2::impl::in f) -> void override; + +#line 6062 "reflect.h2" + public: auto traverse(cpp2::impl::in o) -> void override; + +#line 6090 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 6114 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 6119 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + public: autodiff_declaration_handler(autodiff_declaration_handler const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(autodiff_declaration_handler const&) -> void = delete; + + +#line 6122 "reflect.h2" +}; + +#line 6125 "reflect.h2" +auto autodiff(meta::type_declaration& t) -> void; + +#line 6227 "reflect.h2" +using error_func = std::function x)>; + +#line 6231 "reflect.h2" +class expression_flags + { +private: cpp2::u8 _value; private: constexpr expression_flags(cpp2::impl::in _val); private: constexpr auto operator=(cpp2::impl::in _val) -> expression_flags& ; public: constexpr auto operator|=(expression_flags const& that) & -> decltype(auto); @@ -1530,20 +2298,20 @@ public: [[nodiscard]] auto to_code() const& -> std::string; public: [[nodiscard]] static auto from_string(cpp2::impl::in s) -> expression_flags; public: [[nodiscard]] static auto from_code(cpp2::impl::in s) -> expression_flags; -#line 3822 "reflect.h2" +#line 6239 "reflect.h2" }; -#line 3830 "reflect.h2" +#line 6247 "reflect.h2" class regex_token { public: std::string string_rep; public: regex_token(cpp2::impl::in str); -#line 3838 "reflect.h2" +#line 6255 "reflect.h2" public: explicit regex_token(); -#line 3843 "reflect.h2" +#line 6260 "reflect.h2" public: virtual auto generate_code([[maybe_unused]] generation_context& unnamed_param_2) const -> void = 0; public: [[nodiscard]] virtual auto reverse() const -> std::shared_ptr = 0; @@ -1555,103 +2323,103 @@ class regex_token public: regex_token(regex_token const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(regex_token const&) -> void = delete; -#line 3849 "reflect.h2" +#line 6266 "reflect.h2" }; using token_ptr = std::shared_ptr; using token_vec = std::vector; -#line 3855 "reflect.h2" +#line 6272 "reflect.h2" // Adds a check in code generation. // class regex_token_check : public regex_token { -#line 3861 "reflect.h2" +#line 6278 "reflect.h2" private: std::string check; public: regex_token_check(cpp2::impl::in str, cpp2::impl::in check_); -#line 3868 "reflect.h2" +#line 6285 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 3872 "reflect.h2" +#line 6289 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; public: virtual ~regex_token_check() noexcept; public: regex_token_check(regex_token_check const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(regex_token_check const&) -> void = delete; -#line 3873 "reflect.h2" +#line 6290 "reflect.h2" }; -#line 3876 "reflect.h2" +#line 6293 "reflect.h2" // Adds code in code generation. // class regex_token_code : public regex_token { -#line 3882 "reflect.h2" +#line 6299 "reflect.h2" private: std::string code; public: regex_token_code(cpp2::impl::in str, cpp2::impl::in code_); -#line 3889 "reflect.h2" +#line 6306 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 3893 "reflect.h2" +#line 6310 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; public: virtual ~regex_token_code() noexcept; public: regex_token_code(regex_token_code const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(regex_token_code const&) -> void = delete; -#line 3894 "reflect.h2" +#line 6311 "reflect.h2" }; -#line 3897 "reflect.h2" +#line 6314 "reflect.h2" // Token that does not influence the matching. E.g. comment. // class regex_token_empty : public regex_token { -#line 3903 "reflect.h2" +#line 6320 "reflect.h2" public: regex_token_empty(cpp2::impl::in str); -#line 3907 "reflect.h2" +#line 6324 "reflect.h2" public: auto generate_code([[maybe_unused]] generation_context& unnamed_param_2) const -> void override; -#line 3911 "reflect.h2" +#line 6328 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; public: virtual ~regex_token_empty() noexcept; public: regex_token_empty(regex_token_empty const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(regex_token_empty const&) -> void = delete; -#line 3912 "reflect.h2" +#line 6329 "reflect.h2" }; -#line 3915 "reflect.h2" +#line 6332 "reflect.h2" // Represents a list of regex tokens as one token. // class regex_token_list : public regex_token { -#line 3921 "reflect.h2" +#line 6338 "reflect.h2" public: token_vec tokens; public: regex_token_list(cpp2::impl::in t); -#line 3928 "reflect.h2" +#line 6345 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 3934 "reflect.h2" +#line 6351 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; -#line 3940 "reflect.h2" +#line 6357 "reflect.h2" public: [[nodiscard]] static auto gen_string(cpp2::impl::in vec) -> std::string; -#line 3948 "reflect.h2" +#line 6365 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; public: virtual ~regex_token_list() noexcept; @@ -1659,10 +2427,10 @@ class regex_token_list public: auto operator=(regex_token_list const&) -> void = delete; -#line 3960 "reflect.h2" +#line 6377 "reflect.h2" }; -#line 3963 "reflect.h2" +#line 6380 "reflect.h2" // // Parse and generation context. // @@ -1678,33 +2446,33 @@ class parse_context_group_state // Start a new alternative. public: auto next_alternative() & -> void; -#line 3983 "reflect.h2" +#line 6400 "reflect.h2" // Swap this state with the other one. NOLINTNEXTLINE(performance-noexcept-swap) public: auto swap(parse_context_group_state& t) & -> void; -#line 3990 "reflect.h2" +#line 6407 "reflect.h2" // Convert this state into a regex token. public: [[nodiscard]] auto get_as_token() & -> token_ptr; -#line 4002 "reflect.h2" +#line 6419 "reflect.h2" // Add a token to the current matcher list. public: auto add(cpp2::impl::in token) & -> void; -#line 4007 "reflect.h2" +#line 6424 "reflect.h2" // True if current matcher list is empty. public: [[nodiscard]] auto empty() const& -> bool; -#line 4011 "reflect.h2" +#line 6428 "reflect.h2" // Apply optimizations to the matcher list. public: static auto post_process_list(token_vec& list) -> void; public: parse_context_group_state(auto const& cur_match_list_, auto const& alternate_match_lists_, auto const& modifiers_); public: parse_context_group_state(); -#line 4025 "reflect.h2" +#line 6442 "reflect.h2" }; -#line 4028 "reflect.h2" +#line 6445 "reflect.h2" // State for the branch reset. Takes care of the group numbering. See '(|)'. // class parse_context_branch_reset_state @@ -1717,25 +2485,25 @@ class parse_context_branch_reset_state // Next group identifier. public: [[nodiscard]] auto next() & -> int; -#line 4046 "reflect.h2" +#line 6463 "reflect.h2" // Set next group identifier. public: auto set_next(cpp2::impl::in g) & -> void; -#line 4052 "reflect.h2" +#line 6469 "reflect.h2" // Start a new alternative branch. public: auto next_alternative() & -> void; -#line 4059 "reflect.h2" +#line 6476 "reflect.h2" // Initialize for a branch reset group. public: auto set_active_reset(cpp2::impl::in restart) & -> void; public: parse_context_branch_reset_state(auto const& is_active_, auto const& cur_group_, auto const& max_group_, auto const& from_); public: parse_context_branch_reset_state(); -#line 4066 "reflect.h2" +#line 6483 "reflect.h2" }; -#line 4069 "reflect.h2" +#line 6486 "reflect.h2" // Context during parsing of the regular expressions. // // Keeps track of the distributed group identifiers, current parsed group and branch resets. @@ -1751,7 +2519,7 @@ class parse_context private: parse_context_group_state cur_group_state {}; private: parse_context_branch_reset_state cur_branch_reset_state {}; -#line 4085 "reflect.h2" +#line 6502 "reflect.h2" public: std::map named_groups {}; private: error_func error_out; // TODO: Declaring std::function fails for cpp2. @@ -1759,64 +2527,64 @@ class parse_context public: parse_context(cpp2::impl::in r, auto const& e); -#line 4096 "reflect.h2" +#line 6513 "reflect.h2" // State management functions // // Returned group state needs to be stored and provided in `end_group`. public: [[nodiscard]] auto start_group() & -> parse_context_group_state; -#line 4109 "reflect.h2" +#line 6526 "reflect.h2" // `old_state` argument needs to be from start group. public: [[nodiscard]] auto end_group(cpp2::impl::in old_state) & -> token_ptr; -#line 4117 "reflect.h2" +#line 6534 "reflect.h2" public: [[nodiscard]] auto get_modifiers() const& -> expression_flags; -#line 4121 "reflect.h2" +#line 6538 "reflect.h2" public: auto set_modifiers(cpp2::impl::in mod) & -> void; -#line 4125 "reflect.h2" +#line 6542 "reflect.h2" // Branch reset management functions // public: [[nodiscard]] auto branch_reset_new_state() & -> parse_context_branch_reset_state; -#line 4137 "reflect.h2" +#line 6554 "reflect.h2" public: auto branch_reset_restore_state(cpp2::impl::in old_state) & -> void; -#line 4144 "reflect.h2" +#line 6561 "reflect.h2" public: auto next_alternative() & -> void; -#line 4150 "reflect.h2" +#line 6567 "reflect.h2" // Regex token management // public: auto add_token(cpp2::impl::in token) & -> void; -#line 4156 "reflect.h2" +#line 6573 "reflect.h2" public: [[nodiscard]] auto has_token() const& -> bool; -#line 4160 "reflect.h2" +#line 6577 "reflect.h2" public: [[nodiscard]] auto pop_token() & -> token_ptr; -#line 4171 "reflect.h2" +#line 6588 "reflect.h2" public: [[nodiscard]] auto get_as_token() & -> token_ptr; -#line 4175 "reflect.h2" +#line 6592 "reflect.h2" // Group management // public: [[nodiscard]] auto get_cur_group() const& -> int; -#line 4181 "reflect.h2" +#line 6598 "reflect.h2" public: [[nodiscard]] auto next_group() & -> int; -#line 4185 "reflect.h2" +#line 6602 "reflect.h2" public: auto set_named_group(cpp2::impl::in name, cpp2::impl::in id) & -> void; -#line 4192 "reflect.h2" +#line 6609 "reflect.h2" public: [[nodiscard]] auto get_named_group(cpp2::impl::in name) const& -> int; -#line 4203 "reflect.h2" +#line 6620 "reflect.h2" // Position management functions // public: [[nodiscard]] auto current() const& -> char; @@ -1824,51 +2592,51 @@ class parse_context // Get the next token in the regex, skipping spaces according to the parameters. See `x` and `xx` modifiers. private: [[nodiscard]] auto get_next_position(cpp2::impl::in in_class, cpp2::impl::in no_skip) const& -> size_t; -#line 4247 "reflect.h2" +#line 6664 "reflect.h2" // Return true if next token is available. private: [[nodiscard]] auto next_impl(cpp2::impl::in in_class, cpp2::impl::in no_skip) & -> bool; -#line 4259 "reflect.h2" +#line 6676 "reflect.h2" public: [[nodiscard]] auto next() & -> decltype(auto); public: [[nodiscard]] auto next_in_class() & -> decltype(auto); public: [[nodiscard]] auto next_no_skip() & -> decltype(auto); public: [[nodiscard]] auto next_n(cpp2::impl::in n) & -> bool; -#line 4272 "reflect.h2" +#line 6689 "reflect.h2" public: [[nodiscard]] auto has_next() const& -> bool; private: [[nodiscard]] auto grab_until_impl(cpp2::impl::in e, cpp2::impl::out r, cpp2::impl::in any) & -> bool; -#line 4295 "reflect.h2" +#line 6712 "reflect.h2" public: [[nodiscard]] auto grab_until(cpp2::impl::in e, cpp2::impl::out r) & -> decltype(auto); public: [[nodiscard]] auto grab_until(cpp2::impl::in e, cpp2::impl::out r) & -> decltype(auto); public: [[nodiscard]] auto grab_until_one_of(cpp2::impl::in e, cpp2::impl::out r) & -> decltype(auto); public: [[nodiscard]] auto grab_n(cpp2::impl::in n, cpp2::impl::out r) & -> bool; -#line 4312 "reflect.h2" +#line 6729 "reflect.h2" public: [[nodiscard]] auto grab_number() & -> std::string; -#line 4333 "reflect.h2" +#line 6750 "reflect.h2" private: [[nodiscard]] auto peek_impl(cpp2::impl::in in_class) const& -> char; -#line 4343 "reflect.h2" +#line 6760 "reflect.h2" public: [[nodiscard]] auto peek() const& -> decltype(auto); public: [[nodiscard]] auto peek_in_class() const& -> decltype(auto); -#line 4347 "reflect.h2" +#line 6764 "reflect.h2" // Parsing functions // public: [[nodiscard]] auto parser_group_modifiers(cpp2::impl::in change_str, expression_flags& parser_modifiers) & -> bool; -#line 4403 "reflect.h2" +#line 6820 "reflect.h2" public: [[nodiscard]] auto parse_until(cpp2::impl::in term) & -> bool; -#line 4442 "reflect.h2" +#line 6859 "reflect.h2" public: [[nodiscard]] auto parse(cpp2::impl::in modifiers) & -> bool; -#line 4457 "reflect.h2" +#line 6874 "reflect.h2" // Misc functions public: [[nodiscard]] auto get_pos() const& -> decltype(auto); @@ -1880,10 +2648,10 @@ class parse_context public: auto operator=(parse_context const&) -> void = delete; -#line 4468 "reflect.h2" +#line 6885 "reflect.h2" }; -#line 4471 "reflect.h2" +#line 6888 "reflect.h2" // Context for one function generation. Generation of functions can be interleaved, // therefore we buffer the code for one function here. // @@ -1893,16 +2661,16 @@ class generation_function_context { public: auto add_tabs(cpp2::impl::in c) & -> void; -#line 4485 "reflect.h2" +#line 6902 "reflect.h2" public: auto remove_tabs(cpp2::impl::in c) & -> void; public: generation_function_context(auto const& code_, auto const& tabs_); public: generation_function_context(); -#line 4488 "reflect.h2" +#line 6905 "reflect.h2" }; -#line 4491 "reflect.h2" +#line 6908 "reflect.h2" // Context for generating the state machine. class generation_context { @@ -1922,68 +2690,68 @@ class generation_context // Add code line. public: auto add(cpp2::impl::in s) & -> void; -#line 4513 "reflect.h2" +#line 6930 "reflect.h2" // Add check for token. The check needs to be a function call that returns a boolean. public: auto add_check(cpp2::impl::in check) & -> void; -#line 4519 "reflect.h2" +#line 6936 "reflect.h2" // Add a stateful check. The check needs to return a `match_return`. public: auto add_statefull(cpp2::impl::in next_func, cpp2::impl::in check) & -> void; -#line 4528 "reflect.h2" +#line 6945 "reflect.h2" protected: auto start_func_named(cpp2::impl::in name) & -> void; -#line 4539 "reflect.h2" +#line 6956 "reflect.h2" protected: [[nodiscard]] auto start_func() & -> std::string; -#line 4546 "reflect.h2" +#line 6963 "reflect.h2" protected: auto end_func_statefull(cpp2::impl::in s) & -> void; -#line 4566 "reflect.h2" +#line 6983 "reflect.h2" // Generate the function for a token. public: [[nodiscard]] auto generate_func(cpp2::impl::in token) & -> std::string; -#line 4576 "reflect.h2" +#line 6993 "reflect.h2" // Generate the reset for a list of group identifiers. public: [[nodiscard]] auto generate_reset(cpp2::impl::in> groups) & -> std::string; -#line 4599 "reflect.h2" +#line 7016 "reflect.h2" // Name generation // protected: [[nodiscard]] auto gen_func_name() & -> std::string; -#line 4607 "reflect.h2" +#line 7024 "reflect.h2" public: [[nodiscard]] auto next_func_name() & -> std::string; -#line 4611 "reflect.h2" +#line 7028 "reflect.h2" protected: [[nodiscard]] auto gen_reset_func_name() & -> std::string; -#line 4617 "reflect.h2" +#line 7034 "reflect.h2" public: [[nodiscard]] auto gen_temp() & -> std::string; -#line 4623 "reflect.h2" +#line 7040 "reflect.h2" // Context management // public: [[nodiscard]] auto new_context() & -> generation_function_context*; -#line 4633 "reflect.h2" +#line 7050 "reflect.h2" public: auto finish_context() & -> void; -#line 4641 "reflect.h2" +#line 7058 "reflect.h2" // Misc functions // private: [[nodiscard]] auto get_current() & -> generation_function_context*; -#line 4647 "reflect.h2" +#line 7064 "reflect.h2" private: [[nodiscard]] auto get_base() & -> generation_function_context*; -#line 4651 "reflect.h2" +#line 7068 "reflect.h2" public: [[nodiscard]] auto get_entry_func() const& -> std::string; -#line 4655 "reflect.h2" +#line 7072 "reflect.h2" public: [[nodiscard]] auto create_named_group_lookup(cpp2::impl::in> named_groups) const& -> std::string; -#line 4679 "reflect.h2" +#line 7096 "reflect.h2" // Run the generation for the token. public: [[nodiscard]] auto run(cpp2::impl::in token) & -> std::string; public: generation_context() = default; @@ -1991,7 +2759,7 @@ class generation_context public: auto operator=(generation_context const&) -> void = delete; -#line 4685 "reflect.h2" +#line 7102 "reflect.h2" }; // Regex syntax: | Example: ab|ba @@ -2011,27 +2779,27 @@ class alternative_token public: auto operator=(alternative_token const&) -> void = delete; -#line 4704 "reflect.h2" +#line 7121 "reflect.h2" }; class alternative_token_gen : public regex_token { -#line 4710 "reflect.h2" +#line 7127 "reflect.h2" private: token_vec alternatives; public: alternative_token_gen(cpp2::impl::in a); -#line 4717 "reflect.h2" +#line 7134 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 4734 "reflect.h2" +#line 7151 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; -#line 4741 "reflect.h2" +#line 7158 "reflect.h2" public: [[nodiscard]] static auto gen_string(cpp2::impl::in a) -> std::string; -#line 4754 "reflect.h2" +#line 7171 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; public: virtual ~alternative_token_gen() noexcept; @@ -2039,19 +2807,19 @@ class alternative_token_gen public: auto operator=(alternative_token_gen const&) -> void = delete; -#line 4766 "reflect.h2" +#line 7183 "reflect.h2" }; -#line 4769 "reflect.h2" +#line 7186 "reflect.h2" // Regex syntax: . // class any_token : public regex_token_check { -#line 4775 "reflect.h2" +#line 7192 "reflect.h2" public: any_token(cpp2::impl::in single_line); -#line 4779 "reflect.h2" +#line 7196 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; public: virtual ~any_token() noexcept; @@ -2059,7 +2827,7 @@ class any_token public: auto operator=(any_token const&) -> void = delete; -#line 4784 "reflect.h2" +#line 7201 "reflect.h2" }; // Regex syntax: (?>) Example: a(?>bc|c)c @@ -2067,17 +2835,17 @@ class any_token class atomic_group_token : public regex_token { -#line 4792 "reflect.h2" +#line 7209 "reflect.h2" public: token_ptr inner_token {nullptr}; public: explicit atomic_group_token(); public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 4803 "reflect.h2" +#line 7220 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 4811 "reflect.h2" +#line 7228 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~atomic_group_token() noexcept; @@ -2085,7 +2853,7 @@ class atomic_group_token public: auto operator=(atomic_group_token const&) -> void = delete; -#line 4814 "reflect.h2" +#line 7231 "reflect.h2" }; // Regex syntax: a @@ -2093,34 +2861,34 @@ class atomic_group_token class char_token : public regex_token { -#line 4822 "reflect.h2" +#line 7239 "reflect.h2" private: std::string token; private: bool ignore_case; public: char_token(cpp2::impl::in t, cpp2::impl::in ignore_case_); -#line 4831 "reflect.h2" +#line 7248 "reflect.h2" public: char_token(cpp2::impl::in t, cpp2::impl::in ignore_case_); -#line 4837 "reflect.h2" +#line 7254 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 4841 "reflect.h2" +#line 7258 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 4864 "reflect.h2" +#line 7281 "reflect.h2" public: auto gen_case_insensitive(cpp2::impl::in lower, cpp2::impl::in upper, generation_context& ctx) const& -> void; -#line 4885 "reflect.h2" +#line 7302 "reflect.h2" public: auto gen_case_sensitive(generation_context& ctx) const& -> void; -#line 4903 "reflect.h2" +#line 7320 "reflect.h2" public: [[nodiscard]] auto add_escapes(std::string str) const& -> std::string; -#line 4918 "reflect.h2" +#line 7335 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 4924 "reflect.h2" +#line 7341 "reflect.h2" public: auto append(char_token const& that) & -> void; public: virtual ~char_token() noexcept; @@ -2128,33 +2896,33 @@ class char_token public: auto operator=(char_token const&) -> void = delete; -#line 4928 "reflect.h2" +#line 7345 "reflect.h2" }; -#line 4931 "reflect.h2" +#line 7348 "reflect.h2" // Regex syntax: [] Example: [abcx-y[:digits:]] // class class_token : public regex_token { -#line 4937 "reflect.h2" +#line 7354 "reflect.h2" private: bool negate; private: bool case_insensitive; private: std::string class_str; public: class_token(cpp2::impl::in negate_, cpp2::impl::in case_insensitive_, cpp2::impl::in class_str_, cpp2::impl::in str); -#line 4949 "reflect.h2" +#line 7366 "reflect.h2" // TODO: Rework class generation: Generate check functions for classes. public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 5075 "reflect.h2" +#line 7492 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5084 "reflect.h2" +#line 7501 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 5089 "reflect.h2" +#line 7506 "reflect.h2" private: [[nodiscard]] static auto create_matcher(cpp2::impl::in name, cpp2::impl::in template_arguments) -> std::string; public: virtual ~class_token() noexcept; @@ -2162,20 +2930,20 @@ class class_token public: auto operator=(class_token const&) -> void = delete; -#line 5096 "reflect.h2" +#line 7513 "reflect.h2" }; -#line 5099 "reflect.h2" +#line 7516 "reflect.h2" // Regex syntax: \a or \n or \[ // [[nodiscard]] auto escape_token_parse(parse_context& ctx) -> token_ptr; -#line 5140 "reflect.h2" +#line 7557 "reflect.h2" // Regex syntax: \K Example: ab\Kcd // [[nodiscard]] auto global_group_reset_token_parse(parse_context& ctx) -> token_ptr; -#line 5151 "reflect.h2" +#line 7568 "reflect.h2" // Regex syntax: \ Example: \1 // \g{name_or_number} // \k{name_or_number} @@ -2185,20 +2953,20 @@ class class_token class group_ref_token : public regex_token { -#line 5161 "reflect.h2" +#line 7578 "reflect.h2" private: int id; private: bool case_insensitive; private: bool reverse_eval; public: group_ref_token(cpp2::impl::in id_, cpp2::impl::in case_insensitive_, cpp2::impl::in reverse_, cpp2::impl::in str); -#line 5173 "reflect.h2" +#line 7590 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 5274 "reflect.h2" +#line 7691 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5278 "reflect.h2" +#line 7695 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; public: virtual ~group_ref_token() noexcept; @@ -2206,10 +2974,10 @@ class group_ref_token public: auto operator=(group_ref_token const&) -> void = delete; -#line 5281 "reflect.h2" +#line 7698 "reflect.h2" }; -#line 5284 "reflect.h2" +#line 7701 "reflect.h2" // Regex syntax: () Example: (abc) // (?:) (?i:abc) @@ -2223,29 +2991,29 @@ class group_ref_token class group_token : public regex_token { -#line 5298 "reflect.h2" +#line 7715 "reflect.h2" private: int number {-1}; private: bool reverse_eval {false}; private: token_ptr inner {nullptr}; public: [[nodiscard]] static auto parse_lookahead_lookbehind(parse_context& ctx, cpp2::impl::in syntax, cpp2::impl::in lookahead, cpp2::impl::in positive) -> token_ptr; -#line 5320 "reflect.h2" +#line 7737 "reflect.h2" public: [[nodiscard]] static auto parse_atomic_pattern(parse_context& ctx, cpp2::impl::in syntax) -> token_ptr; -#line 5334 "reflect.h2" +#line 7751 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 5493 "reflect.h2" +#line 7910 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5501 "reflect.h2" +#line 7918 "reflect.h2" public: [[nodiscard]] static auto gen_string(cpp2::impl::in name, cpp2::impl::in name_brackets, cpp2::impl::in has_modifier, cpp2::impl::in modifiers, cpp2::impl::in inner_) -> std::string; -#line 5519 "reflect.h2" +#line 7936 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 5550 "reflect.h2" +#line 7967 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~group_token() noexcept; @@ -2254,25 +3022,25 @@ class group_token public: auto operator=(group_token const&) -> void = delete; -#line 5557 "reflect.h2" +#line 7974 "reflect.h2" }; -#line 5560 "reflect.h2" +#line 7977 "reflect.h2" // Regex syntax: \x or \x{} Example: \x{62} // [[nodiscard]] auto hexadecimal_token_parse(parse_context& ctx) -> token_ptr; -#line 5601 "reflect.h2" +#line 8018 "reflect.h2" // Regex syntax: $ Example: aa$ // [[nodiscard]] auto line_end_token_parse(parse_context& ctx) -> token_ptr; -#line 5621 "reflect.h2" +#line 8038 "reflect.h2" // Regex syntax: ^ Example: ^aa // [[nodiscard]] auto line_start_token_parse(parse_context& ctx) -> token_ptr; -#line 5637 "reflect.h2" +#line 8054 "reflect.h2" // Regex syntax: (?=) or (?!) or (*pla), etc. Example: (?=AA) // // Parsed in group_token. @@ -2280,20 +3048,20 @@ class group_token class lookahead_lookbehind_token : public regex_token { -#line 5645 "reflect.h2" +#line 8062 "reflect.h2" protected: bool lookahead; protected: bool positive; public: token_ptr inner {nullptr}; public: lookahead_lookbehind_token(cpp2::impl::in lookahead_, cpp2::impl::in positive_); -#line 5654 "reflect.h2" +#line 8071 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 5665 "reflect.h2" +#line 8082 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5672 "reflect.h2" +#line 8089 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~lookahead_lookbehind_token() noexcept; @@ -2301,26 +3069,26 @@ class lookahead_lookbehind_token public: auto operator=(lookahead_lookbehind_token const&) -> void = delete; -#line 5675 "reflect.h2" +#line 8092 "reflect.h2" }; -#line 5678 "reflect.h2" +#line 8095 "reflect.h2" // Named character classes // [[nodiscard]] auto named_class_token_parse(parse_context& ctx) -> token_ptr; -#line 5706 "reflect.h2" +#line 8123 "reflect.h2" // Regex syntax: \o{} Example: \o{142} // [[nodiscard]] auto octal_token_parse(parse_context& ctx) -> token_ptr; -#line 5734 "reflect.h2" +#line 8151 "reflect.h2" // Regex syntax: {min, max} Example: a{2,4} // class range_token : public regex_token { -#line 5740 "reflect.h2" +#line 8157 "reflect.h2" protected: int min_count {-1}; protected: int max_count {-1}; protected: int kind {range_flags::greedy}; @@ -2330,22 +3098,22 @@ class range_token public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 5820 "reflect.h2" +#line 8237 "reflect.h2" public: auto parse_modifier(parse_context& ctx) & -> void; -#line 5832 "reflect.h2" +#line 8249 "reflect.h2" public: [[nodiscard]] auto gen_mod_string() const& -> std::string; -#line 5845 "reflect.h2" +#line 8262 "reflect.h2" public: [[nodiscard]] auto gen_range_string() const& -> std::string; -#line 5864 "reflect.h2" +#line 8281 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5874 "reflect.h2" +#line 8291 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 5885 "reflect.h2" +#line 8302 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~range_token() noexcept; @@ -2353,16 +3121,16 @@ class range_token public: auto operator=(range_token const&) -> void = delete; -#line 5888 "reflect.h2" +#line 8305 "reflect.h2" }; -#line 5891 "reflect.h2" +#line 8308 "reflect.h2" // Regex syntax: *, +, or ? Example: aa* // class special_range_token : public range_token { -#line 5897 "reflect.h2" +#line 8314 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; public: virtual ~special_range_token() noexcept; @@ -2371,7 +3139,7 @@ class special_range_token public: auto operator=(special_range_token const&) -> void = delete; -#line 5927 "reflect.h2" +#line 8344 "reflect.h2" }; // Regex syntax: \G Example: \Gaa @@ -2380,14 +3148,14 @@ class special_range_token // [[nodiscard]] auto start_match_parse(parse_context& ctx) -> token_ptr; -#line 5949 "reflect.h2" +#line 8366 "reflect.h2" // Regex syntax: \b or \B Example: \bword\b // // Matches the start end end of word boundaries. // [[nodiscard]] auto word_boundary_token_parse(parse_context& ctx) -> token_ptr; -#line 5971 "reflect.h2" +#line 8388 "reflect.h2" //----------------------------------------------------------------------- // // Parser for regular expression. @@ -2408,24 +3176,24 @@ template class regex_generator public: regex_generator(cpp2::impl::in r, Error_out const& e); -#line 5994 "reflect.h2" +#line 8411 "reflect.h2" public: [[nodiscard]] auto parse() & -> std::string; -#line 6029 "reflect.h2" +#line 8446 "reflect.h2" private: auto extract_modifiers() & -> void; public: regex_generator(regex_generator const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(regex_generator const&) -> void = delete; -#line 6043 "reflect.h2" +#line 8460 "reflect.h2" }; template [[nodiscard]] auto generate_regex(cpp2::impl::in regex, Err const& err) -> std::string; -#line 6055 "reflect.h2" +#line 8472 "reflect.h2" auto regex_gen(meta::type_declaration& t) -> void; -#line 6110 "reflect.h2" +#line 8527 "reflect.h2" //----------------------------------------------------------------------- // // apply_metafunctions @@ -2436,7 +3204,7 @@ auto regex_gen(meta::type_declaration& t) -> void; auto const& error ) -> bool; -#line 6242 "reflect.h2" +#line 8659 "reflect.h2" } } @@ -2703,15 +3471,20 @@ compiler_services::compiler_services(compiler_services&& that) noexcept #line 231 "reflect.h2" template [[nodiscard]] auto reflection_base::print() const& -> std::string { return CPP2_UFCS(pretty_print_visualize)((*cpp2::impl::assert_not_null(n)), 0); } +#line 233 "reflect.h2" + template [[nodiscard]] auto reflection_base::is_same(cpp2::impl::in o) const& -> bool { return n == o.n; }// Test pointers +#line 234 "reflect.h2" + template template [[nodiscard]] auto reflection_base::is_same([[maybe_unused]] reflection_base const& unnamed_param_2) const& -> bool { return false; } + template reflection_base::~reflection_base() noexcept{} template reflection_base::reflection_base(reflection_base const& that) : compiler_services{ static_cast(that) } , n{ that.n }{} template reflection_base::reflection_base(reflection_base&& that) noexcept : compiler_services{ static_cast(that) } - , n{ std::move(that).n }{} + , n{ std::move(that).n }{}// Different types => false -#line 235 "reflect.h2" +#line 238 "reflect.h2" //----------------------------------------------------------------------- // // Declarations @@ -2723,126 +3496,126 @@ template reflection_base::reflection_base(reflection_base&& that // All declarations // -#line 249 "reflect.h2" +#line 252 "reflect.h2" declaration::declaration( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 254 "reflect.h2" +#line 257 "reflect.h2" { } -#line 258 "reflect.h2" +#line 261 "reflect.h2" [[nodiscard]] auto declaration::is_public() const& -> bool { return CPP2_UFCS(is_public)((*cpp2::impl::assert_not_null(n))); } -#line 259 "reflect.h2" +#line 262 "reflect.h2" [[nodiscard]] auto declaration::is_protected() const& -> bool { return CPP2_UFCS(is_protected)((*cpp2::impl::assert_not_null(n))); } -#line 260 "reflect.h2" +#line 263 "reflect.h2" [[nodiscard]] auto declaration::is_private() const& -> bool { return CPP2_UFCS(is_private)((*cpp2::impl::assert_not_null(n))); } -#line 261 "reflect.h2" +#line 264 "reflect.h2" [[nodiscard]] auto declaration::is_default_access() const& -> bool { return CPP2_UFCS(is_default_access)((*cpp2::impl::assert_not_null(n))); } -#line 263 "reflect.h2" +#line 266 "reflect.h2" [[nodiscard]] auto declaration::default_to_public() & -> decltype(auto) { return static_cast(CPP2_UFCS(make_public)((*cpp2::impl::assert_not_null(n)))); } -#line 264 "reflect.h2" +#line 267 "reflect.h2" [[nodiscard]] auto declaration::default_to_protected() & -> decltype(auto) { return static_cast(CPP2_UFCS(make_protected)((*cpp2::impl::assert_not_null(n)))); } -#line 265 "reflect.h2" +#line 268 "reflect.h2" [[nodiscard]] auto declaration::default_to_private() & -> decltype(auto) { return static_cast(CPP2_UFCS(make_private)((*cpp2::impl::assert_not_null(n)))); } -#line 267 "reflect.h2" +#line 270 "reflect.h2" [[nodiscard]] auto declaration::make_public() & -> bool { return CPP2_UFCS(make_public)((*cpp2::impl::assert_not_null(n))); } -#line 268 "reflect.h2" +#line 271 "reflect.h2" [[nodiscard]] auto declaration::make_protected() & -> bool { return CPP2_UFCS(make_protected)((*cpp2::impl::assert_not_null(n))); } -#line 269 "reflect.h2" +#line 272 "reflect.h2" [[nodiscard]] auto declaration::make_private() & -> bool { return CPP2_UFCS(make_private)((*cpp2::impl::assert_not_null(n))); } -#line 271 "reflect.h2" +#line 274 "reflect.h2" [[nodiscard]] auto declaration::has_name() const& -> bool { return CPP2_UFCS(has_name)((*cpp2::impl::assert_not_null(n))); } -#line 272 "reflect.h2" +#line 275 "reflect.h2" [[nodiscard]] auto declaration::has_name(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_name)((*cpp2::impl::assert_not_null(n)), s); } -#line 274 "reflect.h2" +#line 277 "reflect.h2" [[nodiscard]] auto declaration::name() const& -> std::string_view{ if (has_name()) {return CPP2_UFCS(as_string_view)((*cpp2::impl::assert_not_null(CPP2_UFCS(name)(*cpp2::impl::assert_not_null(n))))); } else { return ""; } } -#line 279 "reflect.h2" +#line 282 "reflect.h2" [[nodiscard]] auto declaration::has_initializer() const& -> bool { return CPP2_UFCS(has_initializer)((*cpp2::impl::assert_not_null(n))); } -#line 281 "reflect.h2" +#line 284 "reflect.h2" [[nodiscard]] auto declaration::get_initializer() const& -> statement { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(n)).initializer), (*this) }; } -#line 283 "reflect.h2" +#line 286 "reflect.h2" [[nodiscard]] auto declaration::is_global() const& -> bool { return CPP2_UFCS(is_global)((*cpp2::impl::assert_not_null(n))); } -#line 284 "reflect.h2" +#line 287 "reflect.h2" [[nodiscard]] auto declaration::is_function() const& -> bool { return CPP2_UFCS(is_function)((*cpp2::impl::assert_not_null(n))); } -#line 285 "reflect.h2" +#line 288 "reflect.h2" [[nodiscard]] auto declaration::is_object() const& -> bool { return CPP2_UFCS(is_object)((*cpp2::impl::assert_not_null(n))); } -#line 286 "reflect.h2" +#line 289 "reflect.h2" [[nodiscard]] auto declaration::is_base_object() const& -> bool { return CPP2_UFCS(is_base_object)((*cpp2::impl::assert_not_null(n))); } -#line 287 "reflect.h2" +#line 290 "reflect.h2" [[nodiscard]] auto declaration::is_member_object() const& -> bool { return CPP2_UFCS(is_member_object)((*cpp2::impl::assert_not_null(n))); } -#line 288 "reflect.h2" +#line 291 "reflect.h2" [[nodiscard]] auto declaration::is_type() const& -> bool { return CPP2_UFCS(is_type)((*cpp2::impl::assert_not_null(n))); } -#line 289 "reflect.h2" +#line 292 "reflect.h2" [[nodiscard]] auto declaration::is_namespace() const& -> bool { return CPP2_UFCS(is_namespace)((*cpp2::impl::assert_not_null(n))); } -#line 290 "reflect.h2" +#line 293 "reflect.h2" [[nodiscard]] auto declaration::is_alias() const& -> bool { return CPP2_UFCS(is_alias)((*cpp2::impl::assert_not_null(n))); } -#line 292 "reflect.h2" +#line 295 "reflect.h2" [[nodiscard]] auto declaration::is_type_alias() const& -> bool { return CPP2_UFCS(is_type_alias)((*cpp2::impl::assert_not_null(n))); } -#line 293 "reflect.h2" +#line 296 "reflect.h2" [[nodiscard]] auto declaration::is_namespace_alias() const& -> bool { return CPP2_UFCS(is_namespace_alias)((*cpp2::impl::assert_not_null(n))); } -#line 294 "reflect.h2" +#line 297 "reflect.h2" [[nodiscard]] auto declaration::is_object_alias() const& -> bool { return CPP2_UFCS(is_object_alias)((*cpp2::impl::assert_not_null(n))); } -#line 296 "reflect.h2" +#line 299 "reflect.h2" [[nodiscard]] auto declaration::is_function_expression() const& -> bool { return CPP2_UFCS(is_function_expression)((*cpp2::impl::assert_not_null(n))); } -#line 298 "reflect.h2" +#line 301 "reflect.h2" [[nodiscard]] auto declaration::as_function() const& -> function_declaration { return { n, (*this) }; } -#line 299 "reflect.h2" +#line 302 "reflect.h2" [[nodiscard]] auto declaration::as_object() const& -> object_declaration { return { n, (*this) }; } -#line 300 "reflect.h2" +#line 303 "reflect.h2" [[nodiscard]] auto declaration::as_type() const& -> type_declaration { return { n, (*this) }; } -#line 301 "reflect.h2" +#line 304 "reflect.h2" [[nodiscard]] auto declaration::as_nonglobal_namespace() const& -> namespace_declaration { return { n, (*this) }; } -#line 302 "reflect.h2" +#line 305 "reflect.h2" [[nodiscard]] auto declaration::as_alias() const& -> alias_declaration { return { n, (*this) }; } -#line 304 "reflect.h2" +#line 307 "reflect.h2" [[nodiscard]] auto declaration::get_parent() const& -> declaration { return declaration((*cpp2::impl::assert_not_null(n)).parent_declaration, (*this)); } -#line 306 "reflect.h2" +#line 309 "reflect.h2" [[nodiscard]] auto declaration::parent_is_function() const& -> bool { return CPP2_UFCS(parent_is_function)((*cpp2::impl::assert_not_null(n))); } -#line 307 "reflect.h2" +#line 310 "reflect.h2" [[nodiscard]] auto declaration::parent_is_object() const& -> bool { return CPP2_UFCS(parent_is_object)((*cpp2::impl::assert_not_null(n))); } -#line 308 "reflect.h2" +#line 311 "reflect.h2" [[nodiscard]] auto declaration::parent_is_type() const& -> bool { return CPP2_UFCS(parent_is_type)((*cpp2::impl::assert_not_null(n))); } -#line 309 "reflect.h2" +#line 312 "reflect.h2" [[nodiscard]] auto declaration::parent_is_nonglobal_namespace() const& -> bool { return CPP2_UFCS(parent_is_nonglobal_namespace)((*cpp2::impl::assert_not_null(n))); } -#line 310 "reflect.h2" +#line 313 "reflect.h2" [[nodiscard]] auto declaration::parent_is_alias() const& -> bool { return CPP2_UFCS(parent_is_alias)((*cpp2::impl::assert_not_null(n))); } -#line 312 "reflect.h2" +#line 315 "reflect.h2" [[nodiscard]] auto declaration::parent_is_type_alias() const& -> bool { return CPP2_UFCS(parent_is_type_alias)((*cpp2::impl::assert_not_null(n))); } -#line 313 "reflect.h2" +#line 316 "reflect.h2" [[nodiscard]] auto declaration::parent_is_namespace_alias() const& -> bool { return CPP2_UFCS(parent_is_namespace_alias)((*cpp2::impl::assert_not_null(n))); } -#line 314 "reflect.h2" +#line 317 "reflect.h2" [[nodiscard]] auto declaration::parent_is_object_alias() const& -> bool { return CPP2_UFCS(parent_is_object_alias)((*cpp2::impl::assert_not_null(n))); } -#line 316 "reflect.h2" +#line 319 "reflect.h2" [[nodiscard]] auto declaration::parent_is_polymorphic() const& -> bool { return CPP2_UFCS(parent_is_polymorphic)((*cpp2::impl::assert_not_null(n))); } -#line 318 "reflect.h2" +#line 321 "reflect.h2" auto declaration::mark_for_removal_from_enclosing_type() & -> void // this precondition should be sufficient ... { if (cpp2::type_safety.is_active() && !(parent_is_type()) ) { cpp2::type_safety.report_violation(""); } -#line 321 "reflect.h2" +#line 324 "reflect.h2" auto test {CPP2_UFCS(type_member_mark_for_removal)((*cpp2::impl::assert_not_null(n)))}; if (cpp2::cpp2_default.is_active() && !(cpp2::move(test)) ) { cpp2::cpp2_default.report_violation(""); }// ... to ensure this assert is true } @@ -2853,111 +3626,111 @@ declaration::declaration(declaration const& that) declaration::declaration(declaration&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 327 "reflect.h2" +#line 330 "reflect.h2" //----------------------------------------------------------------------- // Function declarations // -#line 334 "reflect.h2" +#line 337 "reflect.h2" function_declaration::function_declaration( cpp2::impl::in n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 339 "reflect.h2" +#line 342 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_function)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } } -#line 344 "reflect.h2" +#line 347 "reflect.h2" [[nodiscard]] auto function_declaration::index_of_parameter_named(cpp2::impl::in s) const& -> int { return CPP2_UFCS(index_of_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 345 "reflect.h2" +#line 348 "reflect.h2" [[nodiscard]] auto function_declaration::has_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 346 "reflect.h2" +#line 349 "reflect.h2" [[nodiscard]] auto function_declaration::has_return_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_return_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 347 "reflect.h2" +#line 350 "reflect.h2" [[nodiscard]] auto function_declaration::has_parameter_or_return_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_parameter_or_return_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 348 "reflect.h2" +#line 351 "reflect.h2" [[nodiscard]] auto function_declaration::has_in_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_in_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 349 "reflect.h2" +#line 352 "reflect.h2" [[nodiscard]] auto function_declaration::has_in_ref_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_in_ref_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 350 "reflect.h2" +#line 353 "reflect.h2" [[nodiscard]] auto function_declaration::has_copy_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_copy_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 351 "reflect.h2" +#line 354 "reflect.h2" [[nodiscard]] auto function_declaration::has_inout_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_inout_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 352 "reflect.h2" +#line 355 "reflect.h2" [[nodiscard]] auto function_declaration::has_out_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_out_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 353 "reflect.h2" +#line 356 "reflect.h2" [[nodiscard]] auto function_declaration::has_move_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_move_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 354 "reflect.h2" +#line 357 "reflect.h2" [[nodiscard]] auto function_declaration::has_forward_parameter_named(cpp2::impl::in s) const& -> bool { return CPP2_UFCS(has_forward_parameter_named)((*cpp2::impl::assert_not_null(n)), s); } -#line 355 "reflect.h2" +#line 358 "reflect.h2" [[nodiscard]] auto function_declaration::first_parameter_name() const& -> std::string { return CPP2_UFCS(first_parameter_name)((*cpp2::impl::assert_not_null(n))); } -#line 357 "reflect.h2" +#line 360 "reflect.h2" [[nodiscard]] auto function_declaration::has_parameter_with_name_and_pass(cpp2::impl::in s, cpp2::impl::in pass) const& -> bool { return CPP2_UFCS(has_parameter_with_name_and_pass)((*cpp2::impl::assert_not_null(n)), s, pass); } -#line 359 "reflect.h2" +#line 362 "reflect.h2" [[nodiscard]] auto function_declaration::is_function_with_this() const& -> bool { return CPP2_UFCS(is_function_with_this)((*cpp2::impl::assert_not_null(n))); } -#line 360 "reflect.h2" +#line 363 "reflect.h2" [[nodiscard]] auto function_declaration::is_virtual() const& -> bool { return CPP2_UFCS(is_virtual_function)((*cpp2::impl::assert_not_null(n))); } -#line 361 "reflect.h2" +#line 364 "reflect.h2" [[nodiscard]] auto function_declaration::is_defaultable() const& -> bool { return CPP2_UFCS(is_defaultable_function)((*cpp2::impl::assert_not_null(n))); } -#line 362 "reflect.h2" +#line 365 "reflect.h2" [[nodiscard]] auto function_declaration::is_constructor() const& -> bool { return CPP2_UFCS(is_constructor)((*cpp2::impl::assert_not_null(n))); } -#line 363 "reflect.h2" +#line 366 "reflect.h2" [[nodiscard]] auto function_declaration::is_default_constructor() const& -> bool { return CPP2_UFCS(is_default_constructor)((*cpp2::impl::assert_not_null(n))); } -#line 364 "reflect.h2" +#line 367 "reflect.h2" [[nodiscard]] auto function_declaration::is_move() const& -> bool { return CPP2_UFCS(is_move)((*cpp2::impl::assert_not_null(n))); } -#line 365 "reflect.h2" +#line 368 "reflect.h2" [[nodiscard]] auto function_declaration::is_swap() const& -> bool { return CPP2_UFCS(is_swap)((*cpp2::impl::assert_not_null(n))); } -#line 366 "reflect.h2" +#line 369 "reflect.h2" [[nodiscard]] auto function_declaration::is_constructor_with_that() const& -> bool { return CPP2_UFCS(is_constructor_with_that)((*cpp2::impl::assert_not_null(n))); } -#line 367 "reflect.h2" +#line 370 "reflect.h2" [[nodiscard]] auto function_declaration::is_constructor_with_in_that() const& -> bool { return CPP2_UFCS(is_constructor_with_in_that)((*cpp2::impl::assert_not_null(n))); } -#line 368 "reflect.h2" +#line 371 "reflect.h2" [[nodiscard]] auto function_declaration::is_constructor_with_move_that() const& -> bool { return CPP2_UFCS(is_constructor_with_move_that)((*cpp2::impl::assert_not_null(n))); } -#line 369 "reflect.h2" +#line 372 "reflect.h2" [[nodiscard]] auto function_declaration::is_assignment() const& -> bool { return CPP2_UFCS(is_assignment)((*cpp2::impl::assert_not_null(n))); } -#line 370 "reflect.h2" +#line 373 "reflect.h2" [[nodiscard]] auto function_declaration::is_assignment_with_that() const& -> bool { return CPP2_UFCS(is_assignment_with_that)((*cpp2::impl::assert_not_null(n))); } -#line 371 "reflect.h2" +#line 374 "reflect.h2" [[nodiscard]] auto function_declaration::is_assignment_with_in_that() const& -> bool { return CPP2_UFCS(is_assignment_with_in_that)((*cpp2::impl::assert_not_null(n))); } -#line 372 "reflect.h2" +#line 375 "reflect.h2" [[nodiscard]] auto function_declaration::is_assignment_with_move_that() const& -> bool { return CPP2_UFCS(is_assignment_with_move_that)((*cpp2::impl::assert_not_null(n))); } -#line 373 "reflect.h2" +#line 376 "reflect.h2" [[nodiscard]] auto function_declaration::is_destructor() const& -> bool { return CPP2_UFCS(is_destructor)((*cpp2::impl::assert_not_null(n))); } -#line 375 "reflect.h2" +#line 378 "reflect.h2" [[nodiscard]] auto function_declaration::is_copy_or_move() const& -> bool { return is_constructor_with_that() || is_assignment_with_that(); } -#line 377 "reflect.h2" +#line 380 "reflect.h2" [[nodiscard]] auto function_declaration::has_declared_return_type() const& -> bool { return CPP2_UFCS(has_declared_return_type)((*cpp2::impl::assert_not_null(n))); } -#line 378 "reflect.h2" +#line 381 "reflect.h2" [[nodiscard]] auto function_declaration::has_deduced_return_type() const& -> bool { return CPP2_UFCS(has_deduced_return_type)((*cpp2::impl::assert_not_null(n))); } -#line 379 "reflect.h2" +#line 382 "reflect.h2" [[nodiscard]] auto function_declaration::has_bool_return_type() const& -> bool { return CPP2_UFCS(has_bool_return_type)((*cpp2::impl::assert_not_null(n))); } -#line 380 "reflect.h2" +#line 383 "reflect.h2" [[nodiscard]] auto function_declaration::has_non_void_return_type() const& -> bool { return CPP2_UFCS(has_non_void_return_type)((*cpp2::impl::assert_not_null(n))); } -#line 382 "reflect.h2" +#line 385 "reflect.h2" [[nodiscard]] auto function_declaration::has_compound_body() const& -> bool { return CPP2_UFCS(is_function_with_compound_body)((*cpp2::impl::assert_not_null(n))); } -#line 384 "reflect.h2" +#line 387 "reflect.h2" [[nodiscard]] auto function_declaration::get_body() const& -> statement { return { CPP2_UFCS(get_function_body)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 385 "reflect.h2" +#line 388 "reflect.h2" [[nodiscard]] auto function_declaration::get_compound_body() const& -> compound_statement { return { CPP2_UFCS(get_function_compound_body)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 386 "reflect.h2" +#line 389 "reflect.h2" [[nodiscard]] auto function_declaration::get_unnamed_return_type() const& -> std::string { return CPP2_UFCS(unnamed_return_type_to_string)((*cpp2::impl::assert_not_null(n))); } -#line 387 "reflect.h2" +#line 390 "reflect.h2" [[nodiscard]] auto function_declaration::get_signature() const& -> std::string { return CPP2_UFCS(signature_to_string)((*cpp2::impl::assert_not_null(n))); } -#line 389 "reflect.h2" +#line 392 "reflect.h2" [[nodiscard]] auto function_declaration::is_binary_comparison_function() const& -> bool { return CPP2_UFCS(is_binary_comparison_function)((*cpp2::impl::assert_not_null(n))); } -#line 391 "reflect.h2" +#line 394 "reflect.h2" [[nodiscard]] auto function_declaration::get_parameters() const& -> std::vector { @@ -2968,7 +3741,7 @@ declaration::declaration(declaration&& that) noexcept return ret; } -#line 401 "reflect.h2" +#line 404 "reflect.h2" [[nodiscard]] auto function_declaration::get_returns() const& -> std::vector { @@ -2981,20 +3754,20 @@ declaration::declaration(declaration&& that) noexcept // Modifying operations // -#line 413 "reflect.h2" +#line 416 "reflect.h2" [[nodiscard]] auto function_declaration::default_to_virtual() & -> decltype(auto) { return static_cast(CPP2_UFCS(make_function_virtual)((*cpp2::impl::assert_not_null(n)))); } -#line 415 "reflect.h2" +#line 418 "reflect.h2" [[nodiscard]] auto function_declaration::make_virtual() & -> bool { return CPP2_UFCS(make_function_virtual)((*cpp2::impl::assert_not_null(n))); } -#line 417 "reflect.h2" +#line 420 "reflect.h2" auto function_declaration::add_initializer(cpp2::impl::in source) & -> void -#line 420 "reflect.h2" +#line 423 "reflect.h2" { if ((*this).is_active() && !(!(has_initializer())) ) { (*this).report_violation(CPP2_CONTRACT_MSG("cannot add an initializer to a function that already has one")); } if ((*this).is_active() && !(parent_is_type()) ) { (*this).report_violation(CPP2_CONTRACT_MSG("cannot add an initializer to a function that isn't in a type scope")); } -#line 421 "reflect.h2" +#line 424 "reflect.h2" auto stmt {parse_statement(source)}; if (!((cpp2::impl::as_(stmt)))) { error("cannot add an initializer that is not a valid statement"); @@ -3009,30 +3782,30 @@ declaration::declaration(declaration&& that) noexcept function_declaration::function_declaration(function_declaration&& that) noexcept : declaration{ static_cast(that) }{} -#line 432 "reflect.h2" +#line 435 "reflect.h2" //----------------------------------------------------------------------- // Object declarations // -#line 439 "reflect.h2" +#line 442 "reflect.h2" object_declaration::object_declaration( cpp2::impl::in n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 444 "reflect.h2" +#line 447 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_object)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } } -#line 449 "reflect.h2" +#line 452 "reflect.h2" [[nodiscard]] auto object_declaration::is_const() const& -> bool { return CPP2_UFCS(is_const)((*cpp2::impl::assert_not_null(n))); } -#line 450 "reflect.h2" +#line 453 "reflect.h2" [[nodiscard]] auto object_declaration::has_wildcard_type() const& -> bool { return CPP2_UFCS(has_wildcard_type)((*cpp2::impl::assert_not_null(n))); } -#line 452 "reflect.h2" +#line 455 "reflect.h2" [[nodiscard]] auto object_declaration::type() const& -> std::string{ auto ret {CPP2_UFCS(object_type)((*cpp2::impl::assert_not_null(n)))}; require(!(contains(ret, "(*ERROR*)")), @@ -3040,7 +3813,7 @@ function_declaration::function_declaration(function_declaration&& that) noexcept return ret; } -#line 459 "reflect.h2" +#line 462 "reflect.h2" [[nodiscard]] auto object_declaration::initializer() const& -> std::string{ auto ret {CPP2_UFCS(object_initializer)((*cpp2::impl::assert_not_null(n)))}; require(!(contains(ret, "(*ERROR*)")), @@ -3053,25 +3826,25 @@ function_declaration::function_declaration(function_declaration&& that) noexcept object_declaration::object_declaration(object_declaration&& that) noexcept : declaration{ static_cast(that) }{} -#line 468 "reflect.h2" +#line 471 "reflect.h2" //----------------------------------------------------------------------- // Type and namespace declarations // -#line 475 "reflect.h2" +#line 478 "reflect.h2" type_or_namespace_declaration::type_or_namespace_declaration( cpp2::impl::in n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 480 "reflect.h2" +#line 483 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_type)((*cpp2::impl::assert_not_null(n))) || CPP2_UFCS(is_namespace)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } } -#line 485 "reflect.h2" +#line 488 "reflect.h2" auto type_or_namespace_declaration::reserve_names(cpp2::impl::in name, auto&& ...etc) const& -> void { // etc is not declared ':string_view' for compatibility with GCC 10.x for ( @@ -3086,7 +3859,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept } } -#line 499 "reflect.h2" +#line 502 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_functions() const& -> std::vector { @@ -3098,7 +3871,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 510 "reflect.h2" +#line 513 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_functions_needing_initializer() const& -> std::vector { @@ -3114,7 +3887,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 525 "reflect.h2" +#line 528 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_objects() const& -> std::vector { @@ -3125,7 +3898,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 535 "reflect.h2" +#line 538 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_types() const& -> std::vector { @@ -3136,7 +3909,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 545 "reflect.h2" +#line 548 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_aliases() const& -> std::vector { @@ -3147,7 +3920,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 555 "reflect.h2" +#line 558 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_members() const& -> std::vector { @@ -3158,7 +3931,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 565 "reflect.h2" +#line 568 "reflect.h2" auto type_or_namespace_declaration::add_member(cpp2::impl::in source) & -> void { auto decl {parse_statement(source)}; @@ -3169,6 +3942,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept if (!(CPP2_UFCS(is_declaration)((*cpp2::impl::assert_not_null(decl))))) { error("cannot add a member that is not a declaration"); } + require(CPP2_UFCS(add_type_or_namespace_member)((*cpp2::impl::assert_not_null(n)), std::move(cpp2::move(decl))), std::string("unexpected error while attempting to add member:\n") + source); } @@ -3178,36 +3952,36 @@ object_declaration::object_declaration(object_declaration&& that) noexcept type_or_namespace_declaration::type_or_namespace_declaration(type_or_namespace_declaration&& that) noexcept : declaration{ static_cast(that) }{} -#line 585 "reflect.h2" +#line 589 "reflect.h2" type_declaration::type_declaration( cpp2::impl::in n_, cpp2::impl::in s ) : type_or_namespace_declaration{ n_, s } -#line 590 "reflect.h2" +#line 594 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_type)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } } -#line 596 "reflect.h2" +#line 600 "reflect.h2" [[nodiscard]] auto type_declaration::is_polymorphic() const& -> bool { return CPP2_UFCS(is_polymorphic)((*cpp2::impl::assert_not_null(n))); } -#line 597 "reflect.h2" +#line 601 "reflect.h2" [[nodiscard]] auto type_declaration::is_final() const& -> bool { return CPP2_UFCS(is_type_final)((*cpp2::impl::assert_not_null(n))); } -#line 598 "reflect.h2" +#line 602 "reflect.h2" [[nodiscard]] auto type_declaration::make_final() & -> bool { return CPP2_UFCS(make_type_final)((*cpp2::impl::assert_not_null(n))); } -#line 600 "reflect.h2" +#line 604 "reflect.h2" [[nodiscard]] auto type_declaration::query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret -#line 607 "reflect.h2" +#line 611 "reflect.h2" { cpp2::impl::deferred_init out_this_in_that; cpp2::impl::deferred_init out_this_move_that; cpp2::impl::deferred_init inout_this_in_that; cpp2::impl::deferred_init inout_this_move_that; -#line 608 "reflect.h2" +#line 612 "reflect.h2" auto declared {CPP2_UFCS(find_declared_value_set_functions)((*cpp2::impl::assert_not_null(n)))}; out_this_in_that.construct(declared.out_this_in_that != nullptr); out_this_move_that.construct(declared.out_this_move_that != nullptr); @@ -3216,15 +3990,15 @@ type_or_namespace_declaration::type_or_namespace_declaration(type_or_namespace_d return { std::move(out_this_in_that.value()), std::move(out_this_move_that.value()), std::move(inout_this_in_that.value()), std::move(inout_this_move_that.value()) }; // NOLINT(performance-move-const-arg) } -#line 616 "reflect.h2" +#line 620 "reflect.h2" [[nodiscard]] auto type_declaration::disable_member_function_generation() & -> decltype(auto) { return CPP2_UFCS(type_disable_member_function_generation)((*cpp2::impl::assert_not_null(n))); } -#line 617 "reflect.h2" +#line 621 "reflect.h2" [[nodiscard]] auto type_declaration::disable_ref_qualifier_generation() & -> decltype(auto) { return CPP2_UFCS(type_disable_ref_qualifier_generation)((*cpp2::impl::assert_not_null(n))); } // At some point we may want to allow this also for namespaces, but for now only types -#line 620 "reflect.h2" +#line 624 "reflect.h2" [[nodiscard]] auto type_declaration::remove_marked_members() & -> decltype(auto) { return CPP2_UFCS(type_remove_marked_members)((*cpp2::impl::assert_not_null(n))); } -#line 621 "reflect.h2" +#line 625 "reflect.h2" [[nodiscard]] auto type_declaration::remove_all_members() & -> decltype(auto) { return CPP2_UFCS(type_remove_all_members)((*cpp2::impl::assert_not_null(n))); } type_declaration::type_declaration(type_declaration const& that) @@ -3232,14 +4006,14 @@ type_or_namespace_declaration::type_or_namespace_declaration(type_or_namespace_d type_declaration::type_declaration(type_declaration&& that) noexcept : type_or_namespace_declaration{ static_cast(that) }{} -#line 629 "reflect.h2" +#line 633 "reflect.h2" namespace_declaration::namespace_declaration( cpp2::impl::in n_, cpp2::impl::in s ) : type_or_namespace_declaration{ n_, s } -#line 634 "reflect.h2" +#line 638 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_namespace)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } @@ -3250,19 +4024,19 @@ type_declaration::type_declaration(type_declaration&& that) noexcept namespace_declaration::namespace_declaration(namespace_declaration&& that) noexcept : type_or_namespace_declaration{ static_cast(that) }{} -#line 641 "reflect.h2" +#line 645 "reflect.h2" //----------------------------------------------------------------------- // Alias declarations // -#line 648 "reflect.h2" +#line 652 "reflect.h2" alias_declaration::alias_declaration( cpp2::impl::in n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 653 "reflect.h2" +#line 657 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_alias)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } @@ -3273,35 +4047,35 @@ namespace_declaration::namespace_declaration(namespace_declaration&& that) noexc alias_declaration::alias_declaration(alias_declaration&& that) noexcept : declaration{ static_cast(that) }{} -#line 660 "reflect.h2" +#line 664 "reflect.h2" //----------------------------------------------------------------------- // Parameter declarations // -#line 667 "reflect.h2" +#line 671 "reflect.h2" parameter_declaration::parameter_declaration( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 672 "reflect.h2" +#line 676 "reflect.h2" { } -#line 676 "reflect.h2" +#line 680 "reflect.h2" [[nodiscard]] auto parameter_declaration::get_declaration() const& -> object_declaration { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(n)).declaration), (*this) }; } -#line 677 "reflect.h2" +#line 681 "reflect.h2" [[nodiscard]] auto parameter_declaration::get_passing_style() const& -> passing_style { return (*cpp2::impl::assert_not_null(n)).pass; } -#line 679 "reflect.h2" +#line 683 "reflect.h2" [[nodiscard]] auto parameter_declaration::is_implicit() const& -> bool { return (*cpp2::impl::assert_not_null(n)).mod == parameter_declaration_node::modifier::implicit; } -#line 680 "reflect.h2" +#line 684 "reflect.h2" [[nodiscard]] auto parameter_declaration::is_virtual() const& -> bool { return (*cpp2::impl::assert_not_null(n)).mod == parameter_declaration_node::modifier::virtual_; } -#line 681 "reflect.h2" +#line 685 "reflect.h2" [[nodiscard]] auto parameter_declaration::is_override() const& -> bool { return (*cpp2::impl::assert_not_null(n)).mod == parameter_declaration_node::modifier::override_; } -#line 682 "reflect.h2" +#line 686 "reflect.h2" [[nodiscard]] auto parameter_declaration::is_final() const& -> bool { return (*cpp2::impl::assert_not_null(n)).mod == parameter_declaration_node::modifier::final_; } parameter_declaration::parameter_declaration(parameter_declaration const& that) @@ -3309,7 +4083,7 @@ alias_declaration::alias_declaration(alias_declaration&& that) noexcept parameter_declaration::parameter_declaration(parameter_declaration&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 686 "reflect.h2" +#line 690 "reflect.h2" //----------------------------------------------------------------------- // // Expressions @@ -3321,45 +4095,45 @@ parameter_declaration::parameter_declaration(parameter_declaration&& that) noexc // Binary expressions // -#line 713 "reflect.h2" +#line 717 "reflect.h2" template binary_expression::binary_expression( binary_expression_node* const& n_, cpp2::impl::in s ) : reflection_base>{ n_, s } -#line 718 "reflect.h2" +#line 722 "reflect.h2" { } -#line 722 "reflect.h2" +#line 726 "reflect.h2" template [[nodiscard]] auto binary_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null((*this).n))); } -#line 723 "reflect.h2" +#line 727 "reflect.h2" template [[nodiscard]] auto binary_expression::lhs_is_id_expression() const& -> bool { return CPP2_UFCS(lhs_is_id_expression)((*cpp2::impl::assert_not_null((*this).n))); } -#line 724 "reflect.h2" +#line 728 "reflect.h2" template [[nodiscard]] auto binary_expression::is_standalone_expression() const& -> bool { return CPP2_UFCS(is_standalone_expression)((*cpp2::impl::assert_not_null((*this).n))); } -#line 725 "reflect.h2" +#line 729 "reflect.h2" template [[nodiscard]] auto binary_expression::terms_size() const& -> int { return CPP2_UFCS(terms_size)((*cpp2::impl::assert_not_null((*this).n))); } -#line 726 "reflect.h2" +#line 730 "reflect.h2" template [[nodiscard]] auto binary_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null((*this).n))); } -#line 727 "reflect.h2" +#line 731 "reflect.h2" template [[nodiscard]] auto binary_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null((*this).n))); } -#line 728 "reflect.h2" +#line 732 "reflect.h2" template [[nodiscard]] auto binary_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null((*this).n))); } -#line 729 "reflect.h2" +#line 733 "reflect.h2" template [[nodiscard]] auto binary_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null((*this).n))); } -#line 730 "reflect.h2" +#line 734 "reflect.h2" template [[nodiscard]] auto binary_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null((*this).n))); } -#line 736 "reflect.h2" +#line 740 "reflect.h2" template template binary_expression::term_t::term_t(auto&& o, auto&& ptr, auto&& cs) : op{ CPP2_FORWARD(o) } , term{ CPP2_FORWARD(ptr), CPP2_FORWARD(cs) }{} -#line 738 "reflect.h2" +#line 742 "reflect.h2" template template [[nodiscard]] auto binary_expression::term_t::get_op() const& -> std::string { return op; } -#line 739 "reflect.h2" +#line 743 "reflect.h2" template template [[nodiscard]] auto binary_expression::term_t::get_term() const& -> T { return term; } template template binary_expression::term_t::term_t(term_t const& that) @@ -3377,7 +4151,7 @@ template template auto binary_expressi op = std::move(that).op; term = std::move(that).term; return *this;} -#line 742 "reflect.h2" +#line 746 "reflect.h2" template [[nodiscard]] auto binary_expression::get_terms() const& -> auto{ if constexpr (std::is_same_v) { std::vector> ret {}; @@ -3453,25 +4227,25 @@ template template auto binary_expressi } } -#line 817 "reflect.h2" +#line 821 "reflect.h2" template [[nodiscard]] auto binary_expression::as_expression_list() const& -> expression_list { return { CPP2_UFCS(get_expression_list)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 818 "reflect.h2" +#line 822 "reflect.h2" template [[nodiscard]] auto binary_expression::as_literal() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_literal)(*cpp2::impl::assert_not_null((*this).n))))); } // Get the postfix-expression, if that's the entire expression (not actually binary) -#line 821 "reflect.h2" +#line 825 "reflect.h2" template [[nodiscard]] auto binary_expression::get_if_only_a_postfix_expression() const& -> postfix_expression { return { CPP2_UFCS(get_if_only_a_postfix_expression_node)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } // Get left-hand postfix-expression -#line 823 "reflect.h2" +#line 827 "reflect.h2" template [[nodiscard]] auto binary_expression::get_lhs_postfix_expression() const& -> postfix_expression { return { CPP2_UFCS(get_postfix_expression_node)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } // Get first right-hand postfix-expression, if there is one -#line 825 "reflect.h2" +#line 829 "reflect.h2" template [[nodiscard]] auto binary_expression::get_second_postfix_expression() const& -> postfix_expression { return { CPP2_UFCS(get_second_postfix_expression_node)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 827 "reflect.h2" +#line 831 "reflect.h2" template [[nodiscard]] auto binary_expression::is_result_a_temporary_variable() const& -> bool { return CPP2_UFCS(is_result_a_temporary_variable)((*cpp2::impl::assert_not_null((*this).n))); } -#line 829 "reflect.h2" +#line 833 "reflect.h2" template [[nodiscard]] auto binary_expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null((*this).n))); } template binary_expression::binary_expression(binary_expression const& that) @@ -3479,29 +4253,29 @@ template template auto binary_expressi template binary_expression::binary_expression(binary_expression&& that) noexcept : reflection_base>{ static_cast>&&>(that) }{} -#line 833 "reflect.h2" +#line 837 "reflect.h2" //----------------------------------------------------------------------- // Expression list // -#line 840 "reflect.h2" +#line 844 "reflect.h2" expression_list::expression_list( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 845 "reflect.h2" +#line 849 "reflect.h2" { } -#line 849 "reflect.h2" +#line 853 "reflect.h2" [[nodiscard]] auto expression_list::is_empty() const& -> bool { return CPP2_UFCS(is_empty)((*cpp2::impl::assert_not_null(n))); } -#line 850 "reflect.h2" +#line 854 "reflect.h2" [[nodiscard]] auto expression_list::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 852 "reflect.h2" +#line 856 "reflect.h2" [[nodiscard]] auto expression_list::get_expressions() const& -> std::vector { @@ -3512,7 +4286,7 @@ template binary_expression::binary_expre return ret; } -#line 862 "reflect.h2" +#line 866 "reflect.h2" [[nodiscard]] auto expression_list::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } expression_list::expression_list(expression_list const& that) @@ -3520,24 +4294,24 @@ template binary_expression::binary_expre expression_list::expression_list(expression_list&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 866 "reflect.h2" +#line 870 "reflect.h2" //----------------------------------------------------------------------- // Prefix expressions // -#line 873 "reflect.h2" +#line 877 "reflect.h2" prefix_expression::prefix_expression( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 878 "reflect.h2" +#line 882 "reflect.h2" { } -#line 882 "reflect.h2" +#line 886 "reflect.h2" [[nodiscard]] auto prefix_expression::get_ops() const& -> std::vector{ std::vector ret {}; for ( auto const& op : (*cpp2::impl::assert_not_null(n)).ops ) { @@ -3546,32 +4320,32 @@ expression_list::expression_list(expression_list&& that) noexcept return ret; } -#line 890 "reflect.h2" +#line 894 "reflect.h2" [[nodiscard]] auto prefix_expression::get_postfix_expression() const& -> postfix_expression { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null((*this).n)).expr), (*this) }; } -#line 892 "reflect.h2" +#line 896 "reflect.h2" [[nodiscard]] auto prefix_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 893 "reflect.h2" +#line 897 "reflect.h2" [[nodiscard]] auto prefix_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 894 "reflect.h2" +#line 898 "reflect.h2" [[nodiscard]] auto prefix_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 895 "reflect.h2" +#line 899 "reflect.h2" [[nodiscard]] auto prefix_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 896 "reflect.h2" +#line 900 "reflect.h2" [[nodiscard]] auto prefix_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 897 "reflect.h2" +#line 901 "reflect.h2" [[nodiscard]] auto prefix_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 898 "reflect.h2" +#line 902 "reflect.h2" [[nodiscard]] auto prefix_expression::is_result_a_temporary_variable() const& -> bool { return CPP2_UFCS(is_result_a_temporary_variable)((*cpp2::impl::assert_not_null(n))); } -#line 900 "reflect.h2" +#line 904 "reflect.h2" [[nodiscard]] auto prefix_expression::as_expression_list() const& -> expression_list { return { CPP2_UFCS(get_expression_list)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 901 "reflect.h2" +#line 905 "reflect.h2" [[nodiscard]] auto prefix_expression::as_literal() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_literal)(*cpp2::impl::assert_not_null(n))))); } -#line 902 "reflect.h2" +#line 906 "reflect.h2" [[nodiscard]] auto prefix_expression::as_identifier() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_identifier)(*cpp2::impl::assert_not_null(n))))); } -#line 904 "reflect.h2" +#line 908 "reflect.h2" [[nodiscard]] auto prefix_expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null((*this).n))); } prefix_expression::~prefix_expression() noexcept{} @@ -3580,32 +4354,32 @@ prefix_expression::prefix_expression(prefix_expression const& that) prefix_expression::prefix_expression(prefix_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 908 "reflect.h2" +#line 912 "reflect.h2" //----------------------------------------------------------------------- // Postfix expressions // -#line 915 "reflect.h2" +#line 919 "reflect.h2" postfix_expression::postfix_expression( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 920 "reflect.h2" +#line 924 "reflect.h2" { } -#line 924 "reflect.h2" +#line 928 "reflect.h2" [[nodiscard]] auto postfix_expression::get_primary_expression() const& -> primary_expression { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null((*this).n)).expr), (*this) }; } -#line 930 "reflect.h2" +#line 934 "reflect.h2" postfix_expression::term_t::term_t(auto&& term, auto&& cs) : term_{ CPP2_FORWARD(term) } , cs_{ CPP2_FORWARD(cs) }{} -#line 932 "reflect.h2" +#line 936 "reflect.h2" [[nodiscard]] auto postfix_expression::term_t::get_op() const& -> std::string_view { return CPP2_UFCS(as_string_view)((*cpp2::impl::assert_not_null((*cpp2::impl::assert_not_null(term_)).op))); } // If op is More is contained in the Notes @@ -3614,18 +4388,18 @@ prefix_expression::prefix_expression(prefix_expression&& that) noexcept // [ ( expression_list subscript or function call // ... expression fold expression -#line 940 "reflect.h2" +#line 944 "reflect.h2" [[nodiscard]] auto postfix_expression::term_t::is_id_expression() const& -> bool { return CPP2_UFCS(get)((*cpp2::impl::assert_not_null(term_)).id_expr) != nullptr; } -#line 941 "reflect.h2" +#line 945 "reflect.h2" [[nodiscard]] auto postfix_expression::term_t::is_expression_list() const& -> bool { return CPP2_UFCS(get)((*cpp2::impl::assert_not_null(term_)).expr_list) != nullptr; } -#line 942 "reflect.h2" +#line 946 "reflect.h2" [[nodiscard]] auto postfix_expression::term_t::is_expression() const& -> bool { return CPP2_UFCS(get)((*cpp2::impl::assert_not_null(term_)).last_expr) != nullptr; } -#line 944 "reflect.h2" +#line 948 "reflect.h2" [[nodiscard]] auto postfix_expression::term_t::get_id_expression() const& -> id_expression { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(term_)).id_expr), *cpp2::impl::assert_not_null(cs_) }; } -#line 945 "reflect.h2" +#line 949 "reflect.h2" [[nodiscard]] auto postfix_expression::term_t::get_expression_list() const& -> expression_list { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(term_)).expr_list), *cpp2::impl::assert_not_null(cs_) }; } -#line 946 "reflect.h2" +#line 950 "reflect.h2" [[nodiscard]] auto postfix_expression::term_t::get_expression() const& -> expression { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(term_)).last_expr), *cpp2::impl::assert_not_null(cs_) }; } postfix_expression::term_t::term_t(term_t const& that) @@ -3635,46 +4409,46 @@ postfix_expression::term_t::term_t(term_t&& that) noexcept : term_{ std::move(that).term_ } , cs_{ std::move(that).cs_ }{} -#line 949 "reflect.h2" +#line 953 "reflect.h2" [[nodiscard]] auto postfix_expression::get_terms() const& -> auto{ std::vector ret {}; for ( auto const& t : (*cpp2::impl::assert_not_null((*this).n)).ops ) {static_cast(CPP2_UFCS(emplace_back)(ret, &t, &(*this))); } return ret; } -#line 955 "reflect.h2" +#line 959 "reflect.h2" [[nodiscard]] auto postfix_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 956 "reflect.h2" +#line 960 "reflect.h2" [[nodiscard]] auto postfix_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 957 "reflect.h2" +#line 961 "reflect.h2" [[nodiscard]] auto postfix_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 958 "reflect.h2" +#line 962 "reflect.h2" [[nodiscard]] auto postfix_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 959 "reflect.h2" +#line 963 "reflect.h2" [[nodiscard]] auto postfix_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 960 "reflect.h2" +#line 964 "reflect.h2" [[nodiscard]] auto postfix_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 962 "reflect.h2" +#line 966 "reflect.h2" [[nodiscard]] auto postfix_expression::as_identifier() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_identifier)(*cpp2::impl::assert_not_null(n))))); } -#line 963 "reflect.h2" +#line 967 "reflect.h2" [[nodiscard]] auto postfix_expression::as_expression_list() const& -> expression_list { return { CPP2_UFCS(get_expression_list)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 964 "reflect.h2" +#line 968 "reflect.h2" [[nodiscard]] auto postfix_expression::as_literal() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_literal)(*cpp2::impl::assert_not_null(n))))); } -#line 966 "reflect.h2" +#line 970 "reflect.h2" [[nodiscard]] auto postfix_expression::get_first_token_ignoring_this() const& -> std::string_view{ auto ptok {CPP2_UFCS(get_first_token_ignoring_this)((*cpp2::impl::assert_not_null(n)))}; if (ptok) {return *cpp2::impl::assert_not_null(cpp2::move(ptok)); } return ""; } -#line 972 "reflect.h2" +#line 976 "reflect.h2" [[nodiscard]] auto postfix_expression::starts_with_function_call_with_num_parameters(cpp2::impl::in num) const& -> bool { return CPP2_UFCS(starts_with_function_call_with_n_parameters)((*cpp2::impl::assert_not_null(n)), num); } -#line 973 "reflect.h2" +#line 977 "reflect.h2" [[nodiscard]] auto postfix_expression::is_result_a_temporary_variable() const& -> bool { return CPP2_UFCS(is_result_a_temporary_variable)((*cpp2::impl::assert_not_null(n))); } -#line 975 "reflect.h2" +#line 979 "reflect.h2" [[nodiscard]] auto postfix_expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } postfix_expression::postfix_expression(postfix_expression const& that) @@ -3682,34 +4456,34 @@ postfix_expression::term_t::term_t(term_t&& that) noexcept postfix_expression::postfix_expression(postfix_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 979 "reflect.h2" +#line 983 "reflect.h2" //----------------------------------------------------------------------- // Template arguments // -#line 986 "reflect.h2" +#line 990 "reflect.h2" template_arg::template_arg( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 991 "reflect.h2" +#line 995 "reflect.h2" { } -#line 995 "reflect.h2" +#line 999 "reflect.h2" [[nodiscard]] auto template_arg::is_expression() const& -> bool { return CPP2_UFCS(is_expression)((*cpp2::impl::assert_not_null(n))); } -#line 996 "reflect.h2" +#line 1000 "reflect.h2" [[nodiscard]] auto template_arg::is_type_id() const& -> bool { return CPP2_UFCS(is_type_id)((*cpp2::impl::assert_not_null(n))); } -#line 998 "reflect.h2" +#line 1002 "reflect.h2" [[nodiscard]] auto template_arg::as_expression() const& -> expression { return { CPP2_UFCS(get_expression)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 999 "reflect.h2" +#line 1003 "reflect.h2" [[nodiscard]] auto template_arg::as_type_id() const& -> type_id { return { CPP2_UFCS(get_type_id)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 1001 "reflect.h2" +#line 1005 "reflect.h2" [[nodiscard]] auto template_arg::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } template_arg::template_arg(template_arg const& that) @@ -3717,27 +4491,27 @@ postfix_expression::postfix_expression(postfix_expression&& that) noexcept template_arg::template_arg(template_arg&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1005 "reflect.h2" +#line 1009 "reflect.h2" //----------------------------------------------------------------------- // Unqualified IDs // -#line 1012 "reflect.h2" +#line 1016 "reflect.h2" unqualified_id::unqualified_id( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1017 "reflect.h2" +#line 1021 "reflect.h2" { } -#line 1021 "reflect.h2" +#line 1025 "reflect.h2" [[nodiscard]] auto unqualified_id::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 1023 "reflect.h2" +#line 1027 "reflect.h2" [[nodiscard]] auto unqualified_id::get_identifier() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_identifier)(*cpp2::impl::assert_not_null(n))))); } //get_template_args: (this) -> std::vector = { @@ -3746,10 +4520,10 @@ template_arg::template_arg(template_arg&& that) noexcept // return ret; //} -#line 1031 "reflect.h2" +#line 1035 "reflect.h2" [[nodiscard]] auto unqualified_id::as_token() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_token)(*cpp2::impl::assert_not_null(n))))); } -#line 1033 "reflect.h2" +#line 1037 "reflect.h2" [[nodiscard]] auto unqualified_id::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } unqualified_id::unqualified_id(unqualified_id const& that) @@ -3757,31 +4531,31 @@ template_arg::template_arg(template_arg&& that) noexcept unqualified_id::unqualified_id(unqualified_id&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1037 "reflect.h2" +#line 1041 "reflect.h2" //----------------------------------------------------------------------- // Qualified IDs // -#line 1044 "reflect.h2" +#line 1048 "reflect.h2" qualified_id::qualified_id( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1049 "reflect.h2" +#line 1053 "reflect.h2" { } -#line 1057 "reflect.h2" +#line 1061 "reflect.h2" qualified_id::term_t::term_t(auto&& o, auto&& ptr, auto&& cs) : op{ CPP2_FORWARD(o) } , unqualified{ CPP2_FORWARD(ptr), CPP2_FORWARD(cs) }{} -#line 1059 "reflect.h2" +#line 1063 "reflect.h2" [[nodiscard]] auto qualified_id::term_t::get_op() const& -> std::string { return op; } -#line 1060 "reflect.h2" +#line 1064 "reflect.h2" [[nodiscard]] auto qualified_id::term_t::get_unqualified() const& -> unqualified_id { return unqualified; } qualified_id::term_t::term_t(term_t const& that) @@ -3791,7 +4565,7 @@ qualified_id::term_t::term_t(term_t&& that) noexcept : op{ std::move(that).op } , unqualified{ std::move(that).unqualified }{} -#line 1063 "reflect.h2" +#line 1067 "reflect.h2" [[nodiscard]] auto qualified_id::get_terms() const& -> auto{ std::vector ret {}; for ( auto const& t : (*cpp2::impl::assert_not_null((*this).n)).ids ) {static_cast(CPP2_UFCS(emplace_back)(ret, *cpp2::impl::assert_not_null(t.scope_op), CPP2_UFCS(get)(t.id), (*this))); } @@ -3804,10 +4578,10 @@ qualified_id::term_t::term_t(term_t&& that) noexcept // return ret; //} -#line 1075 "reflect.h2" +#line 1079 "reflect.h2" [[nodiscard]] auto qualified_id::as_token() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_token)(*cpp2::impl::assert_not_null(n))))); } -#line 1077 "reflect.h2" +#line 1081 "reflect.h2" [[nodiscard]] auto qualified_id::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } qualified_id::qualified_id(qualified_id const& that) @@ -3815,19 +4589,19 @@ qualified_id::term_t::term_t(term_t&& that) noexcept qualified_id::qualified_id(qualified_id&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1081 "reflect.h2" +#line 1085 "reflect.h2" //----------------------------------------------------------------------- // Type IDs // -#line 1088 "reflect.h2" +#line 1092 "reflect.h2" type_id::type_id( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1093 "reflect.h2" +#line 1097 "reflect.h2" { } @@ -3838,37 +4612,37 @@ qualified_id::qualified_id(qualified_id&& that) noexcept // return ret; //} -#line 1103 "reflect.h2" +#line 1107 "reflect.h2" [[nodiscard]] auto type_id::is_postfix_expression() const& -> bool { return CPP2_UFCS(is_postfix_expression)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1104 "reflect.h2" +#line 1108 "reflect.h2" [[nodiscard]] auto type_id::is_qualified_id() const& -> bool { return CPP2_UFCS(is_qualified_id)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1105 "reflect.h2" +#line 1109 "reflect.h2" [[nodiscard]] auto type_id::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1106 "reflect.h2" +#line 1110 "reflect.h2" [[nodiscard]] auto type_id::is_function_typeid() const& -> bool { return CPP2_UFCS(is_function_typeid)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1107 "reflect.h2" +#line 1111 "reflect.h2" [[nodiscard]] auto type_id::is_keyword() const& -> bool { return CPP2_UFCS(is_keyword)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1108 "reflect.h2" +#line 1112 "reflect.h2" [[nodiscard]] auto type_id::is_wildcard() const& -> bool { return CPP2_UFCS(is_wildcard)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1109 "reflect.h2" +#line 1113 "reflect.h2" [[nodiscard]] auto type_id::is_pointer_qualified() const& -> bool { return CPP2_UFCS(is_pointer_qualified)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1110 "reflect.h2" +#line 1114 "reflect.h2" [[nodiscard]] auto type_id::is_concept() const& -> bool { return CPP2_UFCS(is_concept)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1112 "reflect.h2" +#line 1116 "reflect.h2" [[nodiscard]] auto type_id::as_postfix_expression() const& -> postfix_expression { return { CPP2_UFCS(get_postfix_expression)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1113 "reflect.h2" +#line 1117 "reflect.h2" [[nodiscard]] auto type_id::as_qualified_id() const& -> qualified_id { return { CPP2_UFCS(get_qualified_id)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1114 "reflect.h2" +#line 1118 "reflect.h2" [[nodiscard]] auto type_id::as_unqualified_id() const& -> unqualified_id { return { CPP2_UFCS(get_unqualified_id)((*cpp2::impl::assert_not_null(n))), (*this) }; } // TODO //as_function_typeid : (this) -> function_typeid = (n*.get_function_typeid(), this); -#line 1117 "reflect.h2" +#line 1121 "reflect.h2" [[nodiscard]] auto type_id::as_keyword() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_keyword)(*cpp2::impl::assert_not_null(n))))); } -#line 1118 "reflect.h2" +#line 1122 "reflect.h2" [[nodiscard]] auto type_id::as_token() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_token)(*cpp2::impl::assert_not_null(n))))); } -#line 1120 "reflect.h2" +#line 1124 "reflect.h2" [[nodiscard]] auto type_id::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } type_id::type_id(type_id const& that) @@ -3876,19 +4650,19 @@ qualified_id::qualified_id(qualified_id&& that) noexcept type_id::type_id(type_id&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1124 "reflect.h2" +#line 1128 "reflect.h2" //----------------------------------------------------------------------- // Primary expressions // -#line 1131 "reflect.h2" +#line 1135 "reflect.h2" primary_expression::primary_expression( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1136 "reflect.h2" +#line 1140 "reflect.h2" { } @@ -3899,31 +4673,31 @@ type_id::type_id(type_id&& that) noexcept // return ret; //} -#line 1146 "reflect.h2" +#line 1150 "reflect.h2" [[nodiscard]] auto primary_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1147 "reflect.h2" +#line 1151 "reflect.h2" [[nodiscard]] auto primary_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 1148 "reflect.h2" +#line 1152 "reflect.h2" [[nodiscard]] auto primary_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1149 "reflect.h2" +#line 1153 "reflect.h2" [[nodiscard]] auto primary_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 1150 "reflect.h2" +#line 1154 "reflect.h2" [[nodiscard]] auto primary_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 1151 "reflect.h2" +#line 1155 "reflect.h2" [[nodiscard]] auto primary_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 1152 "reflect.h2" +#line 1156 "reflect.h2" [[nodiscard]] auto primary_expression::is_declaration() const& -> bool { return CPP2_UFCS(is_declaration)((*cpp2::impl::assert_not_null(n))); } -#line 1154 "reflect.h2" +#line 1158 "reflect.h2" [[nodiscard]] auto primary_expression::as_identifier() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_identifier)(*cpp2::impl::assert_not_null(n))))); } -#line 1155 "reflect.h2" +#line 1159 "reflect.h2" [[nodiscard]] auto primary_expression::as_expression_list() const& -> expression_list { return { CPP2_UFCS(get_expression_list)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 1156 "reflect.h2" +#line 1160 "reflect.h2" [[nodiscard]] auto primary_expression::as_literal() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_literal)(*cpp2::impl::assert_not_null(n))))); } -#line 1157 "reflect.h2" +#line 1161 "reflect.h2" [[nodiscard]] auto primary_expression::as_declaration() const& -> declaration { return { CPP2_UFCS(get_declaration)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 1159 "reflect.h2" +#line 1163 "reflect.h2" [[nodiscard]] auto primary_expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } primary_expression::primary_expression(primary_expression const& that) @@ -3931,19 +4705,19 @@ type_id::type_id(type_id&& that) noexcept primary_expression::primary_expression(primary_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1163 "reflect.h2" +#line 1167 "reflect.h2" //----------------------------------------------------------------------- // ID expression // -#line 1170 "reflect.h2" +#line 1174 "reflect.h2" id_expression::id_expression( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1175 "reflect.h2" +#line 1179 "reflect.h2" { } @@ -3954,25 +4728,25 @@ primary_expression::primary_expression(primary_expression&& that) noexcept // return ret; //} -#line 1185 "reflect.h2" +#line 1189 "reflect.h2" [[nodiscard]] auto id_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1186 "reflect.h2" +#line 1190 "reflect.h2" [[nodiscard]] auto id_expression::is_empty() const& -> bool { return CPP2_UFCS(is_empty)((*cpp2::impl::assert_not_null(n))); } -#line 1187 "reflect.h2" +#line 1191 "reflect.h2" [[nodiscard]] auto id_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 1188 "reflect.h2" +#line 1192 "reflect.h2" [[nodiscard]] auto id_expression::is_qualified() const& -> bool { return CPP2_UFCS(is_qualified)((*cpp2::impl::assert_not_null(n))); } -#line 1189 "reflect.h2" +#line 1193 "reflect.h2" [[nodiscard]] auto id_expression::is_unqualified() const& -> bool { return CPP2_UFCS(is_unqualified)((*cpp2::impl::assert_not_null(n))); } -#line 1191 "reflect.h2" +#line 1195 "reflect.h2" [[nodiscard]] auto id_expression::as_identifier() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_identifier)(*cpp2::impl::assert_not_null(n))))); } -#line 1192 "reflect.h2" +#line 1196 "reflect.h2" [[nodiscard]] auto id_expression::as_qualified() const& -> qualified_id { return { CPP2_UFCS(get_qualified_id)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1193 "reflect.h2" +#line 1197 "reflect.h2" [[nodiscard]] auto id_expression::as_unqualified() const& -> unqualified_id { return { CPP2_UFCS(get_unqualified_id)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1195 "reflect.h2" +#line 1199 "reflect.h2" [[nodiscard]] auto id_expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } id_expression::~id_expression() noexcept{} @@ -3981,71 +4755,71 @@ id_expression::id_expression(id_expression const& that) id_expression::id_expression(id_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1199 "reflect.h2" +#line 1203 "reflect.h2" //----------------------------------------------------------------------- // General expression // -#line 1206 "reflect.h2" +#line 1210 "reflect.h2" expression::expression( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1211 "reflect.h2" +#line 1215 "reflect.h2" { } -#line 1215 "reflect.h2" +#line 1219 "reflect.h2" [[nodiscard]] auto expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1216 "reflect.h2" +#line 1220 "reflect.h2" [[nodiscard]] auto expression::is_standalone_expression() const& -> bool { return CPP2_UFCS(is_standalone_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1217 "reflect.h2" +#line 1221 "reflect.h2" [[nodiscard]] auto expression::subexpression_count() const& -> int { return CPP2_UFCS(subexpression_count)((*cpp2::impl::assert_not_null(n))); } -#line 1218 "reflect.h2" +#line 1222 "reflect.h2" [[nodiscard]] auto expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 1219 "reflect.h2" +#line 1223 "reflect.h2" [[nodiscard]] auto expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1220 "reflect.h2" +#line 1224 "reflect.h2" [[nodiscard]] auto expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 1221 "reflect.h2" +#line 1225 "reflect.h2" [[nodiscard]] auto expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 1222 "reflect.h2" +#line 1226 "reflect.h2" [[nodiscard]] auto expression::is_empty_expression_list() const& -> bool { return CPP2_UFCS(is_empty_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 1223 "reflect.h2" +#line 1227 "reflect.h2" [[nodiscard]] auto expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 1224 "reflect.h2" +#line 1228 "reflect.h2" [[nodiscard]] auto expression::is_assignment_expression() const& -> bool { return CPP2_UFCS(is_assignment_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1226 "reflect.h2" +#line 1230 "reflect.h2" [[nodiscard]] auto expression::is_simple_assignment() const& -> bool{ auto ret {CPP2_UFCS(get_lhs_rhs_if_simple_assignment)((*cpp2::impl::assert_not_null(n)))}; return ret.lhs && ret.rhs; } -#line 1231 "reflect.h2" +#line 1235 "reflect.h2" [[nodiscard]] auto expression::get_lhs_rhs_if_simple_assignment() const& -> get_lhs_rhs_if_simple_assignment_ret -#line 1236 "reflect.h2" +#line 1240 "reflect.h2" { cpp2::impl::deferred_init lhs; cpp2::impl::deferred_init rhs; -#line 1237 "reflect.h2" +#line 1241 "reflect.h2" auto ret {CPP2_UFCS(get_lhs_rhs_if_simple_assignment)((*cpp2::impl::assert_not_null(n)))}; lhs.construct(ret.lhs, (*this)); rhs.construct(cpp2::move(ret).rhs, (*this)); return { std::move(lhs.value()), std::move(rhs.value()) }; } -#line 1242 "reflect.h2" +#line 1246 "reflect.h2" [[nodiscard]] auto expression::as_assignment_expression() const& -> assignment_expression { return { CPP2_UFCS(get_assignment_expression)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1243 "reflect.h2" +#line 1247 "reflect.h2" [[nodiscard]] auto expression::as_expression_list() const& -> expression_list { return { CPP2_UFCS(get_expression_list)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1244 "reflect.h2" +#line 1248 "reflect.h2" [[nodiscard]] auto expression::as_literal() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_literal)(*cpp2::impl::assert_not_null(n))))); } -#line 1246 "reflect.h2" +#line 1250 "reflect.h2" [[nodiscard]] auto expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } expression::~expression() noexcept{} @@ -4054,31 +4828,31 @@ expression::expression(expression const& that) expression::expression(expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1250 "reflect.h2" +#line 1254 "reflect.h2" //----------------------------------------------------------------------- // is_as_expression // -#line 1257 "reflect.h2" +#line 1261 "reflect.h2" is_as_expression::is_as_expression( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1262 "reflect.h2" +#line 1266 "reflect.h2" { } -#line 1270 "reflect.h2" +#line 1274 "reflect.h2" is_as_expression::term_t::term_t(auto&& o, auto&& ptr, auto&& cs) : op{ CPP2_FORWARD(o) } , expr{ CPP2_FORWARD(ptr), CPP2_FORWARD(cs) }{} -#line 1272 "reflect.h2" +#line 1276 "reflect.h2" [[nodiscard]] auto is_as_expression::term_t::get_op() const& -> std::string { return op; } -#line 1273 "reflect.h2" +#line 1277 "reflect.h2" [[nodiscard]] auto is_as_expression::term_t::get_expr() const& -> expression { return expr; } is_as_expression::term_t::term_t(term_t const& that) @@ -4088,42 +4862,42 @@ is_as_expression::term_t::term_t(term_t&& that) noexcept : op{ std::move(that).op } , expr{ std::move(that).expr }{} -#line 1276 "reflect.h2" +#line 1280 "reflect.h2" [[nodiscard]] auto is_as_expression::get_expression() const& -> prefix_expression { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(n)).expr), (*this) }; } -#line 1278 "reflect.h2" +#line 1282 "reflect.h2" [[nodiscard]] auto is_as_expression::get_terms() const& -> auto{ std::vector ret {}; for ( auto const& t : (*cpp2::impl::assert_not_null((*this).n)).ops ) {static_cast(CPP2_UFCS(emplace_back)(ret, *cpp2::impl::assert_not_null(t.op), CPP2_UFCS(get)(t.expr), (*this))); } return ret; } -#line 1284 "reflect.h2" +#line 1288 "reflect.h2" [[nodiscard]] auto is_as_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1285 "reflect.h2" +#line 1289 "reflect.h2" [[nodiscard]] auto is_as_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1286 "reflect.h2" +#line 1290 "reflect.h2" [[nodiscard]] auto is_as_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1287 "reflect.h2" +#line 1291 "reflect.h2" [[nodiscard]] auto is_as_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1288 "reflect.h2" +#line 1292 "reflect.h2" [[nodiscard]] auto is_as_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1289 "reflect.h2" +#line 1293 "reflect.h2" [[nodiscard]] auto is_as_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1291 "reflect.h2" +#line 1295 "reflect.h2" [[nodiscard]] auto is_as_expression::as_expression_list() const& -> expression_list { return { CPP2_UFCS(get_expression_list)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 1292 "reflect.h2" +#line 1296 "reflect.h2" [[nodiscard]] auto is_as_expression::as_literal() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_literal)(*cpp2::impl::assert_not_null(n))))); } -#line 1294 "reflect.h2" +#line 1298 "reflect.h2" [[nodiscard]] auto is_as_expression::get_identifier() const& -> std::string_view{ auto ptok {CPP2_UFCS(get_identifier)((*cpp2::impl::assert_not_null((*this).n)))}; if (ptok) {return *cpp2::impl::assert_not_null(cpp2::move(ptok)); } return ""; } -#line 1300 "reflect.h2" +#line 1304 "reflect.h2" [[nodiscard]] auto is_as_expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null((*this).n))); } is_as_expression::~is_as_expression() noexcept{} @@ -4132,7 +4906,7 @@ is_as_expression::is_as_expression(is_as_expression const& that) is_as_expression::is_as_expression(is_as_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1304 "reflect.h2" +#line 1308 "reflect.h2" //----------------------------------------------------------------------- // // Statements @@ -4144,19 +4918,19 @@ is_as_expression::is_as_expression(is_as_expression&& that) noexcept // General statement // -#line 1318 "reflect.h2" +#line 1322 "reflect.h2" statement::statement( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1323 "reflect.h2" +#line 1327 "reflect.h2" { } -#line 1327 "reflect.h2" +#line 1331 "reflect.h2" [[nodiscard]] auto statement::get_parameters() const& -> std::vector { @@ -4167,45 +4941,45 @@ is_as_expression::is_as_expression(is_as_expression&& that) noexcept return ret; } -#line 1337 "reflect.h2" +#line 1341 "reflect.h2" [[nodiscard]] auto statement::is_expression_statement() const& -> bool { return CPP2_UFCS(is_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1338 "reflect.h2" +#line 1342 "reflect.h2" [[nodiscard]] auto statement::is_compound_statement() const& -> bool { return CPP2_UFCS(is_compound)((*cpp2::impl::assert_not_null(n))); } -#line 1339 "reflect.h2" +#line 1343 "reflect.h2" [[nodiscard]] auto statement::is_selection_statement() const& -> bool { return CPP2_UFCS(is_selection)((*cpp2::impl::assert_not_null(n))); } -#line 1340 "reflect.h2" +#line 1344 "reflect.h2" [[nodiscard]] auto statement::is_declaration() const& -> bool { return CPP2_UFCS(is_declaration)((*cpp2::impl::assert_not_null(n))); } -#line 1341 "reflect.h2" +#line 1345 "reflect.h2" [[nodiscard]] auto statement::is_return_statement() const& -> bool { return CPP2_UFCS(is_return)((*cpp2::impl::assert_not_null(n))); } -#line 1342 "reflect.h2" +#line 1346 "reflect.h2" [[nodiscard]] auto statement::is_iteration_statement() const& -> bool { return CPP2_UFCS(is_iteration)((*cpp2::impl::assert_not_null(n))); } -#line 1343 "reflect.h2" +#line 1347 "reflect.h2" [[nodiscard]] auto statement::is_using_statement() const& -> bool { return CPP2_UFCS(is_using)((*cpp2::impl::assert_not_null(n))); } -#line 1344 "reflect.h2" +#line 1348 "reflect.h2" [[nodiscard]] auto statement::is_contract() const& -> bool { return CPP2_UFCS(is_contract)((*cpp2::impl::assert_not_null(n))); } -#line 1345 "reflect.h2" +#line 1349 "reflect.h2" [[nodiscard]] auto statement::is_inspect_expression() const& -> bool { return CPP2_UFCS(is_inspect)((*cpp2::impl::assert_not_null(n))); } -#line 1346 "reflect.h2" +#line 1350 "reflect.h2" [[nodiscard]] auto statement::is_jump_statement() const& -> bool { return CPP2_UFCS(is_jump)((*cpp2::impl::assert_not_null(n))); } -#line 1348 "reflect.h2" +#line 1352 "reflect.h2" [[nodiscard]] auto statement::as_expression_statement() const& -> expression_statement { return { CPP2_UFCS_TEMPLATE(get_if)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1349 "reflect.h2" +#line 1353 "reflect.h2" [[nodiscard]] auto statement::as_compound_statement() const& -> compound_statement { return { CPP2_UFCS_TEMPLATE(get_if)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1350 "reflect.h2" +#line 1354 "reflect.h2" [[nodiscard]] auto statement::as_selection_statement() const& -> selection_statement { return selection_statement(CPP2_UFCS_TEMPLATE(get_if)((*cpp2::impl::assert_not_null(n))), (*this)); } -#line 1351 "reflect.h2" +#line 1355 "reflect.h2" [[nodiscard]] auto statement::as_declaration() const& -> declaration { return declaration(CPP2_UFCS_TEMPLATE(get_if)((*cpp2::impl::assert_not_null(n))), (*this)); } -#line 1352 "reflect.h2" +#line 1356 "reflect.h2" [[nodiscard]] auto statement::as_return_statement() const& -> return_statement { return return_statement(CPP2_UFCS_TEMPLATE(get_if)((*cpp2::impl::assert_not_null(n))), (*this)); } -#line 1353 "reflect.h2" +#line 1357 "reflect.h2" [[nodiscard]] auto statement::as_iteration_statement() const& -> iteration_statement { return iteration_statement(CPP2_UFCS_TEMPLATE(get_if)((*cpp2::impl::assert_not_null(n))), (*this)); } //as_using_statement : (this) -> using_statement = using_statement (n*.get_if(), this); //as_contract : (this) -> contract = contract (n*.get_if(), this); //as_inspect_expression : (this) -> inspect_expression = inspect_expression (n*.get_if(), this); //as_jump_statement : (this) -> jump_statement = jump_statement (n*.get_if(), this); -#line 1359 "reflect.h2" +#line 1363 "reflect.h2" [[nodiscard]] auto statement::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } statement::~statement() noexcept{} @@ -4214,27 +4988,27 @@ statement::statement(statement const& that) statement::statement(statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1363 "reflect.h2" +#line 1367 "reflect.h2" //----------------------------------------------------------------------- // Expression statements // -#line 1370 "reflect.h2" +#line 1374 "reflect.h2" expression_statement::expression_statement( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1375 "reflect.h2" +#line 1379 "reflect.h2" { } -#line 1379 "reflect.h2" +#line 1383 "reflect.h2" [[nodiscard]] auto expression_statement::get_expression() const& -> expression { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(n)).expr), (*this) }; } -#line 1381 "reflect.h2" +#line 1385 "reflect.h2" [[nodiscard]] auto expression_statement::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } expression_statement::expression_statement(expression_statement const& that) @@ -4242,24 +5016,24 @@ statement::statement(statement&& that) noexcept expression_statement::expression_statement(expression_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1385 "reflect.h2" +#line 1389 "reflect.h2" //----------------------------------------------------------------------- // Compound statements // -#line 1392 "reflect.h2" +#line 1396 "reflect.h2" compound_statement::compound_statement( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1397 "reflect.h2" +#line 1401 "reflect.h2" { } -#line 1401 "reflect.h2" +#line 1405 "reflect.h2" [[nodiscard]] auto compound_statement::get_statements() const& -> std::vector { @@ -4270,7 +5044,7 @@ expression_statement::expression_statement(expression_statement&& that) noexcept return ret; } -#line 1411 "reflect.h2" +#line 1415 "reflect.h2" auto compound_statement::add_statement(cpp2::impl::in source, cpp2::impl::in before_position) & -> void { auto stmt {parse_statement(source)}; @@ -4287,35 +5061,35 @@ expression_statement::expression_statement(expression_statement&& that) noexcept compound_statement::compound_statement(compound_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1424 "reflect.h2" +#line 1428 "reflect.h2" //----------------------------------------------------------------------- // Selection statements // -#line 1431 "reflect.h2" +#line 1435 "reflect.h2" selection_statement::selection_statement( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1436 "reflect.h2" +#line 1440 "reflect.h2" { } -#line 1440 "reflect.h2" +#line 1444 "reflect.h2" [[nodiscard]] auto selection_statement::has_false_branch_in_source_code() const& -> bool { return CPP2_UFCS(has_false_branch_in_source_code)((*cpp2::impl::assert_not_null(n))); } -#line 1441 "reflect.h2" +#line 1445 "reflect.h2" [[nodiscard]] auto selection_statement::has_false_branch() const& -> bool { return CPP2_UFCS(has_false_branch)((*cpp2::impl::assert_not_null(n))); } -#line 1443 "reflect.h2" +#line 1447 "reflect.h2" [[nodiscard]] auto selection_statement::get_identifier() const& -> std::string_view { return CPP2_UFCS(as_string_view)((*cpp2::impl::assert_not_null(CPP2_UFCS(get_identifier)(*cpp2::impl::assert_not_null(n))))); } -#line 1444 "reflect.h2" +#line 1448 "reflect.h2" [[nodiscard]] auto selection_statement::get_expression() const& -> logical_or_expression { return { CPP2_UFCS(get_expression)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1445 "reflect.h2" +#line 1449 "reflect.h2" [[nodiscard]] auto selection_statement::get_true_branch() const& -> compound_statement { return { CPP2_UFCS(get_true_branch)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1446 "reflect.h2" +#line 1450 "reflect.h2" [[nodiscard]] auto selection_statement::get_false_branch() const& -> compound_statement { return { CPP2_UFCS(get_false_branch)((*cpp2::impl::assert_not_null(n))), (*this) }; } selection_statement::selection_statement(selection_statement const& that) @@ -4323,27 +5097,27 @@ compound_statement::compound_statement(compound_statement&& that) noexcept selection_statement::selection_statement(selection_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1450 "reflect.h2" +#line 1454 "reflect.h2" //----------------------------------------------------------------------- // Return statements // -#line 1457 "reflect.h2" +#line 1461 "reflect.h2" return_statement::return_statement( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1462 "reflect.h2" +#line 1466 "reflect.h2" { } -#line 1466 "reflect.h2" +#line 1470 "reflect.h2" [[nodiscard]] auto return_statement::has_expression() const& -> bool { return CPP2_UFCS(has_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1468 "reflect.h2" +#line 1472 "reflect.h2" [[nodiscard]] auto return_statement::get_expression() const& -> expression { return { CPP2_UFCS(get_expression)((*cpp2::impl::assert_not_null(n))), (*this) }; } return_statement::return_statement(return_statement const& that) @@ -4351,45 +5125,45 @@ selection_statement::selection_statement(selection_statement&& that) noexcept return_statement::return_statement(return_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1472 "reflect.h2" +#line 1476 "reflect.h2" //----------------------------------------------------------------------- // Iteration statements - for, do, while // -#line 1479 "reflect.h2" +#line 1483 "reflect.h2" iteration_statement::iteration_statement( cpp2::impl::in n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1484 "reflect.h2" +#line 1488 "reflect.h2" { } -#line 1488 "reflect.h2" +#line 1492 "reflect.h2" [[nodiscard]] auto iteration_statement::is_do() const& -> bool { return CPP2_UFCS(is_do)((*cpp2::impl::assert_not_null(n))); } -#line 1489 "reflect.h2" +#line 1493 "reflect.h2" [[nodiscard]] auto iteration_statement::is_while() const& -> bool { return CPP2_UFCS(is_while)((*cpp2::impl::assert_not_null(n))); } -#line 1490 "reflect.h2" +#line 1494 "reflect.h2" [[nodiscard]] auto iteration_statement::is_for() const& -> bool { return CPP2_UFCS(is_for)((*cpp2::impl::assert_not_null(n))); } -#line 1491 "reflect.h2" +#line 1495 "reflect.h2" [[nodiscard]] auto iteration_statement::has_next() const& -> bool { return CPP2_UFCS(has_next)((*cpp2::impl::assert_not_null(n))); } -#line 1493 "reflect.h2" +#line 1497 "reflect.h2" [[nodiscard]] auto iteration_statement::get_label() const& -> std::string { return CPP2_UFCS(to_string)(CPP2_UFCS(get_label)((*cpp2::impl::assert_not_null(n)))); } -#line 1494 "reflect.h2" +#line 1498 "reflect.h2" [[nodiscard]] auto iteration_statement::get_next_expression() const& -> assignment_expression { return { CPP2_UFCS(get_next_expression)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1495 "reflect.h2" +#line 1499 "reflect.h2" [[nodiscard]] auto iteration_statement::get_do_while_condition() const& -> logical_or_expression { return { CPP2_UFCS(get_do_while_condition)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1496 "reflect.h2" +#line 1500 "reflect.h2" [[nodiscard]] auto iteration_statement::get_do_while_body() const& -> compound_statement { return { CPP2_UFCS(get_do_while_body)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1497 "reflect.h2" +#line 1501 "reflect.h2" [[nodiscard]] auto iteration_statement::get_for_range() const& -> expression { return { CPP2_UFCS(get_for_range)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1498 "reflect.h2" +#line 1502 "reflect.h2" [[nodiscard]] auto iteration_statement::get_for_parameter() const& -> parameter_declaration { return { CPP2_UFCS(get_for_parameter)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 1499 "reflect.h2" +#line 1503 "reflect.h2" [[nodiscard]] auto iteration_statement::get_for_body() const& -> statement { return { CPP2_UFCS(get_for_body)((*cpp2::impl::assert_not_null(n))), (*this) }; } iteration_statement::iteration_statement(iteration_statement const& that) @@ -4397,7 +5171,7 @@ return_statement::return_statement(return_statement&& that) noexcept iteration_statement::iteration_statement(iteration_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1503 "reflect.h2" +#line 1507 "reflect.h2" //----------------------------------------------------------------------- // // Metafunctions - these are hardwired for now until we get to the @@ -4410,13 +5184,13 @@ iteration_statement::iteration_statement(iteration_statement&& that) noexcept // Some common metafunction helpers (metafunctions are just functions, // so they can be factored as usual) // -#line 1515 "reflect.h2" +#line 1519 "reflect.h2" auto add_virtual_destructor(meta::type_declaration& t) -> void { CPP2_UFCS(add_member)(t, "operator=: (virtual move this) = { }"); } -#line 1521 "reflect.h2" +#line 1525 "reflect.h2" //----------------------------------------------------------------------- // // "... an abstract base class defines an interface ..." @@ -4431,7 +5205,7 @@ auto add_virtual_destructor(meta::type_declaration& t) -> void // a public default constructor, a public virtual destructor, and // protected copy/move operations // -#line 1535 "reflect.h2" +#line 1539 "reflect.h2" auto interface(meta::type_declaration& t) -> void { auto has_dtor {false}; @@ -4463,7 +5237,7 @@ auto interface(meta::type_declaration& t) -> void } } -#line 1567 "reflect.h2" +#line 1571 "reflect.h2" //----------------------------------------------------------------------- // // "C.35: A base class destructor should be either public and @@ -4480,7 +5254,7 @@ auto interface(meta::type_declaration& t) -> void // // Unlike an interface, it can have nonpublic and nonvirtual functions. // -#line 1583 "reflect.h2" +#line 1587 "reflect.h2" auto polymorphic_base(meta::type_declaration& t) -> void { auto has_dtor {false}; @@ -4505,7 +5279,7 @@ auto polymorphic_base(meta::type_declaration& t) -> void } } -#line 1608 "reflect.h2" +#line 1612 "reflect.h2" //----------------------------------------------------------------------- // // "... A totally ordered type ... requires operator<=> that @@ -4526,7 +5300,7 @@ auto polymorphic_base(meta::type_declaration& t) -> void //----------------------------------------------------------------------- // -#line 1628 "reflect.h2" +#line 1632 "reflect.h2" auto ordered_impl( meta::type_declaration& t, cpp2::impl::in ordering// must be "strong_ordering" etc. @@ -4556,7 +5330,7 @@ auto ordered_impl( // // Note: the ordering that should be encouraged as default gets the nice name // -#line 1657 "reflect.h2" +#line 1661 "reflect.h2" auto ordered(meta::type_declaration& t) -> void { ordered_impl(t, "strong_ordering"); @@ -4565,7 +5339,7 @@ auto ordered(meta::type_declaration& t) -> void //----------------------------------------------------------------------- // weakly_ordered - a weakly ordered type // -#line 1665 "reflect.h2" +#line 1669 "reflect.h2" auto weakly_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "weak_ordering"); @@ -4574,13 +5348,13 @@ auto weakly_ordered(meta::type_declaration& t) -> void //----------------------------------------------------------------------- // partially_ordered - a partially ordered type // -#line 1673 "reflect.h2" +#line 1677 "reflect.h2" auto partially_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "partial_ordering"); } -#line 1679 "reflect.h2" +#line 1683 "reflect.h2" //----------------------------------------------------------------------- // // "A value is ... a regular type. It must have all public @@ -4597,7 +5371,7 @@ auto partially_ordered(meta::type_declaration& t) -> void // // A type with (copy and move) x (construction and assignment) // -#line 1695 "reflect.h2" +#line 1699 "reflect.h2" auto copyable(meta::type_declaration& t) -> void { // If the user explicitly wrote any of the copy/move functions, @@ -4625,12 +5399,12 @@ auto copyable(meta::type_declaration& t) -> void }} } -#line 1723 "reflect.h2" +#line 1727 "reflect.h2" // copy_constructible // // A type with (copy and move) construction // -#line 1727 "reflect.h2" +#line 1731 "reflect.h2" auto copy_constructible(meta::type_declaration& t) -> void { // If the user explicitly wrote any of the copy/move constructors, @@ -4656,14 +5430,14 @@ auto copy_constructible(meta::type_declaration& t) -> void }} } -#line 1753 "reflect.h2" +#line 1757 "reflect.h2" //----------------------------------------------------------------------- // // hashable // // A memberwise hashable type // -#line 1759 "reflect.h2" +#line 1763 "reflect.h2" auto hashable(meta::type_declaration& t) -> void { CPP2_UFCS(require)(t, !(CPP2_UFCS(empty)(CPP2_UFCS(get_member_objects)(t))), @@ -4689,7 +5463,7 @@ auto hashable(meta::type_declaration& t) -> void CPP2_UFCS(add_member)(t, cpp2::move(hash) + "\n return ret;\n }"); } -#line 1785 "reflect.h2" +#line 1789 "reflect.h2" //----------------------------------------------------------------------- // // basic_value @@ -4697,7 +5471,7 @@ auto hashable(meta::type_declaration& t) -> void // A regular type: copyable, plus has public default construction // and no protected or virtual functions // -#line 1792 "reflect.h2" +#line 1796 "reflect.h2" auto basic_value(meta::type_declaration& t) -> void { CPP2_UFCS(copyable)(t); @@ -4726,28 +5500,28 @@ auto basic_value(meta::type_declaration& t) -> void // // Note: the ordering that should be encouraged as default gets the nice name // -#line 1820 "reflect.h2" +#line 1824 "reflect.h2" auto value(meta::type_declaration& t) -> void { CPP2_UFCS(ordered)(t); CPP2_UFCS(basic_value)(t); } -#line 1826 "reflect.h2" +#line 1830 "reflect.h2" auto weakly_ordered_value(meta::type_declaration& t) -> void { CPP2_UFCS(weakly_ordered)(t); CPP2_UFCS(basic_value)(t); } -#line 1832 "reflect.h2" +#line 1836 "reflect.h2" auto partially_ordered_value(meta::type_declaration& t) -> void { CPP2_UFCS(partially_ordered)(t); CPP2_UFCS(basic_value)(t); } -#line 1839 "reflect.h2" +#line 1843 "reflect.h2" //----------------------------------------------------------------------- // // C.20: If you can avoid defining default operations, do @@ -4770,7 +5544,7 @@ auto partially_ordered_value(meta::type_declaration& t) -> void // // a type without declared copy/move/destructor functions // -#line 1861 "reflect.h2" +#line 1865 "reflect.h2" auto cpp1_rule_of_zero(meta::type_declaration& t) -> void { for ( auto& mf : CPP2_UFCS(get_member_functions)(t) ) @@ -4813,7 +5587,7 @@ auto cpp1_rule_of_zero(meta::type_declaration& t) -> void // parameters instead of concrete forwarding parameters (mainly used // for cppfront internal use, so cppfront builds under GCC 10) // -#line 1903 "reflect.h2" +#line 1907 "reflect.h2" auto cpp2_struct(meta::type_declaration& t) -> void { std::string ctor_params {}; @@ -4870,7 +5644,7 @@ value_member_info::value_member_info(auto const& name_, auto const& type_, auto , type{ type_ } , value{ value_ }{} -#line 1955 "reflect.h2" +#line 1959 "reflect.h2" //----------------------------------------------------------------------- // // "C enumerations constitute a curiously half-baked concept. ... @@ -4889,7 +5663,7 @@ value_member_info::value_member_info(auto const& name_, auto const& type_, auto // a type together with named constants that are its possible values // -#line 1978 "reflect.h2" +#line 1982 "reflect.h2" auto basic_enum( meta::type_declaration& t, auto const& nextval, @@ -4914,7 +5688,7 @@ auto basic_enum( { std::string value{"-1"}; -#line 2001 "reflect.h2" +#line 2005 "reflect.h2" for ( auto const& m : CPP2_UFCS(get_members)(t) ) if ( CPP2_UFCS(is_member_object)(m)) @@ -4956,7 +5730,7 @@ std::string value{"-1"}; } } -#line 2041 "reflect.h2" +#line 2045 "reflect.h2" if ((CPP2_UFCS(empty)(enumerators))) { CPP2_UFCS(error)(t, "an enumeration must contain at least one enumerator value"); return ; @@ -5007,7 +5781,7 @@ std::string value{"-1"}; } } -#line 2092 "reflect.h2" +#line 2096 "reflect.h2" // 2. Replace: Erase the contents and replace with modified contents // // Note that most values and functions are declared as '==' compile-time values, i.e. Cpp1 'constexpr' @@ -5057,7 +5831,7 @@ std::string to_string_impl{" to_string_impl: (this, prefix: std::string_view" // Provide 'to_string' and 'to_code' functions to print enumerator // name(s) as human-readable strings or as code expressions -#line 2139 "reflect.h2" +#line 2143 "reflect.h2" { if (bitwise) { to_string_impl += ", separator: std::string_view ) -> std::string = { \n" @@ -5098,7 +5872,7 @@ std::string to_string_impl{" to_string_impl: (this, prefix: std::string_view" } } -#line 2178 "reflect.h2" +#line 2182 "reflect.h2" if (bitwise) { CPP2_UFCS(add_member)(t, " to_string: (this) -> std::string = to_string_impl( \"\", \", \" );"); CPP2_UFCS(add_member)(t, " to_code : (this) -> std::string = to_string_impl( \"" + cpp2::to_string(CPP2_UFCS(name)(t)) + "::\", \" | \" );"); @@ -5112,7 +5886,7 @@ std::string from_string{" from_string: (s: std::string_view) -> " + cpp2::to_ // Provide a 'from_string' function to parse strings into enumerators -#line 2189 "reflect.h2" +#line 2193 "reflect.h2" { std::string_view prefix {""}; std::string_view combine_op {"return"}; @@ -5134,7 +5908,7 @@ std::string from_string{" from_string: (s: std::string_view) -> " + cpp2::to_ { std::string_view else_{""}; -#line 2209 "reflect.h2" +#line 2213 "reflect.h2" for ( auto const& e : cpp2::move(enumerators) ) { from_string += " " + cpp2::to_string(else_) + "if \"" + cpp2::to_string(e.name) + "\" == x { " + cpp2::to_string(combine_op) + " " + cpp2::to_string(CPP2_UFCS(name)(t)) + "::" + cpp2::to_string(e.name) + "; }\n"; @@ -5142,7 +5916,7 @@ std::string_view else_{""}; } } -#line 2215 "reflect.h2" +#line 2219 "reflect.h2" if (bitwise) { from_string += " else { break outer; }\n" " }\n" @@ -5158,11 +5932,11 @@ std::string_view else_{""}; } } -#line 2229 "reflect.h2" +#line 2233 "reflect.h2" CPP2_UFCS(add_member)(t, " from_code: (s: std::string_view) -> " + cpp2::to_string(CPP2_UFCS(name)(t)) + " = { str: std::string = s; return from_string( cpp2::string_util::replace_all(str, \"" + cpp2::to_string(CPP2_UFCS(name)(t)) + "::\", \"\" ) ); }"); } -#line 2233 "reflect.h2" +#line 2237 "reflect.h2" //----------------------------------------------------------------------- // // "An enum[...] is a totally ordered value type that stores a @@ -5172,7 +5946,7 @@ std::string_view else_{""}; // // -- P0707R4, section 3 // -#line 2242 "reflect.h2" +#line 2246 "reflect.h2" auto cpp2_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with an incrementing value generator @@ -5189,7 +5963,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void ); } -#line 2259 "reflect.h2" +#line 2263 "reflect.h2" //----------------------------------------------------------------------- // // "flag_enum expresses an enumeration that stores values @@ -5200,7 +5974,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void // // -- P0707R4, section 3 // -#line 2269 "reflect.h2" +#line 2273 "reflect.h2" auto flag_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with a power-of-two value generator @@ -5222,7 +5996,7 @@ auto flag_enum(meta::type_declaration& t) -> void ); } -#line 2291 "reflect.h2" +#line 2295 "reflect.h2" //----------------------------------------------------------------------- // // "As with void*, programmers should know that unions [...] are @@ -5247,7 +6021,7 @@ auto flag_enum(meta::type_declaration& t) -> void // a type that contains exactly one of a fixed set of values at a time // -#line 2315 "reflect.h2" +#line 2319 "reflect.h2" auto cpp2_union(meta::type_declaration& t) -> void { std::vector alternatives {}; @@ -5256,7 +6030,7 @@ auto value{0}; // 1. Gather: All the user-written members, and find/compute the max size -#line 2322 "reflect.h2" +#line 2326 "reflect.h2" for ( auto const& m : CPP2_UFCS(get_members)(t) ) { do @@ -5286,7 +6060,7 @@ auto value{0}; } while (false); ++value; } } -#line 2350 "reflect.h2" +#line 2354 "reflect.h2" std::string discriminator_type {}; if (cpp2::impl::cmp_less(CPP2_UFCS(ssize)(alternatives),std::numeric_limits::max())) { discriminator_type = "i8"; @@ -5301,7 +6075,7 @@ auto value{0}; discriminator_type = "i64"; }}} -#line 2365 "reflect.h2" +#line 2369 "reflect.h2" // 2. Replace: Erase the contents and replace with modified contents CPP2_UFCS(remove_marked_members)(t); @@ -5310,7 +6084,7 @@ std::string storage{" _storage: cpp2::aligned_storage t) -> void { std::cout << CPP2_UFCS(print)(t) << "\n"; } -#line 2472 "reflect.h2" +#line 2476 "reflect.h2" //----------------------------------------------------------------------- // // noisy - make each function print its name and signature, // so the programmer can see what's called // -#line 2477 "reflect.h2" +#line 2481 "reflect.h2" auto noisy(cpp2::impl::in t) -> void { for ( @@ -5447,7 +6221,7 @@ auto noisy(cpp2::impl::in t) -> void } } -#line 2494 "reflect.h2" +#line 2498 "reflect.h2" //----------------------------------------------------------------------- // // python - expose the type using pybind11 @@ -5455,14 +6229,14 @@ auto noisy(cpp2::impl::in t) -> void // *** Basic proof of concept only, limited and not well tested // Hardcoded for pybind11 and g++10 and my local cppfront include path // -#line 2501 "reflect.h2" +#line 2505 "reflect.h2" [[nodiscard]] auto python_param_names_and_types(cpp2::impl::in mf) -> python_param_names_and_types_ret -#line 2507 "reflect.h2" +#line 2511 "reflect.h2" { std::string names {}; std::string types {}; -#line 2508 "reflect.h2" +#line 2512 "reflect.h2" for ( auto const& param : CPP2_UFCS(get_parameters)(mf) ) if ( CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param)) != "this") @@ -5476,7 +6250,7 @@ auto noisy(cpp2::impl::in t) -> void }return { std::move(names), std::move(types) }; } -#line 2521 "reflect.h2" +#line 2525 "reflect.h2" auto python(meta::type_declaration& t) -> void { std::string bind {}; @@ -5513,14 +6287,14 @@ auto python(meta::type_declaration& t) -> void CPP2_UFCS(add_extra_build_step)(t, cpp2::move(build)); } -#line 2558 "reflect.h2" +#line 2562 "reflect.h2" //----------------------------------------------------------------------- // // javascript - expose the type using emscripten // // *** Basic proof of concept only, limited and not well tested // -#line 2564 "reflect.h2" +#line 2568 "reflect.h2" auto javascript(meta::type_declaration& t) -> void { std::string bind {}; @@ -5557,12 +6331,12 @@ auto javascript(meta::type_declaration& t) -> void CPP2_UFCS(disable_ref_qualifier_generation)(t); } -#line 2601 "reflect.h2" +#line 2605 "reflect.h2" //----------------------------------------------------------------------- // // For reflection test cases // -#line 2605 "reflect.h2" +#line 2609 "reflect.h2" auto sample_print(cpp2::impl::in s, cpp2::impl::in indent) -> void { std::cout @@ -5571,1238 +6345,3887 @@ auto sample_print(cpp2::impl::in s, cpp2::impl::in << "\n"; } -#line 2614 "reflect.h2" -//----------------------------------------------------------------------- -// -// sample_traverser serves two purposes: -// -// - infrastructure for writing reflection API test cases -// -// - a sample for how code can use the reflection API, notably -// for reflecting on function bodies (statements, expressions) -// +#line 2619 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in decl) -> void{ + traverse(decl); + } -#line 2624 "reflect.h2" -auto sample_traverser(cpp2::impl::in decl, cpp2::impl::in indent) -> void -{ - sample_print("Declaration: " + cpp2::to_string(CPP2_UFCS(name)(decl)) + "", indent); +#line 2623 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in decl) -> void + { + if (CPP2_UFCS(is_function)(decl)) { + pre_traverse(CPP2_UFCS(as_function)(decl)); + } - if (CPP2_UFCS(is_function)(decl)) { - sample_traverser(CPP2_UFCS(as_function)(decl), indent + 1); - } + if (CPP2_UFCS(is_object)(decl)) { + pre_traverse(CPP2_UFCS(as_object)(decl)); + } - if (CPP2_UFCS(is_object)(decl)) { - sample_traverser(CPP2_UFCS(as_object)(decl), indent + 1); - } + if (CPP2_UFCS(is_type)(decl)) { + pre_traverse(CPP2_UFCS(as_type)(decl)); + } - if (CPP2_UFCS(is_type)(decl)) { - sample_traverser(CPP2_UFCS(as_type)(decl), indent + 1); + // ... + // ... extend as desired to namespace, alias, etc. + // ... } - // ... - // ... extend as desired to namespace, alias, etc. - // ... -} - -#line 2646 "reflect.h2" -auto sample_traverser(cpp2::impl::in f, cpp2::impl::in indent) -> void -{ - sample_print("Function: " + cpp2::to_string(CPP2_UFCS(name)(f)) + "", indent + 1); +#line 2643 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in f) -> void{ + traverse(f); + } - auto parameters {CPP2_UFCS(get_parameters)(f)}; - if (!(CPP2_UFCS(empty)(parameters))) { - sample_print("Parameters:", indent + 2); +#line 2647 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in f) -> void + { + auto parameters {CPP2_UFCS(get_parameters)(f)}; for ( auto const& param : cpp2::move(parameters) ) { - sample_traverser(param, indent + 3); + pre_traverse(param); } - } - auto returns {CPP2_UFCS(get_returns)(f)}; - if (!(CPP2_UFCS(empty)(returns))) { - sample_print("Returns:", indent + 2); + auto returns {CPP2_UFCS(get_returns)(f)}; for ( auto const& param : cpp2::move(returns) ) { - sample_traverser(param, indent + 3); + pre_traverse(param); } - } - sample_print("Body:", indent + 2); - if (!(CPP2_UFCS(has_compound_body)(f))) { - sample_traverser(CPP2_UFCS(get_body)(f), indent + 3); + if (!(CPP2_UFCS(has_compound_body)(f))) { + pre_traverse(CPP2_UFCS(get_body)(f)); + } + else { + pre_traverse(CPP2_UFCS(get_compound_body)(f)); + } } - else { - sample_traverser(CPP2_UFCS(get_compound_body)(f), indent + 3); + +#line 2668 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in o) -> void{ + traverse(o); } -} -#line 2676 "reflect.h2" -auto sample_traverser(cpp2::impl::in o, cpp2::impl::in indent) -> void -{ - sample_print("Object: name " + cpp2::to_string(CPP2_UFCS(name)(o)) + ", type " + cpp2::to_string(CPP2_UFCS(type)(o)) + "", indent); - if (CPP2_UFCS(has_initializer)(o)) { - sample_print("Initializer:", indent + 1); - sample_traverser(CPP2_UFCS(get_initializer)(o), indent + 2); +#line 2672 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in o) -> void + { + if (CPP2_UFCS(has_initializer)(o)) { + pre_traverse(CPP2_UFCS(get_initializer)(o)); + } } -} -#line 2686 "reflect.h2" -auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent) -> void -{ - sample_print("Type: " + cpp2::to_string(CPP2_UFCS(name)(t)) + "", indent); +#line 2680 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in t) -> void{ + traverse(t); + } - if (CPP2_UFCS(parent_is_nonglobal_namespace)(t)) +#line 2684 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in t) -> void { - auto ns {CPP2_UFCS(as_nonglobal_namespace)(CPP2_UFCS(get_parent)(t))}; - sample_print("is a member of namespace " + cpp2::to_string(CPP2_UFCS(name)(ns)) + " which contains the following names:", indent + 1); - for ( auto const& m : CPP2_UFCS(get_members)(ns) ) { - sample_print(CPP2_UFCS(name)(m), indent + 2); + for ( auto const& m : CPP2_UFCS(get_members)(t) ) { + pre_traverse(m); } - CPP2_UFCS(add_member)(ns, "add_1: (x) = x+1;"); - static_cast(cpp2::move(ns)); } - for ( auto const& m : CPP2_UFCS(get_members)(t) ) { - sample_traverser(m, indent + 1); +#line 2692 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in t) -> void{ + traverse(t); } -} -#line 2707 "reflect.h2" -auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent) -> void -{ - sample_print("parameter:", indent); +#line 2696 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in t) -> void + { + pre_traverse(CPP2_UFCS(get_declaration)(t)); + } - auto pass {CPP2_UFCS(get_passing_style)(t)}; - if (pass == passing_style::in) { sample_print("passing style: in", indent + 1);} - if (pass == passing_style::in_ref) { sample_print("passing style: in_ref", indent + 1);} - if (pass == passing_style::copy) { sample_print("passing style: copy", indent + 1);} - if (pass == passing_style::inout) { sample_print("passing style: inout", indent + 1);} - if (pass == passing_style::out) { sample_print("passing style: out", indent + 1);} - if (pass == passing_style::move) { sample_print("passing style: move", indent + 1);} - if (pass == passing_style::forward) { sample_print("passing style: forward", indent + 1);} - if (cpp2::move(pass) == passing_style::forward_ref) {sample_print("passing style: forward_ref", indent + 1); } +#line 2701 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); + } - sample_print("declaration:", indent + 1); - sample_traverser(CPP2_UFCS(get_declaration)(t), indent + 2); -} +#line 2705 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in stmt) -> void + { + if (CPP2_UFCS(is_expression_statement)(stmt)) { + pre_traverse(CPP2_UFCS(get_expression)(CPP2_UFCS(as_expression_statement)(stmt))); + } -#line 2726 "reflect.h2" -auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void -{ - auto params {CPP2_UFCS(get_parameters)(stmt)}; - if (!(CPP2_UFCS(empty)(params))) { - sample_print("statement parameters: ", indent); - for ( auto const& param : cpp2::move(params) ) { - sample_traverser(param, indent + 1); + if (CPP2_UFCS(is_compound_statement)(stmt)) { + pre_traverse(CPP2_UFCS(as_compound_statement)(stmt)); } - } - if (CPP2_UFCS(is_expression_statement)(stmt)) { - sample_traverser(CPP2_UFCS(get_expression)(CPP2_UFCS(as_expression_statement)(stmt)), indent); + if (CPP2_UFCS(is_selection_statement)(stmt)) + { + pre_traverse(CPP2_UFCS(as_selection_statement)(stmt)); + } + + if (CPP2_UFCS(is_declaration)(stmt)) { + pre_traverse(CPP2_UFCS(as_declaration)(stmt)); + } + + if (CPP2_UFCS(is_return_statement)(stmt)) { + pre_traverse(CPP2_UFCS(as_return_statement)(stmt)); + } + + if (CPP2_UFCS(is_iteration_statement)(stmt)) { + pre_traverse(CPP2_UFCS(as_iteration_statement)(stmt)); + } + + // TODO: + // using + // contract + // inspect + // jump } - if (CPP2_UFCS(is_compound_statement)(stmt)) { - sample_traverser(CPP2_UFCS(as_compound_statement)(stmt), indent); +#line 2740 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } - if (CPP2_UFCS(is_selection_statement)(stmt)) +#line 2744 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in stmt) -> void { - auto sel {CPP2_UFCS(as_selection_statement)(stmt)}; - sample_print("" + cpp2::to_string(CPP2_UFCS(get_identifier)(sel)) + " statement", indent); + auto stmts {CPP2_UFCS(get_statements)(stmt)}; - sample_print("condition:", indent + 1); - sample_traverser(CPP2_UFCS(get_expression)(sel), indent + 2); + for ( auto const& cur : cpp2::move(stmts) ) { + pre_traverse(cur); + } + } - sample_print("true branch:", indent + 1); - sample_traverser(CPP2_UFCS(get_true_branch)(sel), indent + 2); +#line 2754 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); + } - if (CPP2_UFCS(has_false_branch)(sel)) { - sample_print("false branch:", indent + 1); - sample_traverser(CPP2_UFCS(get_false_branch)(cpp2::move(sel)), indent + 2); +#line 2758 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in stmt) -> void + { + if (CPP2_UFCS(has_expression)(stmt)) { + pre_traverse(CPP2_UFCS(get_expression)(stmt)); } } - if (CPP2_UFCS(is_declaration)(stmt)) { - sample_traverser(CPP2_UFCS(as_declaration)(stmt), indent + 1); +#line 2766 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } - if (CPP2_UFCS(is_return_statement)(stmt)) { - sample_traverser(CPP2_UFCS(as_return_statement)(stmt), indent + 1); +#line 2770 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in stmt) -> void + { + if (CPP2_UFCS(is_do)(stmt) || CPP2_UFCS(is_while)(stmt)) { + pre_traverse(CPP2_UFCS(get_do_while_condition)(stmt)); + pre_traverse(CPP2_UFCS(get_do_while_body)(stmt)); + } + else { + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_for)(stmt)) ) { cpp2::cpp2_default.report_violation(""); } + pre_traverse(CPP2_UFCS(get_for_range)(stmt)); + pre_traverse(CPP2_UFCS(get_for_parameter)(stmt)); + pre_traverse(CPP2_UFCS(get_for_body)(stmt)); + } + + if (CPP2_UFCS(has_next)(stmt)) { + pre_traverse(CPP2_UFCS(get_next_expression)(stmt)); + } } - if (CPP2_UFCS(is_iteration_statement)(stmt)) { - sample_traverser(CPP2_UFCS(as_iteration_statement)(stmt), indent + 1); +#line 2789 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } - // TODO: - // using - // contract - // inspect - // jump -} - -#line 2781 "reflect.h2" -auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void -{ - auto stmts {CPP2_UFCS(get_statements)(stmt)}; +#line 2793 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in stmt) -> void + { + pre_traverse(CPP2_UFCS(get_expression)(stmt)); + pre_traverse(CPP2_UFCS(get_true_branch)(stmt)); - if (CPP2_UFCS(empty)(stmts)) { - sample_print("compound statement (empty)", indent); - return ; + if (CPP2_UFCS(has_false_branch)(stmt)) { + pre_traverse(CPP2_UFCS(get_false_branch)(stmt)); + } } - // Else - sample_print("compound statement", indent); - for ( auto const& stmt2 : cpp2::move(stmts) ) { - sample_traverser(stmt2, indent + 1); +#line 2804 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in expr) -> void + { + // Nothing to select here. + traverse(expr); } -} -#line 2798 "reflect.h2" -auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void -{ - sample_print("return statement", indent); - if (CPP2_UFCS(has_expression)(stmt)) { - sample_print("expression", indent + 1); - sample_traverser(CPP2_UFCS(get_expression)(stmt), indent + 2); +#line 2810 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in expr) -> void + { + // An expression has other shortcuts to query deeper properties, + // but let's just traverse all the nested grammer elements to + // show how that traversal works + + // The expressions use the pre_traverse function to decide which expression + // they are. The correct one calls traverse only once. + + // The expression's basic payload is just an assignment expression + pre_traverse(CPP2_UFCS(as_assignment_expression)(expr)); } -} -#line 2808 "reflect.h2" -auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void -{ - if (CPP2_UFCS(is_do)(stmt) || CPP2_UFCS(is_while)(stmt)) { - if (CPP2_UFCS(is_do)(stmt)) { - sample_print("do loop:", indent); +#line 2824 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual assignment, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); } + + // Else we're at an actual binary expression with a rhs else { - sample_print("while loop:", indent); + traverse(binexpr); } - sample_print("condition:", indent + 1); - sample_traverser(CPP2_UFCS(get_do_while_condition)(stmt), indent + 2); - sample_print("body:", indent + 1); - sample_traverser(CPP2_UFCS(get_do_while_body)(stmt), indent + 2); - } - else { - if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_for)(stmt)) ) { cpp2::cpp2_default.report_violation(""); } - sample_print("for loop:", indent); - sample_print("range:", indent + 1); - sample_traverser(CPP2_UFCS(get_for_range)(stmt), indent + 2); - sample_print("parameter:", indent + 1); - sample_traverser(CPP2_UFCS(get_for_parameter)(stmt), indent + 2); - sample_print("body:", indent + 1); - sample_traverser(CPP2_UFCS(get_for_body)(stmt), indent + 2); - } - - if (CPP2_UFCS(has_next)(stmt)) { - sample_print("next expression:", indent + 1); - sample_traverser(CPP2_UFCS(get_next_expression)(stmt), indent + 2); } -} -#line 2840 "reflect.h2" -auto sample_traverser(cpp2::impl::in expr, cpp2::impl::in indent) -> void -{ - // An expression has other shortcuts to query deeper properties, - // but let's just traverse all the nested grammar elements to - // show how that traversal works +#line 2841 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; - // The expression's basic payload is just an assignment expression - // today - this can change when we add try-expressions - if (CPP2_UFCS(is_assignment_expression)(expr)) { - sample_traverser(CPP2_UFCS(as_assignment_expression)(expr), indent); + for ( + auto const& term : cpp2::move(terms) ) + { + traverse(CPP2_UFCS(get_term)(term)); + } } -} -#line 2854 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 2852 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual assignment, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual logical-or, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("assignment", indent); -{ -auto first{true}; +#line 2869 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2870 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 2880 "reflect.h2" } -} -#line 2884 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 2881 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual logical-or, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual logical-and, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("logical-or", indent); -{ -auto first{true}; +#line 2898 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2900 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 2910 "reflect.h2" } -} -#line 2914 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 2909 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual logical-and, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual bit-or, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("logical-and", indent); -{ -auto first{true}; +#line 2926 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2930 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 2940 "reflect.h2" } -} -#line 2944 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 2937 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual bit-or, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual bit-xor, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("bit-or", indent); -{ -auto first{true}; +#line 2954 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2960 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 2970 "reflect.h2" } -} -#line 2974 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 2966 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual bit-xor, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual bit-and, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("bit-xor", indent); -{ -auto first{true}; +#line 2983 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2990 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 3000 "reflect.h2" } -} -#line 3004 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 2995 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual bit-and, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual equality, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("bit-and", indent); -{ -auto first{true}; +#line 3012 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3020 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 3030 "reflect.h2" } -} -#line 3034 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 3023 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual equality, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual relational, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("equality", indent); -{ -auto first{true}; +#line 3040 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3050 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 3060 "reflect.h2" - } -} - -#line 3064 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - - // If this has only one term, it's not an actual relational, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); } - // Else we're at an actual binary expression with a rhs - else { - sample_print("relational", indent); -{ -auto first{true}; +#line 3051 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } -#line 3080 "reflect.h2" - for ( - auto const& term : cpp2::move(terms) ) - { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + // If this has only one term, it's not an actual compare, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); } -} -#line 3090 "reflect.h2" - } -} - -#line 3094 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual compare, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("compare", indent); -{ -auto first{true}; +#line 3068 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3110 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 3120 "reflect.h2" } -} -#line 3124 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 3079 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual shift, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual shift, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("shift", indent); -{ -auto first{true}; +#line 3096 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3140 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 3150 "reflect.h2" } -} -#line 3154 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 3107 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual additive, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual additive, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("additive", indent); -{ -auto first{true}; +#line 3124 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3170 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 3180 "reflect.h2" } -} -#line 3184 "reflect.h2" -auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(binexpr)}; - if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } +#line 3136 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } - // If this has only one term, it's not an actual multiplicative, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(ssize)(terms) == 1) { - sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + // If this has only one term, it's not an actual multiplicative, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms)))); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("multiplicative", indent); -{ -auto first{true}; +#line 3153 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3200 "reflect.h2" for ( auto const& term : cpp2::move(terms) ) { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - } - first = false; - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + traverse(CPP2_UFCS(get_term)(term)); } -} -#line 3210 "reflect.h2" } -} -#line 3214 "reflect.h2" -auto sample_traverser(cpp2::impl::in isas, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(isas)}; +#line 3164 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in isas) -> void + { + auto terms {CPP2_UFCS(get_terms)(isas)}; - // If this has no additional terms, it's not an actual is-as, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(empty)(terms)) { - sample_traverser(CPP2_UFCS(get_expression)(isas), indent); + // If this has no additional terms, it's not an actual is-as, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(empty)(cpp2::move(terms))) { + pre_traverse(CPP2_UFCS(get_expression)(isas)); + } + + // Else we're at an actual is-as expression with a rhs + else { + traverse(isas); + } } - // Else we're at an actual is-as expression with a rhs - else { - sample_print("is-as expression", indent); +#line 3180 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in isas) -> void + { + auto terms {CPP2_UFCS(get_terms)(isas)}; - sample_print("expression", indent + 1); - sample_traverser(CPP2_UFCS(get_expression)(isas), indent + 2); + pre_traverse(CPP2_UFCS(get_expression)(isas)); for ( auto const& term : cpp2::move(terms) ) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); - sample_print("term:", indent + 1); - sample_traverser(CPP2_UFCS(get_expr)(term), indent + 2); + traverse(CPP2_UFCS(get_expr)(term)); } } -} -#line 3240 "reflect.h2" -auto sample_traverser(cpp2::impl::in exprs, cpp2::impl::in indent) -> void -{ - if (CPP2_UFCS(is_empty)(exprs)) { - sample_print("()", indent); - } - else { - sample_print("(", indent); +#line 3191 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in exprs) -> void + { for ( auto const& expr : CPP2_UFCS(get_expressions)(exprs) ) { - sample_traverser(expr, indent + 1); + traverse(expr); } - sample_print(")", indent); } -} - -#line 3255 "reflect.h2" -auto sample_traverser(cpp2::impl::in prefix, cpp2::impl::in indent) -> void -{ - auto ops {CPP2_UFCS(get_ops)(prefix)}; - // If this has no additional ops, it's not a naked prefix expr, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(empty)(ops)) { - sample_traverser(CPP2_UFCS(get_postfix_expression)(prefix), indent); - } +#line 3198 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in prefix) -> void + { + auto ops {CPP2_UFCS(get_ops)(prefix)}; - // Else we're at an actual prefix expression with ops - else { - sample_print("prefix expression", indent); + // If this has no additional ops, it's not a naked prefix expr, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(empty)(cpp2::move(ops))) { + pre_traverse(CPP2_UFCS(get_postfix_expression)(prefix)); + } - for ( auto const& op : cpp2::move(ops) ) { - sample_print("op: " + cpp2::to_string(op) + "", indent + 1); + // Else we're at an actual prefix expression with ops + else { + traverse(prefix); } + } - sample_print("expression", indent + 1); - sample_traverser(CPP2_UFCS(get_postfix_expression)(prefix), indent + 2); +#line 3214 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in prefix) -> void + { + pre_traverse(CPP2_UFCS(get_postfix_expression)(prefix)); } -} -#line 3279 "reflect.h2" -auto sample_traverser(cpp2::impl::in postfix, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(postfix)}; +#line 3219 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in postfix) -> void + { + auto terms {CPP2_UFCS(get_terms)(postfix)}; - // If this has no additional terms, it's not a naked postfix expr, - // it's holding a lower grammar production so go traverse that - if (CPP2_UFCS(empty)(terms)) { - sample_traverser(CPP2_UFCS(get_primary_expression)(postfix), indent); + // If this has no additional terms, it's not a naked postfix expr, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(empty)(cpp2::move(terms))) { + traverse(CPP2_UFCS(get_primary_expression)(postfix)); + } + + // Else we're at an actual postfix expression with ops + else { + traverse(postfix); + } } - // Else we're at an actual postfix expression with ops - else { - sample_print("postfix expression", indent); +#line 3235 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in postfix) -> void + { + auto terms {CPP2_UFCS(get_terms)(postfix)}; - sample_print("expression", indent + 1); - sample_traverser(CPP2_UFCS(get_primary_expression)(postfix), indent + 2); + traverse(CPP2_UFCS(get_primary_expression)(postfix)); for ( auto const& term : cpp2::move(terms) ) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); if (CPP2_UFCS(is_id_expression)(term)) { - sample_traverser(CPP2_UFCS(get_id_expression)(term), indent + 1); + traverse(CPP2_UFCS(get_id_expression)(term)); } else {if (CPP2_UFCS(is_expression_list)(term)) { - sample_traverser(CPP2_UFCS(get_expression_list)(term), indent + 1); + traverse(CPP2_UFCS(get_expression_list)(term)); } else {if (CPP2_UFCS(is_expression)(term)) { - sample_traverser(CPP2_UFCS(get_expression)(term), indent + 1); + traverse(CPP2_UFCS(get_expression)(term)); }}} } } -} -#line 3312 "reflect.h2" -auto sample_traverser(cpp2::impl::in uid, cpp2::impl::in indent) -> void -{ - if (CPP2_UFCS(is_identifier)(uid)) { - sample_print(CPP2_UFCS(get_identifier)(uid), indent); +#line 3254 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in uid) -> void + { + static_cast(uid); } - else { - sample_print(CPP2_UFCS(to_string)(uid), indent + 1); + +#line 3260 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in qid) -> void + { + for ( + auto const& term : CPP2_UFCS(get_terms)(qid) ) + { + traverse(CPP2_UFCS(get_unqualified)(term)); + } } -} -#line 3323 "reflect.h2" -auto sample_traverser(cpp2::impl::in qid, cpp2::impl::in indent) -> void -{ -{ -auto first{true}; +#line 3270 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in tid) -> void + { + if (CPP2_UFCS(is_postfix_expression)(tid)) { + traverse(CPP2_UFCS(as_postfix_expression)(tid)); + } + else {if (CPP2_UFCS(is_qualified_id)(tid)) { + traverse(CPP2_UFCS(as_qualified_id)(tid)); + } + else {if (CPP2_UFCS(is_unqualified_id)(tid)) { + traverse(CPP2_UFCS(as_unqualified_id)(tid)); + } + else { + // Regular type_id + }}} + } + +#line 3287 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in primary) -> void + { + if (CPP2_UFCS(is_identifier)(primary)) { + // Regular identifier + } + else {if (CPP2_UFCS(is_expression_list)(primary)) { + traverse(CPP2_UFCS(as_expression_list)(primary)); + } + else {if (CPP2_UFCS(is_literal)(primary)) { + // Regular literal + } + else {if (CPP2_UFCS(is_declaration)(primary)) { + // TODO: traverse(primary.as_declaration()); + } + else { + // Regular primary + }}}} + } + +#line 3307 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in idexpr) -> void + { + if (CPP2_UFCS(is_identifier)(idexpr)) { + // Regular id + } + else {if (CPP2_UFCS(is_qualified)(idexpr)) { + traverse(CPP2_UFCS(as_qualified)(idexpr)); + } + else {if (CPP2_UFCS(is_unqualified)(idexpr)) { + traverse(CPP2_UFCS(as_unqualified)(idexpr)); + } + else { + // Regular id expr + }}} + } + +#line 3325 "reflect.h2" +//----------------------------------------------------------------------- +// +// sample_traverser serves two purposes: +// +// - infrastructure for writing reflection API test cases +// +// - a sample for how code can use the reflection API, notably +// for reflecting on function bodies (statements, expressions) +// + +#line 3335 "reflect.h2" +auto sample_traverser(cpp2::impl::in decl, cpp2::impl::in indent) -> void +{ + sample_print("Declaration: " + cpp2::to_string(CPP2_UFCS(name)(decl)) + "", indent); + + if (CPP2_UFCS(is_function)(decl)) { + sample_traverser(CPP2_UFCS(as_function)(decl), indent + 1); + } + + if (CPP2_UFCS(is_object)(decl)) { + sample_traverser(CPP2_UFCS(as_object)(decl), indent + 1); + } + + if (CPP2_UFCS(is_type)(decl)) { + sample_traverser(CPP2_UFCS(as_type)(decl), indent + 1); + } + + // ... + // ... extend as desired to namespace, alias, etc. + // ... +} + +#line 3357 "reflect.h2" +auto sample_traverser(cpp2::impl::in f, cpp2::impl::in indent) -> void +{ + sample_print("Function: " + cpp2::to_string(CPP2_UFCS(name)(f)) + "", indent + 1); + + auto parameters {CPP2_UFCS(get_parameters)(f)}; + if (!(CPP2_UFCS(empty)(parameters))) { + sample_print("Parameters:", indent + 2); + for ( auto const& param : cpp2::move(parameters) ) { + sample_traverser(param, indent + 3); + } + } + + auto returns {CPP2_UFCS(get_returns)(f)}; + if (!(CPP2_UFCS(empty)(returns))) { + sample_print("Returns:", indent + 2); + for ( auto const& param : cpp2::move(returns) ) { + sample_traverser(param, indent + 3); + } + } + + sample_print("Body:", indent + 2); + if (!(CPP2_UFCS(has_compound_body)(f))) { + sample_traverser(CPP2_UFCS(get_body)(f), indent + 3); + } + else { + sample_traverser(CPP2_UFCS(get_compound_body)(f), indent + 3); + } +} + +#line 3387 "reflect.h2" +auto sample_traverser(cpp2::impl::in o, cpp2::impl::in indent) -> void +{ + sample_print("Object: name " + cpp2::to_string(CPP2_UFCS(name)(o)) + ", type " + cpp2::to_string(CPP2_UFCS(type)(o)) + "", indent); + if (CPP2_UFCS(has_initializer)(o)) { + sample_print("Initializer:", indent + 1); + sample_traverser(CPP2_UFCS(get_initializer)(o), indent + 2); + } +} + +#line 3397 "reflect.h2" +auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent) -> void +{ + sample_print("Type: " + cpp2::to_string(CPP2_UFCS(name)(t)) + "", indent); + + if (CPP2_UFCS(parent_is_nonglobal_namespace)(t)) + { + auto ns {CPP2_UFCS(as_nonglobal_namespace)(CPP2_UFCS(get_parent)(t))}; + sample_print("is a member of namespace " + cpp2::to_string(CPP2_UFCS(name)(ns)) + " which contains the following names:", indent + 1); + for ( auto const& m : CPP2_UFCS(get_members)(ns) ) { + sample_print(CPP2_UFCS(name)(m), indent + 2); + } + CPP2_UFCS(add_member)(ns, "add_1: (x) = x+1;"); + static_cast(cpp2::move(ns)); + } + + for ( auto const& m : CPP2_UFCS(get_members)(t) ) { + sample_traverser(m, indent + 1); + } +} + +#line 3418 "reflect.h2" +auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent) -> void +{ + sample_print("parameter:", indent); + + auto pass {CPP2_UFCS(get_passing_style)(t)}; + if (pass == passing_style::in) { sample_print("passing style: in", indent + 1);} + if (pass == passing_style::in_ref) { sample_print("passing style: in_ref", indent + 1);} + if (pass == passing_style::copy) { sample_print("passing style: copy", indent + 1);} + if (pass == passing_style::inout) { sample_print("passing style: inout", indent + 1);} + if (pass == passing_style::out) { sample_print("passing style: out", indent + 1);} + if (pass == passing_style::move) { sample_print("passing style: move", indent + 1);} + if (pass == passing_style::forward) { sample_print("passing style: forward", indent + 1);} + if (cpp2::move(pass) == passing_style::forward_ref) {sample_print("passing style: forward_ref", indent + 1); } + + sample_print("declaration:", indent + 1); + sample_traverser(CPP2_UFCS(get_declaration)(t), indent + 2); +} + +#line 3437 "reflect.h2" +auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void +{ + auto params {CPP2_UFCS(get_parameters)(stmt)}; + if (!(CPP2_UFCS(empty)(params))) { + sample_print("statement parameters: ", indent); + for ( auto const& param : cpp2::move(params) ) { + sample_traverser(param, indent + 1); + } + } + + if (CPP2_UFCS(is_expression_statement)(stmt)) { + sample_traverser(CPP2_UFCS(get_expression)(CPP2_UFCS(as_expression_statement)(stmt)), indent); + } + + if (CPP2_UFCS(is_compound_statement)(stmt)) { + sample_traverser(CPP2_UFCS(as_compound_statement)(stmt), indent); + } + + if (CPP2_UFCS(is_selection_statement)(stmt)) + { + auto sel {CPP2_UFCS(as_selection_statement)(stmt)}; + sample_print("" + cpp2::to_string(CPP2_UFCS(get_identifier)(sel)) + " statement", indent); + + sample_print("condition:", indent + 1); + sample_traverser(CPP2_UFCS(get_expression)(sel), indent + 2); + + sample_print("true branch:", indent + 1); + sample_traverser(CPP2_UFCS(get_true_branch)(sel), indent + 2); + + if (CPP2_UFCS(has_false_branch)(sel)) { + sample_print("false branch:", indent + 1); + sample_traverser(CPP2_UFCS(get_false_branch)(cpp2::move(sel)), indent + 2); + } + } + + if (CPP2_UFCS(is_declaration)(stmt)) { + sample_traverser(CPP2_UFCS(as_declaration)(stmt), indent + 1); + } + + if (CPP2_UFCS(is_return_statement)(stmt)) { + sample_traverser(CPP2_UFCS(as_return_statement)(stmt), indent + 1); + } + + if (CPP2_UFCS(is_iteration_statement)(stmt)) { + sample_traverser(CPP2_UFCS(as_iteration_statement)(stmt), indent + 1); + } + + // TODO: + // using + // contract + // inspect + // jump +} + +#line 3492 "reflect.h2" +auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void +{ + auto stmts {CPP2_UFCS(get_statements)(stmt)}; + + if (CPP2_UFCS(empty)(stmts)) { + sample_print("compound statement (empty)", indent); + return ; + } + + // Else + sample_print("compound statement", indent); + for ( auto const& stmt2 : cpp2::move(stmts) ) { + sample_traverser(stmt2, indent + 1); + } +} + +#line 3509 "reflect.h2" +auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void +{ + sample_print("return statement", indent); + if (CPP2_UFCS(has_expression)(stmt)) { + sample_print("expression", indent + 1); + sample_traverser(CPP2_UFCS(get_expression)(stmt), indent + 2); + } +} + +#line 3519 "reflect.h2" +auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void +{ + if (CPP2_UFCS(is_do)(stmt) || CPP2_UFCS(is_while)(stmt)) { + if (CPP2_UFCS(is_do)(stmt)) { + sample_print("do loop:", indent); + } + else { + sample_print("while loop:", indent); + } + sample_print("condition:", indent + 1); + sample_traverser(CPP2_UFCS(get_do_while_condition)(stmt), indent + 2); + sample_print("body:", indent + 1); + sample_traverser(CPP2_UFCS(get_do_while_body)(stmt), indent + 2); + } + else { + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_for)(stmt)) ) { cpp2::cpp2_default.report_violation(""); } + sample_print("for loop:", indent); + sample_print("range:", indent + 1); + sample_traverser(CPP2_UFCS(get_for_range)(stmt), indent + 2); + sample_print("parameter:", indent + 1); + sample_traverser(CPP2_UFCS(get_for_parameter)(stmt), indent + 2); + sample_print("body:", indent + 1); + sample_traverser(CPP2_UFCS(get_for_body)(stmt), indent + 2); + } + + if (CPP2_UFCS(has_next)(stmt)) { + sample_print("next expression:", indent + 1); + sample_traverser(CPP2_UFCS(get_next_expression)(stmt), indent + 2); + } +} + +#line 3551 "reflect.h2" +auto sample_traverser(cpp2::impl::in expr, cpp2::impl::in indent) -> void +{ + // An expression has other shortcuts to query deeper properties, + // but let's just traverse all the nested grammar elements to + // show how that traversal works + + // The expression's basic payload is just an assignment expression + // today - this can change when we add try-expressions + if (CPP2_UFCS(is_assignment_expression)(expr)) { + sample_traverser(CPP2_UFCS(as_assignment_expression)(expr), indent); + } +} + +#line 3565 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual assignment, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("assignment", indent); +{ +auto first{true}; + +#line 3581 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3591 "reflect.h2" + } +} + +#line 3595 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual logical-or, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("logical-or", indent); +{ +auto first{true}; + +#line 3611 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3621 "reflect.h2" + } +} + +#line 3625 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual logical-and, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("logical-and", indent); +{ +auto first{true}; + +#line 3641 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3651 "reflect.h2" + } +} + +#line 3655 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual bit-or, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("bit-or", indent); +{ +auto first{true}; + +#line 3671 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3681 "reflect.h2" + } +} + +#line 3685 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual bit-xor, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("bit-xor", indent); +{ +auto first{true}; + +#line 3701 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3711 "reflect.h2" + } +} + +#line 3715 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual bit-and, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("bit-and", indent); +{ +auto first{true}; + +#line 3731 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3741 "reflect.h2" + } +} + +#line 3745 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual equality, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("equality", indent); +{ +auto first{true}; + +#line 3761 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3771 "reflect.h2" + } +} + +#line 3775 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual relational, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("relational", indent); +{ +auto first{true}; + +#line 3791 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3801 "reflect.h2" + } +} + +#line 3805 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual compare, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("compare", indent); +{ +auto first{true}; + +#line 3821 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3831 "reflect.h2" + } +} + +#line 3835 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual shift, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("shift", indent); +{ +auto first{true}; + +#line 3851 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3861 "reflect.h2" + } +} + +#line 3865 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual additive, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("additive", indent); +{ +auto first{true}; + +#line 3881 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3891 "reflect.h2" + } +} + +#line 3895 "reflect.h2" +auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(terms))) ) { cpp2::cpp2_default.report_violation(""); } + + // If this has only one term, it's not an actual multiplicative, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(ssize)(terms) == 1) { + sample_traverser(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(terms))), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("multiplicative", indent); +{ +auto first{true}; + +#line 3911 "reflect.h2" + for ( + auto const& term : cpp2::move(terms) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_term)(term), indent + 2); + } +} +#line 3921 "reflect.h2" + } +} + +#line 3925 "reflect.h2" +auto sample_traverser(cpp2::impl::in isas, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(isas)}; + + // If this has no additional terms, it's not an actual is-as, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(empty)(terms)) { + sample_traverser(CPP2_UFCS(get_expression)(isas), indent); + } + + // Else we're at an actual is-as expression with a rhs + else { + sample_print("is-as expression", indent); + + sample_print("expression", indent + 1); + sample_traverser(CPP2_UFCS(get_expression)(isas), indent + 2); + + for ( auto const& term : cpp2::move(terms) ) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + sample_print("term:", indent + 1); + sample_traverser(CPP2_UFCS(get_expr)(term), indent + 2); + } + } +} + +#line 3951 "reflect.h2" +auto sample_traverser(cpp2::impl::in exprs, cpp2::impl::in indent) -> void +{ + if (CPP2_UFCS(is_empty)(exprs)) { + sample_print("()", indent); + } + else { + sample_print("(", indent); + for ( auto const& expr : CPP2_UFCS(get_expressions)(exprs) ) { + sample_traverser(expr, indent + 1); + } + sample_print(")", indent); + } +} + +#line 3966 "reflect.h2" +auto sample_traverser(cpp2::impl::in prefix, cpp2::impl::in indent) -> void +{ + auto ops {CPP2_UFCS(get_ops)(prefix)}; + + // If this has no additional ops, it's not a naked prefix expr, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(empty)(ops)) { + sample_traverser(CPP2_UFCS(get_postfix_expression)(prefix), indent); + } + + // Else we're at an actual prefix expression with ops + else { + sample_print("prefix expression", indent); + + for ( auto const& op : cpp2::move(ops) ) { + sample_print("op: " + cpp2::to_string(op) + "", indent + 1); + } + + sample_print("expression", indent + 1); + sample_traverser(CPP2_UFCS(get_postfix_expression)(prefix), indent + 2); + } +} + +#line 3990 "reflect.h2" +auto sample_traverser(cpp2::impl::in postfix, cpp2::impl::in indent) -> void +{ + auto terms {CPP2_UFCS(get_terms)(postfix)}; + + // If this has no additional terms, it's not a naked postfix expr, + // it's holding a lower grammar production so go traverse that + if (CPP2_UFCS(empty)(terms)) { + sample_traverser(CPP2_UFCS(get_primary_expression)(postfix), indent); + } + + // Else we're at an actual postfix expression with ops + else { + sample_print("postfix expression", indent); + + sample_print("expression", indent + 1); + sample_traverser(CPP2_UFCS(get_primary_expression)(postfix), indent + 2); + + for ( auto const& term : cpp2::move(terms) ) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + if (CPP2_UFCS(is_id_expression)(term)) { + sample_traverser(CPP2_UFCS(get_id_expression)(term), indent + 1); + } + else {if (CPP2_UFCS(is_expression_list)(term)) { + sample_traverser(CPP2_UFCS(get_expression_list)(term), indent + 1); + } + else {if (CPP2_UFCS(is_expression)(term)) { + sample_traverser(CPP2_UFCS(get_expression)(term), indent + 1); + }}} + } + } +} + +#line 4023 "reflect.h2" +auto sample_traverser(cpp2::impl::in uid, cpp2::impl::in indent) -> void +{ + if (CPP2_UFCS(is_identifier)(uid)) { + sample_print(CPP2_UFCS(get_identifier)(uid), indent); + } + else { + sample_print(CPP2_UFCS(to_string)(uid), indent + 1); + } +} + +#line 4034 "reflect.h2" +auto sample_traverser(cpp2::impl::in qid, cpp2::impl::in indent) -> void +{ +{ +auto first{true}; + +#line 4037 "reflect.h2" + for ( + auto const& term : CPP2_UFCS(get_terms)(qid) ) + { + if (!(first)) { + sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + } + first = false; + sample_print("unqualified:", indent + 1); + sample_traverser(CPP2_UFCS(get_unqualified)(term), indent + 2); + } +} +#line 4047 "reflect.h2" +} + +#line 4050 "reflect.h2" +auto sample_traverser(cpp2::impl::in tid, cpp2::impl::in indent) -> void +{ + if (CPP2_UFCS(is_postfix_expression)(tid)) { + sample_traverser(CPP2_UFCS(as_postfix_expression)(tid), indent); + } + else {if (CPP2_UFCS(is_qualified_id)(tid)) { + sample_traverser(CPP2_UFCS(as_qualified_id)(tid), indent); + } + else {if (CPP2_UFCS(is_unqualified_id)(tid)) { + sample_traverser(CPP2_UFCS(as_unqualified_id)(tid), indent); + } + else { + sample_print(CPP2_UFCS(to_string)(tid), indent); + }}} +} + +#line 4067 "reflect.h2" +auto sample_traverser(cpp2::impl::in primary, cpp2::impl::in indent) -> void +{ + if (CPP2_UFCS(is_identifier)(primary)) { + sample_print(CPP2_UFCS(as_identifier)(primary), indent + 1); + } + else {if (CPP2_UFCS(is_expression_list)(primary)) { + sample_traverser(CPP2_UFCS(as_expression_list)(primary), indent + 1); + } + else {if (CPP2_UFCS(is_literal)(primary)) { + sample_print(CPP2_UFCS(as_literal)(primary), indent + 1); + } + else {if (CPP2_UFCS(is_declaration)(primary)) { + sample_traverser(CPP2_UFCS(as_declaration)(primary), indent + 1); + } + else { + sample_print(CPP2_UFCS(to_string)(primary), indent + 1); + }}}} +} + +#line 4087 "reflect.h2" +auto sample_traverser(cpp2::impl::in idexpr, cpp2::impl::in indent) -> void +{ + if (CPP2_UFCS(is_identifier)(idexpr)) { + sample_print(CPP2_UFCS(as_identifier)(idexpr), indent + 1); + } + else {if (CPP2_UFCS(is_qualified)(idexpr)) { + sample_traverser(CPP2_UFCS(as_qualified)(idexpr), indent + 1); + } + else {if (CPP2_UFCS(is_unqualified)(idexpr)) { + sample_traverser(CPP2_UFCS(as_unqualified)(idexpr), indent + 1); + } + else { + sample_print(CPP2_UFCS(to_string)(idexpr), indent + 1); + }}} +} + +#line 4104 "reflect.h2" +//----------------------------------------------------------------------- +// +// autodiff +// + +#line 4121 "reflect.h2" + autodiff_special_func::autodiff_special_func(cpp2::impl::in name_, cpp2::impl::in n_args_, cpp2::impl::in is_member_, cpp2::impl::in code_primal_, cpp2::impl::in code_fwd_, + cpp2::impl::in code_rws_, cpp2::impl::in code_primal_higher_order_, cpp2::impl::in code_fwd_higher_order_, + cpp2::impl::in code_rws_higher_order_) + : name{ name_ } + , n_args{ n_args_ } + , is_member{ is_member_ } + , code_primal{ code_primal_ } + , code_fwd{ code_fwd_ } + , code_rws{ code_rws_ } + , code_primal_higher_order{ code_primal_higher_order_ } + , code_fwd_higher_order{ code_fwd_higher_order_ } + , code_rws_higher_order{ code_rws_higher_order_ }{ + +#line 4135 "reflect.h2" + if (CPP2_UFCS(empty)(code_primal_higher_order)) { + code_primal_higher_order = code_primal; + } + if (CPP2_UFCS(empty)(code_fwd_higher_order)) { + code_fwd_higher_order = code_fwd; + } + if (CPP2_UFCS(empty)(code_rws_higher_order)) { + code_rws_higher_order = code_rws; + } + } + +#line 4146 "reflect.h2" + autodiff_special_func::autodiff_special_func(autodiff_special_func const& that) + : name{ that.name } + , n_args{ that.n_args } + , is_member{ that.is_member } + , code_primal{ that.code_primal } + , code_fwd{ that.code_fwd } + , code_rws{ that.code_rws } + , code_primal_higher_order{ that.code_primal_higher_order } + , code_fwd_higher_order{ that.code_fwd_higher_order } + , code_rws_higher_order{ that.code_rws_higher_order }{} +#line 4146 "reflect.h2" + auto autodiff_special_func::operator=(autodiff_special_func const& that) -> autodiff_special_func& { + name = that.name; + n_args = that.n_args; + is_member = that.is_member; + code_primal = that.code_primal; + code_fwd = that.code_fwd; + code_rws = that.code_rws; + code_primal_higher_order = that.code_primal_higher_order; + code_fwd_higher_order = that.code_fwd_higher_order; + code_rws_higher_order = that.code_rws_higher_order; + return *this; } +#line 4146 "reflect.h2" + autodiff_special_func::autodiff_special_func(autodiff_special_func&& that) noexcept + : name{ std::move(that).name } + , n_args{ std::move(that).n_args } + , is_member{ std::move(that).is_member } + , code_primal{ std::move(that).code_primal } + , code_fwd{ std::move(that).code_fwd } + , code_rws{ std::move(that).code_rws } + , code_primal_higher_order{ std::move(that).code_primal_higher_order } + , code_fwd_higher_order{ std::move(that).code_fwd_higher_order } + , code_rws_higher_order{ std::move(that).code_rws_higher_order }{} +#line 4146 "reflect.h2" + auto autodiff_special_func::operator=(autodiff_special_func&& that) noexcept -> autodiff_special_func& { + name = std::move(that).name; + n_args = std::move(that).n_args; + is_member = std::move(that).is_member; + code_primal = std::move(that).code_primal; + code_fwd = std::move(that).code_fwd; + code_rws = std::move(that).code_rws; + code_primal_higher_order = std::move(that).code_primal_higher_order; + code_fwd_higher_order = std::move(that).code_fwd_higher_order; + code_rws_higher_order = std::move(that).code_rws_higher_order; + return *this; }// Default copy. + +#line 4148 "reflect.h2" + [[nodiscard]] auto autodiff_special_func::is_match(cpp2::impl::in o) const& -> bool{ + return name == o.name && n_args == o.n_args && is_member == o.is_member; + } + +#line 4155 "reflect.h2" + // TODO: Maybe use variant here. + +#line 4159 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(){} + +#line 4161 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(cpp2::impl::in name_, cpp2::impl::in decl_, cpp2::impl::in is_active_, cpp2::impl::in is_member_) + : name{ name_ } + , decl{ decl_ } + , is_active{ is_active_ } + , is_member{ is_member_ }{ + +#line 4166 "reflect.h2" + } + +#line 4168 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(autodiff_declared_variable const& that) + : name{ that.name } + , decl{ that.decl } + , is_active{ that.is_active } + , is_member{ that.is_member }{} +#line 4168 "reflect.h2" + auto autodiff_declared_variable::operator=(autodiff_declared_variable const& that) -> autodiff_declared_variable& { + name = that.name; + decl = that.decl; + is_active = that.is_active; + is_member = that.is_member; + return *this; } +#line 4168 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(autodiff_declared_variable&& that) noexcept + : name{ std::move(that).name } + , decl{ std::move(that).decl } + , is_active{ std::move(that).is_active } + , is_member{ std::move(that).is_member }{} +#line 4168 "reflect.h2" + auto autodiff_declared_variable::operator=(autodiff_declared_variable&& that) noexcept -> autodiff_declared_variable& { + name = std::move(that).name; + decl = std::move(that).decl; + is_active = std::move(that).is_active; + is_member = std::move(that).is_member; + return *this; } + +#line 4172 "reflect.h2" + // namespace + type name + +#line 4180 "reflect.h2" + autodiff_declaration_stack_item::autodiff_declaration_stack_item(cpp2::impl::in full_name_, cpp2::impl::in decl_) + : full_name{ full_name_ } + , decl{ decl_ }{ + +#line 4183 "reflect.h2" + } + +#line 4185 "reflect.h2" + [[nodiscard]] auto autodiff_declaration_stack_item::lookup_declaration(cpp2::impl::in decl_name) const& -> lookup_declaration_ret{ + std::vector r {}; +#line 4186 "reflect.h2" + for ( auto const& cur : CPP2_UFCS(get_members)(decl) ) { + if (CPP2_UFCS(has_name)(cur) && decl_name == CPP2_UFCS(name)(cur)) { + CPP2_UFCS(push_back)(r, cur); + + // Do not break for overloads. <3 + } + }return r; + } + +#line 4195 "reflect.h2" + [[nodiscard]] auto autodiff_declaration_stack_item::lookup_variable_declaration(cpp2::impl::in decl_name) const& -> lookup_variable_declaration_ret{ + bool found {false}; + autodiff_declared_variable r {}; +{ +auto cur_context{CPP2_UFCS(rbegin)(declared_variables_stack)}; + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + +#line 4199 "reflect.h2" + for( ; cur_context != CPP2_UFCS(rend)(declared_variables_stack); + ++cur_context ) + { + for ( auto const& cur : *cpp2::impl::assert_not_null(cur_context) ) { + if (cur.name == decl_name) { + found = true; + r = cur; + return { std::move(found), std::move(r) }; + } + } + } +} +#line 4200 "reflect.h2" + return { std::move(found), std::move(r) }; + +#line 4210 "reflect.h2" + } + + autodiff_declaration_stack_item::autodiff_declaration_stack_item(autodiff_declaration_stack_item const& that) + : full_name{ that.full_name } + , decl{ that.decl } + , diff_request{ that.diff_request } + , diff_done{ that.diff_done } + , declared_variables_stack{ that.declared_variables_stack }{} +autodiff_declaration_stack_item::autodiff_declaration_stack_item(autodiff_declaration_stack_item&& that) noexcept + : full_name{ std::move(that).full_name } + , decl{ std::move(that).decl } + , diff_request{ std::move(that).diff_request } + , diff_done{ std::move(that).diff_done } + , declared_variables_stack{ std::move(that).declared_variables_stack }{} + +#line 4218 "reflect.h2" + // Code in special function is replaced. Placeholders are: + // _o_ : name of object for member functions. + // _o_ : name of derivative object for member functions. + // _a1_ : First argument value + // _ad1_: First derivative argument value + // _a2_ : Second argument value + // _ad2_: Second derivative argument value + + /* is_member = */ + +#line 4235 "reflect.h2" + /* is_member = */ + +#line 4243 "reflect.h2" + /* is_member = */ + +#line 4251 "reflect.h2" + /* is_member = */ + +#line 4259 "reflect.h2" + /* is_member = */ + +#line 4270 "reflect.h2" + // Members depending on order + +#line 4277 "reflect.h2" + autodiff_context::autodiff_context(){} +#line 4278 "reflect.h2" + autodiff_context::autodiff_context(cpp2::impl::in order_, cpp2::impl::in reverse_) + : order{ order_ } + , reverse{ reverse_ }{ + +#line 4282 "reflect.h2" + if (1 != order) { + if (reverse) { + fwd_ad_type = "cpp2::taylor"; + rws_ad_type = "cpp2::taylor"; + } + else { + fwd_ad_type = "cpp2::taylor"; + } + } + + } + +#line 4294 "reflect.h2" + auto autodiff_context::add_variable_declaration(cpp2::impl::in name, cpp2::impl::in type, cpp2::impl::in is_active, cpp2::impl::in is_member) & -> void{ + CPP2_UFCS(push_back)(CPP2_UFCS(back)(CPP2_UFCS(back)(declaration_stack).declared_variables_stack), autodiff_declared_variable(name, type, is_active, is_member)); + } + +#line 4298 "reflect.h2" + [[nodiscard]] auto autodiff_context::is_variable_active(cpp2::impl::in name) & -> bool{ + return lookup_variable_declaration(name).is_active; + } + +#line 4302 "reflect.h2" + auto autodiff_context::create_namespace_stack(cpp2::impl::in t) & -> void{ + if (CPP2_UFCS(parent_is_nonglobal_namespace)(t)) { + create_namespace_stack(CPP2_UFCS(as_nonglobal_namespace)(CPP2_UFCS(get_parent)(t))); + } + else {if (CPP2_UFCS(parent_is_type)(t)) { + create_namespace_stack(CPP2_UFCS(as_type)(CPP2_UFCS(get_parent)(t))); + }} + + std::string full_name {"::"}; + if (!(CPP2_UFCS(empty)(declaration_stack))) { + full_name = CPP2_UFCS(back)(declaration_stack).full_name + "::"; + } + full_name += CPP2_UFCS(name)(t); + + static_cast(CPP2_UFCS(push_back)(declaration_stack, autodiff_declaration_stack_item(cpp2::move(full_name), t))); + } + +#line 4319 "reflect.h2" + [[nodiscard]] auto autodiff_context::is_forward() const& -> decltype(auto) { return !(reverse) || (reverse && order != 1); } +#line 4320 "reflect.h2" + [[nodiscard]] auto autodiff_context::is_reverse() const& -> decltype(auto) { return reverse; } +#line 4321 "reflect.h2" + [[nodiscard]] auto autodiff_context::is_taylor() const& -> decltype(auto) { return order != 1; } + +#line 4323 "reflect.h2" + [[nodiscard]] auto autodiff_context::gen_temporary() & -> std::string{ + temporary_count += 1; + return "temp_" + cpp2::to_string(temporary_count) + ""; + } + +#line 4328 "reflect.h2" + [[nodiscard]] auto autodiff_context::is_type_active(cpp2::impl::in type) & -> bool{ + auto decls {lookup_type_declaration(type)}; + auto r {false}; + + if (!(CPP2_UFCS(empty)(decls))) { + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(ssize)(decls) == 1) ) { cpp2::cpp2_default.report_violation(""); } + autodiff_activity_check ada {&(*this)}; + CPP2_UFCS(pre_traverse)(ada, CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(decls), 0)); + r = cpp2::move(ada).active; + } + + // TODO: Add template activity lookup. + + if (!(r)) { + // Declaration lookup did not yield an activity: Apply some heuristics. + r = CPP2_UFCS(contains)(type, "double"); + } + + return r; + } + +#line 4349 "reflect.h2" + [[nodiscard]] auto autodiff_context::get_fwd_ad_type(cpp2::impl::in type) & -> std::string{ + auto type_d {type}; + + if ("double" != type) { + auto type_decls {lookup_type_declaration(type)}; + if (!(CPP2_UFCS(empty)(type_decls))) { + // We found a cpp2 type declaration, mark it for differentiation. + add_for_differentiation(CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(type_decls), 0)); + + // Add the AD suffix to the type + type_d += fwd_suffix; + } + } + + // Replace with AD type for the AD order. + return string_util::replace_all(cpp2::move(type_d), "double", fwd_ad_type); + } + +#line 4367 "reflect.h2" + [[nodiscard]] auto autodiff_context::get_rws_ad_type(cpp2::impl::in type) & -> std::string{ + auto type_d {type}; + + if ("double" != type) { + auto type_decls {lookup_type_declaration(type)}; + if (!(CPP2_UFCS(empty)(type_decls))) { + // We found a cpp2 type declaration, mark it for differentiation. + add_for_differentiation(CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(type_decls), 0)); + + // Add the AD suffix to the type + type_d += rws_suffix; + } + } + + // Replace with AD type for the AD order. + return string_util::replace_all(cpp2::move(type_d), "double", rws_ad_type); + } + +#line 4385 "reflect.h2" + [[nodiscard]] auto autodiff_context::get_reverse_passing_style(cpp2::impl::in p) const& -> passing_style{ + // TODO: inspect does not work here: error: error: no matching function for call to ‘is(const cpp2::passing_style&)’ + // return inspect p -> passing_style { + // is passing_style::in = passing_style::inout; + // is passing_style::in_ref = passing_style::inout; + // is passing_style::copy = passing_style::inout; + // is passing_style::inout = passing_style::inout; + // is passing_style::out = passing_style::inout; + // is passing_style::move = passing_style::inout; + // is passing_style::forward = passing_style::inout; + // is passing_style::forward_ref = passing_style::inout; + // is _ = passing_style::inout; + // }; + if (p == passing_style::in) { return passing_style::inout; } + if (p == passing_style::in_ref) { return passing_style::inout; } + if (p == passing_style::copy) { return passing_style::inout; } + if (p == passing_style::inout) { return passing_style::inout; } + if (p == passing_style::out) { return passing_style::inout; } + if (p == passing_style::move) { return passing_style::inout; } + if (p == passing_style::forward) { return passing_style::inout; } + if (p == passing_style::forward_ref) { return passing_style::inout; } + +#line 4408 "reflect.h2" + CPP2_UFCS(error)(CPP2_UFCS(back)(declaration_stack).decl, "AD: Do not know how to handle passing style:" + cpp2::to_string(p) + ""); + + return passing_style::inout; + } + +#line 4413 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_declaration(cpp2::impl::in decl_name) & -> lookup_declaration_ret{ + std::vector r {}; +{ +auto cur{CPP2_UFCS(rbegin)(declaration_stack)}; + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + +#line 4417 "reflect.h2" + for( ; cur != CPP2_UFCS(rend)(declaration_stack); + ++cur ) + { + std::string cur_full_name {(*cpp2::impl::assert_not_null(cur)).full_name + "::" + decl_name}; + auto ele {CPP2_UFCS(find)(declaration_map, cur_full_name)}; + if (ele == CPP2_UFCS(end)(declaration_map)) { + ele = CPP2_UFCS(insert_or_assign)(declaration_map, cpp2::move(cur_full_name), CPP2_UFCS(lookup_declaration)((*cpp2::impl::assert_not_null(cur)), decl_name)).first; + } + + if (!(CPP2_UFCS(empty)((*cpp2::impl::assert_not_null(ele)).second))) { + // A simple assignment or emplace_back did not work. It tired to use move copy operators. + for ( auto const& cp : (*cpp2::impl::assert_not_null(cpp2::move(ele))).second ) { + CPP2_UFCS(push_back)(r, cp); + } + //r = ele*.second; + break; + // TODO: For overload resolution we may want to continue here and just add everything for all parent namespaces. + } + } +} + +#line 4437 "reflect.h2" + return r; + } + +#line 4440 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_variable_declaration(cpp2::impl::in name) & -> autodiff_declared_variable{ + if (name == "_") { + return autodiff_declared_variable(name, "_", false, false); + } +{ +auto cur_context{CPP2_UFCS(rbegin)(declaration_stack)}; + + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + +#line 4448 "reflect.h2" + for( ; cur_context != CPP2_UFCS(rend)(declaration_stack); + ++cur_context ) + { + auto r {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(cur_context)), name)}; + if (r.found) { + return cpp2::move(r).r; + } + } +} + +#line 4457 "reflect.h2" + CPP2_UFCS(error)(CPP2_UFCS(back)(declaration_stack).decl, "AD: Could not find declaration of variable with name `" + cpp2::to_string(name) + "`."); + + return autodiff_declared_variable(); + } + +#line 4462 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_function_declaration(cpp2::impl::in decl_name) & -> lookup_function_declaration_ret{ + std::vector r {}; +#line 4463 "reflect.h2" + auto r_all {lookup_declaration(decl_name)}; + + for ( auto const& cur : cpp2::move(r_all) ) { + if (CPP2_UFCS(is_function)(cur)) { + CPP2_UFCS(push_back)(r, CPP2_UFCS(as_function)(cur)); + } + }return r; + } + +#line 4472 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_member_function_declaration(cpp2::impl::in obj_type, cpp2::impl::in decl_name) & -> lookup_member_function_declaration_ret{ + std::vector r {}; +#line 4473 "reflect.h2" + for ( auto const& cur : CPP2_UFCS(get_members)(obj_type) ) { + if (CPP2_UFCS(is_function)(cur) && CPP2_UFCS(has_name)(cur) && decl_name == CPP2_UFCS(name)(cur)) { + CPP2_UFCS(push_back)(r, CPP2_UFCS(as_function)(cur)); + + // Do not break for overloads. <3 + } + }return r; + } + +#line 4482 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_type_declaration(cpp2::impl::in decl_name) & -> lookup_type_declaration_ret{ + std::vector r {}; +#line 4483 "reflect.h2" + auto r_all {lookup_declaration(decl_name)}; + + for ( auto const& cur : cpp2::move(r_all) ) { + if (CPP2_UFCS(is_type)(cur)) { + CPP2_UFCS(push_back)(r, CPP2_UFCS(as_type)(cur)); + } + }return r; + } + +#line 4492 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_special_function_handling(cpp2::impl::in func_name, cpp2::impl::in n_args, cpp2::impl::in is_member) const& -> lookup_special_function_handling_ret{ + cpp2::impl::deferred_init m; + cpp2::impl::deferred_init code_primal; + cpp2::impl::deferred_init code_fwd; + cpp2::impl::deferred_init code_rws; +#line 4493 "reflect.h2" + autodiff_special_func lookup {func_name, n_args, is_member}; + + m.construct(false); + code_primal.construct(""); + code_fwd.construct(""); + code_rws.construct(""); + for ( auto const& func : special_funcs ) { + if (CPP2_UFCS(is_match)(func, lookup)) { + m.value() = true; + if (is_taylor()) { + code_primal.value() = func.code_primal_higher_order; + code_fwd.value() = func.code_fwd_higher_order; + code_rws.value() = func.code_rws_higher_order; + } + else { + code_primal.value() = func.code_primal; + code_fwd.value() = func.code_fwd; + code_rws.value() = func.code_rws; + } + return { std::move(m.value()), std::move(code_primal.value()), std::move(code_fwd.value()), std::move(code_rws.value()) }; + } + }return { std::move(m.value()), std::move(code_primal.value()), std::move(code_fwd.value()), std::move(code_rws.value()) }; + } + +#line 4517 "reflect.h2" + auto autodiff_context::add_as_differentiated(cpp2::impl::in t) & -> void{ + auto top {&CPP2_UFCS(back)(declaration_stack)}; + + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_same)(CPP2_UFCS(get_parent)(t), (*cpp2::impl::assert_not_null(top)).decl)) ) { cpp2::cpp2_default.report_violation(""); } + + CPP2_UFCS(push_back)((*cpp2::impl::assert_not_null(cpp2::move(top))).diff_done, t); + } + +#line 4525 "reflect.h2" + auto autodiff_context::add_for_differentiation(cpp2::impl::in t) & -> void{ + auto t_parent {CPP2_UFCS(get_parent)(t)}; + + auto found {false}; +{ +auto cur{CPP2_UFCS(rbegin)(declaration_stack)}; + + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + +#line 4533 "reflect.h2" + for( ; cur != CPP2_UFCS(rend)(declaration_stack); + ++cur ) + { + if (CPP2_UFCS(is_same)(t_parent, (*cpp2::impl::assert_not_null(cur)).decl)) { + if (!(is_in_list(t, (*cpp2::impl::assert_not_null(cur)).diff_request))) { + CPP2_UFCS(push_back)((*cpp2::impl::assert_not_null(cur)).diff_request, t); + } + + found = true; + break; + } + } +} + +#line 4546 "reflect.h2" + if (!(cpp2::move(found))) { + CPP2_UFCS(error)(t, "AD: Could not find parent type/namespace for: " + cpp2::to_string(t) + ""); + } + } + +#line 4551 "reflect.h2" + [[nodiscard]] auto autodiff_context::is_in_list(cpp2::impl::in v, cpp2::impl::in> list) -> bool{ + for ( auto const& cur : list ) { + if (CPP2_UFCS(is_same)(cur, v)) { + return true; + } + } + + return false; + } + +#line 4561 "reflect.h2" + auto autodiff_context::enter_function() & -> void{ + temporary_count = 0; + CPP2_UFCS(push_back)(CPP2_UFCS(back)(declaration_stack).declared_variables_stack, std::vector()); + } + +#line 4566 "reflect.h2" + auto autodiff_context::leave_function() & -> void{ + CPP2_UFCS(pop_back)(CPP2_UFCS(back)(declaration_stack).declared_variables_stack); + } + +#line 4570 "reflect.h2" + auto autodiff_context::push_stack(cpp2::impl::in decl) & -> void{ + std::string full_name {""}; + + if (!(CPP2_UFCS(empty)(declaration_stack))) { + full_name += CPP2_UFCS(back)(declaration_stack).full_name; + } + + full_name += "::"; + full_name += CPP2_UFCS(name)(decl); + + CPP2_UFCS(push_back)(declaration_stack, autodiff_declaration_stack_item(cpp2::move(full_name), decl)); + } + +#line 4583 "reflect.h2" + auto autodiff_context::pop_stack() & -> void{ + if (cpp2::cpp2_default.is_active() && !(!(CPP2_UFCS(empty)(declaration_stack))) ) { cpp2::cpp2_default.report_violation(""); } + + auto top {&CPP2_UFCS(back)(declaration_stack)}; + autodiff_declaration_handler ad {&(*this), (*cpp2::impl::assert_not_null(top)).decl}; + + for ( auto const& cur : (*cpp2::impl::assert_not_null(top)).diff_request ) { + if (!(is_in_list(cur, (*cpp2::impl::assert_not_null(top)).diff_done))) { + CPP2_UFCS(pre_traverse)(ad, cur); + } + } + + CPP2_UFCS(pop_back)(declaration_stack); + } + +#line 4598 "reflect.h2" + auto autodiff_context::finish() & -> void{ + while( !(CPP2_UFCS(empty)(declaration_stack)) ) { + pop_stack(); + } + } + +#line 4612 "reflect.h2" + autodiff_diff_code::autodiff_diff_code(cpp2::impl::in ctx_) + : ctx{ ctx_ }{ + +#line 4614 "reflect.h2" + } +#line 4612 "reflect.h2" + auto autodiff_diff_code::operator=(cpp2::impl::in ctx_) -> autodiff_diff_code& { + ctx = ctx_; + fwd = ""; + rws_primal = ""; + rws_backprop = ""; + return *this; + +#line 4614 "reflect.h2" + } +#line 4615 "reflect.h2" + autodiff_diff_code::autodiff_diff_code(autodiff_diff_code const& that) + : ctx{ that.ctx } + , fwd{ that.fwd } + , rws_primal{ that.rws_primal } + , rws_backprop{ that.rws_backprop }{} +#line 4615 "reflect.h2" + auto autodiff_diff_code::operator=(autodiff_diff_code const& that) -> autodiff_diff_code& { + ctx = that.ctx; + fwd = that.fwd; + rws_primal = that.rws_primal; + rws_backprop = that.rws_backprop; + return *this; } +#line 4615 "reflect.h2" + autodiff_diff_code::autodiff_diff_code(autodiff_diff_code&& that) noexcept + : ctx{ std::move(that).ctx } + , fwd{ std::move(that).fwd } + , rws_primal{ std::move(that).rws_primal } + , rws_backprop{ std::move(that).rws_backprop }{} +#line 4615 "reflect.h2" + auto autodiff_diff_code::operator=(autodiff_diff_code&& that) noexcept -> autodiff_diff_code& { + ctx = std::move(that).ctx; + fwd = std::move(that).fwd; + rws_primal = std::move(that).rws_primal; + rws_backprop = std::move(that).rws_backprop; + return *this; } + +#line 4617 "reflect.h2" + auto autodiff_diff_code::add_forward(cpp2::impl::in v) & -> void{if (CPP2_UFCS(is_forward)((*cpp2::impl::assert_not_null(ctx)))) {fwd += v;}} +#line 4618 "reflect.h2" + auto autodiff_diff_code::add_reverse_primal(cpp2::impl::in v) & -> void{if (CPP2_UFCS(is_reverse)((*cpp2::impl::assert_not_null(ctx)))) {rws_primal += v;}} +#line 4619 "reflect.h2" + auto autodiff_diff_code::add_reverse_backprop(cpp2::impl::in v) & -> void{if (CPP2_UFCS(is_reverse)((*cpp2::impl::assert_not_null(ctx)))) {rws_backprop = v + rws_backprop; }} + +#line 4621 "reflect.h2" + auto autodiff_diff_code::reset() & -> void{ + fwd = ""; + rws_primal = ""; + rws_backprop = ""; + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. +#line 4628 "reflect.h2" + auto autodiff_diff_code::operator=(cpp2::impl::in v) -> autodiff_diff_code& { + ctx = ctx; + fwd = v; + rws_primal = ""; + rws_backprop = ""; + return *this; + +#line 4631 "reflect.h2" + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. +#line 4634 "reflect.h2" + auto autodiff_diff_code::operator+=(cpp2::impl::in v) & -> void{ + fwd += v; + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. +#line 4639 "reflect.h2" + auto autodiff_diff_code::operator+=(cpp2::impl::in v) & -> void{ + fwd += v.fwd; + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. +#line 4644 "reflect.h2" + [[nodiscard]] auto autodiff_diff_code::empty() const& -> bool{ + return CPP2_UFCS(empty)(fwd); + } + +#line 4649 "reflect.h2" +// // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. +// to_string: (v: autodiff_diff_code) -> std::string = { +// return v.fwd; +// } + +#line 4660 "reflect.h2" + autodiff_activity_check::autodiff_activity_check(cpp2::impl::in ctx_) + : simple_traverser{ } + , ctx{ ctx_ }{ + +#line 4662 "reflect.h2" + } + +#line 4664 "reflect.h2" + auto autodiff_activity_check::traverse(cpp2::impl::in t) -> void{ + for ( + auto const& m : CPP2_UFCS(get_members)(t) ) + { + if (CPP2_UFCS(is_object)(m) || CPP2_UFCS(is_member_object)(m)) { + pre_traverse(m); + } + + // TODO: Maybe also add functions. + } + } + +#line 4676 "reflect.h2" + auto autodiff_activity_check::traverse(cpp2::impl::in o) -> void{ + + auto type {o.type()}; + + if ("_" == type) { + if (CPP2_UFCS(has_initializer)(o)) { + pre_traverse(CPP2_UFCS(get_initializer)(o)); + } + else { + // Assume active + active = true; + } + } + else { + active |= CPP2_UFCS(is_type_active)((*cpp2::impl::assert_not_null(ctx)), cpp2::move(type)); + } + } + +#line 4694 "reflect.h2" + auto autodiff_activity_check::traverse(cpp2::impl::in primary) -> void + { + if (CPP2_UFCS(is_identifier)(primary)) { + active |= CPP2_UFCS(is_variable_active)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(to_string)(primary)); + } + else {if (CPP2_UFCS(is_expression_list)(primary)) { + for ( auto const& cur : CPP2_UFCS(get_expressions)(CPP2_UFCS(as_expression_list)(primary)) ) { + pre_traverse(cur); + } + } + else {if (CPP2_UFCS(is_literal)(primary)) { + // TODO: Improve check + if (CPP2_UFCS(contains)(CPP2_UFCS(to_string)(primary), ".")) { + active = true; + } + } + else {if (CPP2_UFCS(is_declaration)(primary)) { + pre_traverse(CPP2_UFCS(as_declaration)(primary)); + } + else { + CPP2_UFCS(error)(primary, "AD: Unknown primary expression kind: " + cpp2::to_string(CPP2_UFCS(to_string)(primary)) + ""); + }}}} + } + +#line 4718 "reflect.h2" + auto autodiff_activity_check::traverse(cpp2::impl::in postfix) -> void + { + auto terms {CPP2_UFCS(get_terms)(postfix)}; + + auto is_func {false}; +{ +auto i{0}; + +#line 4725 "reflect.h2" + for ( auto const& term : terms ) { do { + if (CPP2_UFCS(get_op)(term) == ".") { + continue; + } + if (CPP2_UFCS(get_op)(term) == "(" && i + 1 == CPP2_UFCS(ssize)(terms)) {// Function operator has to be the last + is_func = true; + continue; + } + else { + CPP2_UFCS(error)(postfix, "AD: Unknown operator for postfix expression. op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + " expr: " + cpp2::to_string(postfix) + ""); + } + } while (false); i += 1; } +} + + // TODO: Really check for members +#line 4739 "reflect.h2" + if (!(is_func) || CPP2_UFCS(ssize)(terms) != 1) { + active |= CPP2_UFCS(is_variable_active)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(to_string)(CPP2_UFCS(get_primary_expression)(postfix))); + } + + if (cpp2::move(is_func)) { + // Check arguments of function + for ( auto const& cur : CPP2_UFCS(get_expressions)(CPP2_UFCS(get_expression_list)(CPP2_UFCS(back)(cpp2::move(terms)))) ) { + pre_traverse(cur); + } + } + } + +#line 4757 "reflect.h2" + autodiff_handler_base::autodiff_handler_base(cpp2::impl::in ctx_) + : ctx{ ctx_ } + , diff{ ctx }{ + +#line 4760 "reflect.h2" + } +#line 4757 "reflect.h2" + auto autodiff_handler_base::operator=(cpp2::impl::in ctx_) -> autodiff_handler_base& { + ctx = ctx_; + diff = ctx; + return *this; + +#line 4760 "reflect.h2" + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. +#line 4763 "reflect.h2" + auto autodiff_handler_base::append(autodiff_handler_base const& o) & -> void{ + diff.fwd += o.diff.fwd; + diff.rws_primal += o.diff.rws_primal; + diff.rws_backprop = o.diff.rws_backprop + diff.rws_backprop; + } + +#line 4780 "reflect.h2" + autodiff_expression_handler::autodiff_expression_handler(cpp2::impl::in ctx_) + : simple_traverser{ } + , autodiff_handler_base{ ctx_ }{ + +#line 4782 "reflect.h2" + } + +#line 4784 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::add_suffix_if_not_wildcard(cpp2::impl::in lhs, cpp2::impl::in suffix) const& -> std::string{ + if ("_" == lhs) { + return lhs; + } + else { + return lhs + suffix; + } + } + +#line 4793 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::prepare_backprop(cpp2::impl::in rhs_b, cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b) const& -> std::string{ + auto r {rhs_b}; + r = string_util::replace_all(r, "_r_", lhs); + r = string_util::replace_all(r, "_rd_", lhs_d); + r = string_util::replace_all(r, "_rb_", lhs_b); + + return r; + } +#line 4801 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::prepare_backprop(cpp2::impl::in rhs_b, cpp2::impl::in lhs) const& -> std::string { return prepare_backprop(rhs_b, lhs, lhs + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix, lhs + (*cpp2::impl::assert_not_null(ctx)).rws_suffix); } + +#line 4803 "reflect.h2" + auto autodiff_expression_handler::gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in rhs_b) & -> void{ + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(lhs_d) + " = " + cpp2::to_string(rhs_d) + ";\n"); + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(lhs) + " = " + cpp2::to_string(rhs) + ";\n"); + + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(lhs_d) + " = " + cpp2::to_string(rhs_d) + ";\n"); + } + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(lhs) + " = " + cpp2::to_string(rhs) + ";\n"); + CPP2_UFCS(add_reverse_backprop)(diff, "" + cpp2::to_string(lhs_b) + " = 0.0;\n"); + CPP2_UFCS(add_reverse_backprop)(diff, prepare_backprop(rhs_b, lhs, lhs_d, lhs_b)); + } +#line 4814 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b) & -> decltype(auto) { + return gen_assignment(lhs, lhs_d, lhs_b, primal_expr, fwd_expr, rws_expr); } +#line 4816 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_assignment(cpp2::impl::in lhs) & -> decltype(auto) { + return gen_assignment(lhs, add_suffix_if_not_wildcard(lhs, (*cpp2::impl::assert_not_null(ctx)).fwd_suffix), add_suffix_if_not_wildcard(lhs, (*cpp2::impl::assert_not_null(ctx)).rws_suffix), primal_expr, fwd_expr, rws_expr); } + +#line 4820 "reflect.h2" + auto autodiff_expression_handler::gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in rhs_b, cpp2::impl::in type, cpp2::impl::in type_d, cpp2::impl::in type_b) & -> void{ + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(lhs_d) + ": " + cpp2::to_string(type_d) + " = " + cpp2::to_string(rhs_d) + ";\n"); + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(lhs) + " : " + cpp2::to_string(type) + " = " + cpp2::to_string(rhs) + ";\n"); + + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(lhs_d) + ": " + cpp2::to_string(type_d) + " = " + cpp2::to_string(rhs_d) + ";\n"); + } + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(lhs_b) + " : " + cpp2::to_string(type_b) + " = 0.0;\n"); + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(lhs) + " : " + cpp2::to_string(type) + " = " + cpp2::to_string(rhs) + ";\n"); + CPP2_UFCS(add_reverse_backprop)(diff, "" + cpp2::to_string(lhs_b) + " = 0.0;\n"); + CPP2_UFCS(add_reverse_backprop)(diff, prepare_backprop(rhs_b, lhs, lhs_d, lhs_b)); + } +#line 4832 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in rhs_b, cpp2::impl::in type) & -> decltype(auto) { + return gen_declaration(lhs, lhs_d, lhs_b, rhs, rhs_d, rhs_b, type, CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), type), CPP2_UFCS(get_rws_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)); } +#line 4834 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in lhs_b, cpp2::impl::in type) & -> decltype(auto) { + return gen_declaration(lhs, lhs_d, lhs_b, primal_expr, fwd_expr, rws_expr, type); } +#line 4836 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_declaration(cpp2::impl::in lhs, cpp2::impl::in type) & -> decltype(auto) { + return gen_declaration(lhs, lhs + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix, lhs + (*cpp2::impl::assert_not_null(ctx)).rws_suffix, type); } + + autodiff_expression_handler::primal_fwd_rws_name::primal_fwd_rws_name(auto const& primal_, auto const& fwd_, auto const& rws_, auto const& active_) + : primal{ primal_ } + , fwd{ fwd_ } + , rws{ rws_ } + , active{ active_ }{} +autodiff_expression_handler::primal_fwd_rws_name::primal_fwd_rws_name(){} + +#line 4848 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::handle_expression_list(cpp2::impl::in list) & -> std::vector{ + std::vector args {}; + for ( auto const& expr : CPP2_UFCS(get_expressions)(list) ) { + CPP2_UFCS(push_back)(args, handle_expression_term(expr)); + } + + return args; + } + +#line 4857 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::handle_expression_term(auto const& term) & -> primal_fwd_rws_name{ + if (CPP2_UFCS(is_identifier)(term)) { + auto primal {CPP2_UFCS(to_string)(term)}; + auto fwd {primal + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix}; + auto rws {primal + (*cpp2::impl::assert_not_null(ctx)).rws_suffix}; + + auto decl {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), primal)}; + if (decl.is_member) { + fwd = "this" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + "." + fwd; + rws = "this" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + "." + rws; + } + + if (cpp2::move(decl).is_active) { + return { cpp2::move(primal), cpp2::move(fwd), cpp2::move(rws), true }; + } + else { + return { cpp2::move(primal), "", "", false }; + } + + } + else {if (CPP2_UFCS(is_expression_list)(term)) { + auto exprs {term.as_expression_list().get_expressions()}; + if (CPP2_UFCS(ssize)(exprs) != 1) { + CPP2_UFCS(error)(term, "Can not handle multiple expressions. (term.to_string())"); + return { "error", "", "", false }; + } + auto expr {CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(exprs), 0)}; + auto bin_expr {expr.as_assignment_expression()}; + + if (CPP2_UFCS(terms_size)(bin_expr) != 0) { + CPP2_UFCS(error)(term, "Can not handle assign expr inside of expression. " + cpp2::to_string(CPP2_UFCS(to_string)(cpp2::move(expr))) + ""); + return { "error", "", "", false }; + } + + return handle_expression_term(CPP2_UFCS(get_term)(CPP2_UFCS(front)(CPP2_UFCS(get_terms)(cpp2::move(bin_expr))))); + } + else { + // Nothing special. A regular expression. + auto expr {term}; + + autodiff_activity_check ada {ctx}; + CPP2_UFCS(pre_traverse)(ada, expr); + + if (cpp2::move(ada).active) { + + autodiff_expression_handler ad {ctx}; + ad.pre_traverse(cpp2::move(expr)); + auto t {CPP2_UFCS(gen_temporary)((*cpp2::impl::assert_not_null(ctx)))}; + CPP2_UFCS(gen_declaration)(ad, t, "double");// TODO: get type of expression + append(cpp2::move(ad)); + + primal_fwd_rws_name r {t, t + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix, t + (*cpp2::impl::assert_not_null(ctx)).rws_suffix, true}; // TODO: Check why on return (t, t + ctx*.fwd_suffix) the primal is initialized empty. Probably because of the move(t) + static_cast(cpp2::move(t)); + return r; + } + else { + return { CPP2_UFCS(to_string)(cpp2::move(expr)), "", "", false }; + } + }} + } + +#line 4918 "reflect.h2" + auto autodiff_expression_handler::handle_function_call(cpp2::impl::in postfix, cpp2::impl::in has_return) & -> void{ + auto terms {CPP2_UFCS(get_terms)(postfix)}; + + auto is_func {true}; +{ +auto i{0}; + +#line 4924 "reflect.h2" + for ( auto const& term : terms ) { do { + if (CPP2_UFCS(get_op)(term) == ".") { + continue; + } + if (CPP2_UFCS(get_op)(term) == "(" && i + 1 == CPP2_UFCS(ssize)(terms)) {// Function operator has to be the last + continue; + } + + is_func = false; + } while (false); i += 1; } +} + + // Check for function call, everything else is not handled. +#line 4936 "reflect.h2" + if (!((cpp2::move(is_func)))) { + CPP2_UFCS(error)(postfix, "AD: Postfix expressions are only handled for function calls, or member function calls. Do not know how to handle: " + cpp2::to_string(CPP2_UFCS(to_string)(postfix)) + ""); + return ; + } + + std::string object {""}; + std::string object_d {""}; + std::string object_b {""}; + std::string function_name {""}; + std::vector args {}; + + auto primary {CPP2_UFCS(get_primary_expression)(postfix)}; + + if (1 != CPP2_UFCS(ssize)(terms)) { + object = CPP2_UFCS(to_string)(primary); + object_d = CPP2_UFCS(to_string)(primary) + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix; + object_b = CPP2_UFCS(to_string)(cpp2::move(primary)) + (*cpp2::impl::assert_not_null(ctx)).rws_suffix; + } + else { + function_name = CPP2_UFCS(to_string)(cpp2::move(primary)); + } +{ +auto i{0}; + +#line 4959 "reflect.h2" + for ( auto const& term : terms ) { do { + if (CPP2_UFCS(get_op)(term) == ".") { + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_id_expression)(term)) ) { cpp2::cpp2_default.report_violation(""); } + auto name {CPP2_UFCS(to_string)(CPP2_UFCS(get_id_expression)(term))}; + + if (i + 2 == CPP2_UFCS(ssize)(terms)) {// Second last term is function name, last term is function argument list + function_name = cpp2::move(name); + } + else { + object += "." + name; + object_d += "." + cpp2::move(name) + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix; + } + } + else {if (CPP2_UFCS(get_op)(term) == "(") { + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_expression_list)(term)) ) { cpp2::cpp2_default.report_violation(""); } + + args = handle_expression_list(CPP2_UFCS(get_expression_list)(term)); + } + else { + CPP2_UFCS(error)(postfix, "AD: Do not know how to handle postfix term: " + cpp2::to_string(CPP2_UFCS(to_string)(term)) + ""); + }} + } while (false); i += 1; } +} + +#line 4982 "reflect.h2" + if (handle_special_function(object, object_d, object_b, function_name, args)) { + return ; + } + + if (CPP2_UFCS(contains)(object, ".")) { + CPP2_UFCS(error)(postfix, "AD: can not handle nested member function calls: " + cpp2::to_string(CPP2_UFCS(to_string)(postfix)) + ""); + return ; + } + + std::string call_primal {""}; + std::string call_fwd {""}; + std::string call_rws {""}; + + // All arguments have now been handled. Form the function call + std::string ret_temp {""}; + if (has_return) { + ret_temp = CPP2_UFCS(gen_temporary)((*cpp2::impl::assert_not_null(ctx))); + call_fwd += "" + cpp2::to_string(ret_temp) + " := "; + } + + // TODO: This is untested for functions with no return value. Requires handling of out and inout parameters in functions. + if (!(CPP2_UFCS(empty)(object))) {// Prepend object call + call_primal += "" + cpp2::to_string(object) + "."; + call_fwd += "" + cpp2::to_string(object) + "."; + call_rws += "" + cpp2::to_string(object) + "."; + } + call_primal += "" + cpp2::to_string(function_name) + "("; + call_fwd += "" + cpp2::to_string(function_name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + "("; + call_rws += "" + cpp2::to_string(function_name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + "("; + if (!(CPP2_UFCS(empty)(object))) {// Add this_d argument. + call_fwd += "" + cpp2::to_string(cpp2::move(object_d)) + ", "; + call_rws += "" + cpp2::to_string(cpp2::move(object_b)) + ", "; + } + for ( auto const& arg : cpp2::move(args) ) { + // TODO: Add taylor reverse handling. + call_primal += "" + cpp2::to_string(arg.primal) + ", "; + call_fwd += "" + cpp2::to_string(arg.primal) + ", "; + call_rws += "" + cpp2::to_string(arg.primal) + ", "; + if (arg.active) { + call_fwd += "" + cpp2::to_string(arg.fwd) + ", "; + call_rws += "" + cpp2::to_string(arg.rws) + ", "; + } + } + + if (has_return) { + std::vector functions {}; + if (!(CPP2_UFCS(empty)(object))) { + auto obj_decl {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), object)}; + auto obj_decl_types {CPP2_UFCS(lookup_type_declaration)((*cpp2::impl::assert_not_null(ctx)), obj_decl.decl)}; + + if (CPP2_UFCS(empty)(obj_decl_types)) { + CPP2_UFCS(error)(postfix, "AD: Could not find type declaration for `" + cpp2::to_string(cpp2::move(object)) + " with type " + cpp2::to_string(cpp2::move(obj_decl).decl) + "`.\n" + " If cpp2 object: this is an alpha limitation, please declare it befor the current declaration.\n" + " If cpp function: please add a special handling for this member function."); + return ; + } + functions = CPP2_UFCS(lookup_member_function_declaration)((*cpp2::impl::assert_not_null(ctx)), CPP2_ASSERT_IN_BOUNDS_LITERAL(obj_decl_types, 0), cpp2::move(function_name)); + + CPP2_UFCS(add_for_differentiation)((*cpp2::impl::assert_not_null(ctx)), CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(obj_decl_types), 0));// TODO: Add more fine grained differentiation. + } + else { + functions = CPP2_UFCS(lookup_function_declaration)((*cpp2::impl::assert_not_null(ctx)), function_name); + if (CPP2_UFCS(ssize)(functions) == 0) { + CPP2_UFCS(error)(postfix, "AD: Could not find function declaration for `" + cpp2::to_string(cpp2::move(function_name)) + "`.\n" + " If cpp2 function: this is an alpha limitation, please declare it befor the current declaration.\n" + " If cpp function: please add a special handling for this function."); + return ; + } + else {if (CPP2_UFCS(ssize)(functions) != 1) { + CPP2_UFCS(error)(postfix, "AD: No handling for overload resultion is currently implemented."); + return ; + }} + + CPP2_UFCS(add_for_differentiation)((*cpp2::impl::assert_not_null(ctx)), CPP2_ASSERT_IN_BOUNDS_LITERAL(functions, 0)); + } + + std::string ret_name {"r"}; // Default for regular return. + auto returns {CPP2_UFCS(get_returns)(CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(functions), 0))}; + if (!(CPP2_UFCS(empty)(returns))) { + if (CPP2_UFCS(ssize)(returns) != 1) { + CPP2_UFCS(error)(postfix, "AD: Expecting single return."); + } + + for ( auto const& cur : cpp2::move(returns) ) { + ret_name = CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(cur)); + } + } + + std::string ret_name_d {ret_name + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix}; + std::string ret_name_b {cpp2::move(ret_name) + (*cpp2::impl::assert_not_null(ctx)).rws_suffix}; + + call_rws += "_rb_, "; + + call_primal += ")"; + call_fwd += ");\n"; + call_rws += ");\n"; + + CPP2_UFCS(add_forward)(diff, cpp2::move(call_fwd)); + + primal_expr = cpp2::move(call_primal); + fwd_expr = "" + cpp2::to_string(cpp2::move(ret_temp)) + "." + cpp2::to_string(cpp2::move(ret_name_d)) + ""; + rws_expr = "_ = " + cpp2::to_string(cpp2::move(call_rws)) + ""; + } + else { + call_primal += ");\n"; + call_fwd += ");\n"; + call_rws += ");\n"; + + CPP2_UFCS(add_forward)(diff, cpp2::move(call_fwd)); + CPP2_UFCS(add_reverse_primal)(diff, cpp2::move(call_primal)); + CPP2_UFCS(add_reverse_backprop)(diff, cpp2::move(call_rws)); + } + + // TODO: Add function to list of functions/objects for differentiation for the no return case. + } + +#line 5098 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::handle_special_function(cpp2::impl::in object, cpp2::impl::in object_d, cpp2::impl::in object_b, cpp2::impl::in function_name, cpp2::impl::in> args) & -> bool{ + + auto r {CPP2_UFCS(lookup_special_function_handling)((*cpp2::impl::assert_not_null(ctx)), function_name, cpp2::unchecked_narrow(CPP2_UFCS(ssize)(args)), !(CPP2_UFCS(empty)(object)))}; + + if (!(r.m)) { + return false; // No match + } + + // Have a match, do the replacement + std::string code_primal {r.code_primal}; + std::string code_fwd {r.code_fwd}; + std::string code_rws {cpp2::move(r).code_rws}; + + if (!(CPP2_UFCS(empty)(object))) { + code_primal = string_util::replace_all(code_primal, "_o_", object); + code_primal = string_util::replace_all(code_primal, "_od_", object_d); + + code_fwd = string_util::replace_all(code_fwd, "_o_", object); + code_fwd = string_util::replace_all(code_fwd, "_od_", object_d); + + code_rws = string_util::replace_all(code_fwd, "_o_", object); + code_rws = string_util::replace_all(code_rws, "_od_", object_d); + code_rws = string_util::replace_all(code_fwd, "_ob_", object_b); + } +{ +auto i{1}; + +#line 5124 "reflect.h2" + for ( auto const& arg : args ) { + code_primal = string_util::replace_all(code_primal, "_a" + cpp2::to_string(i) + "_", arg.primal); + code_primal = string_util::replace_all(code_primal, "_ad" + cpp2::to_string(i) + "_", arg.fwd); + + code_fwd = string_util::replace_all(code_fwd, "_a" + cpp2::to_string(i) + "_", arg.primal); + code_fwd = string_util::replace_all(code_fwd, "_ad" + cpp2::to_string(i) + "_", arg.fwd); + + code_rws = string_util::replace_all(code_rws, "_a" + cpp2::to_string(i) + "_", arg.primal); + code_rws = string_util::replace_all(code_rws, "_ad" + cpp2::to_string(i) + "_", arg.fwd); + code_rws = string_util::replace_all(code_rws, "_ab" + cpp2::to_string(i) + "_", arg.rws); + } +} + +#line 5136 "reflect.h2" + primal_expr = cpp2::move(code_primal); + fwd_expr = cpp2::move(code_fwd); + rws_expr = cpp2::move(code_rws); + + return true; + } + +#line 5143 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in expr) -> void{ + base::traverse(expr); + } + +#line 5147 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Assign expressions are not yet handled."); + } + +#line 5151 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Logical or expressions are not yet handled."); + } + +#line 5155 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Logical and expressions are not yet handled."); + } + +#line 5159 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Bit or expressions are not yet handled."); + } + +#line 5163 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Bit xor expressions are not yet handled."); + } + +#line 5167 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Bit and expressions are not yet handled."); + } + +#line 5171 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Equality or expressions are not yet handled."); + } + +#line 5175 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Relational expressions are not yet handled."); + } + +#line 5179 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Compare or expressions are not yet handled."); + } + +#line 5183 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Shift or expressions are not yet handled."); + } + +#line 5187 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + + auto first {true}; + auto first_fwd {true}; + std::string op {"+"}; + std::string fwd {""}; + std::string rws {""}; + std::string primal {""}; + for ( auto const& term : cpp2::move(terms) ) { + if (!(first)) { + op = CPP2_UFCS(to_string)(CPP2_UFCS(get_op)(term)); + primal += " " + cpp2::to_string(op) + " "; + } + + auto var {handle_expression_term(CPP2_UFCS(get_term)(term))}; + if (var.active) { + if (first_fwd) { + if (op == "-") {// Special handling for first fwd termn with minus + fwd += "-" + cpp2::to_string(var.fwd) + ""; + } + else { // Special handling for first fwd term with plus + fwd += var.fwd; + } + } + else { + fwd += "" + cpp2::to_string(op) + " " + cpp2::to_string(var.fwd) + ""; + } + rws += "" + cpp2::to_string(var.rws) + " " + cpp2::to_string(op) + "= _rb_;\n"; + + first_fwd = false; + } + primal += cpp2::move(var).primal; + + first = false; + } + + primal_expr = cpp2::move(primal); + fwd_expr = cpp2::move(fwd); + rws_expr = cpp2::move(rws); + } + +#line 5229 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + + auto var_a {handle_expression_term(CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS_LITERAL(terms, 0)))}; + + int i {1}; + for( ; cpp2::impl::cmp_less(i,CPP2_UFCS(ssize)(terms)); i += 1 ) { + auto var_b {handle_expression_term(CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS(terms, i)))}; + + auto op {CPP2_UFCS(to_string)(CPP2_UFCS(get_op)(CPP2_ASSERT_IN_BOUNDS(terms, i)))}; + + std::string fwd {""}; + std::string rws {""}; + std::string primal {""}; + + if ("*" == op) { + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + // TODO: Add taylor overloads + fwd = "" + cpp2::to_string(var_a.fwd) + "..mul(" + cpp2::to_string(var_b.fwd) + ", " + cpp2::to_string(var_a.primal) + ", " + cpp2::to_string(var_b.primal) + ")"; + if (var_a.active) { + //fwd += "(var_b.primal)$ * (var_a.fwd)$"; + rws += "" + cpp2::to_string(var_a.rws) + " += " + cpp2::to_string(var_b.fwd) + "..mul(_rb_, " + cpp2::to_string(var_b.primal) + ", _r_);\n"; + } + if (var_b.active) { + //if !fwd.empty() { fwd += " + "; } + //fwd += "(var_a.primal)$ * (var_b.fwd)$"; + rws += "" + cpp2::to_string(var_b.rws) + " += " + cpp2::to_string(var_a.fwd) + "..mul(_rb_, " + cpp2::to_string(var_a.primal) + ", _r_);\n"; + } + } + else { + if (var_a.active) { + fwd += "" + cpp2::to_string(var_b.primal) + " * " + cpp2::to_string(var_a.fwd) + ""; + rws += "" + cpp2::to_string(var_a.rws) + " += " + cpp2::to_string(var_b.primal) + " * _rb_;\n"; + } + if (var_b.active) { + if (!(CPP2_UFCS(empty)(fwd))) {fwd += " + "; } + fwd += "" + cpp2::to_string(var_a.primal) + " * " + cpp2::to_string(var_b.fwd) + ""; + rws += "" + cpp2::to_string(var_b.rws) + " += " + cpp2::to_string(var_a.primal) + " * _rb_;\n"; + } + } + primal = "" + cpp2::to_string(var_a.primal) + " * " + cpp2::to_string(var_b.primal) + ""; + } + else {if ("/" == op) { + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + // TODO: Add taylor overloads + fwd = "" + cpp2::to_string(var_a.fwd) + ".div(" + cpp2::to_string(var_b.fwd) + ", " + cpp2::to_string(var_a.primal) + ", " + cpp2::to_string(var_b.primal) + ")"; + if (var_a.active) { + rws += "" + cpp2::to_string(var_a.rws) + " += _rb_.div(" + cpp2::to_string(var_b.fwd) + ", _r_, " + cpp2::to_string(var_b.primal) + ");\n"; + } + if (var_b.active) { + rws += "" + cpp2::to_string(var_b.rws) + " -= " + cpp2::to_string(var_a.fwd) + ".mul(_rb_, " + cpp2::to_string(var_a.primal) + ", _r_).div(" + cpp2::to_string(var_b.fwd) + ".mul(" + cpp2::to_string(var_b.fwd) + ", " + cpp2::to_string(var_b.primal) + ", " + cpp2::to_string(var_b.primal) + "), " + cpp2::to_string(var_a.primal) + " * _r_, " + cpp2::to_string(var_b.primal) + " * " + cpp2::to_string(var_b.primal) + ");\n"; + } + } + else { + if (var_a.active) { + fwd += "" + cpp2::to_string(var_a.fwd) + " / " + cpp2::to_string(var_b.primal) + ""; + rws = "" + cpp2::to_string(var_a.rws) + " += _rb_ / " + cpp2::to_string(var_b.primal) + ";\n"; + } + if (var_b.active) { + if (!(CPP2_UFCS(empty)(fwd))) {fwd += " + "; } + fwd += "-" + cpp2::to_string(var_a.primal) + " * " + cpp2::to_string(var_b.fwd) + " / (" + cpp2::to_string(var_b.primal) + " * " + cpp2::to_string(var_b.primal) + ")"; + rws += "" + cpp2::to_string(var_b.rws) + " -= " + cpp2::to_string(var_a.primal) + " * _rb_ / (" + cpp2::to_string(var_b.primal) + " * " + cpp2::to_string(var_b.primal) + ");\n"; + } + } + primal = "" + cpp2::to_string(var_a.primal) + " / " + cpp2::to_string(var_b.primal) + ""; + } + else { + CPP2_UFCS(error)(binexpr, "unkown multiplicative operator '" + cpp2::to_string(cpp2::move(op)) + "'"); + }} + +#line 5300 "reflect.h2" + if (i + 1 == CPP2_UFCS(ssize)(terms)) { + primal_expr = cpp2::move(primal); + fwd_expr = cpp2::move(fwd); + rws_expr = cpp2::move(rws); + } + else { + // Temporary + var_a.primal = CPP2_UFCS(gen_temporary)((*cpp2::impl::assert_not_null(ctx))); + var_a.fwd = var_a.primal + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix; + var_a.rws = var_a.primal + (*cpp2::impl::assert_not_null(ctx)).rws_suffix; + var_a.active = var_a.active | cpp2::move(var_b).active; + gen_declaration(var_a.primal, var_a.fwd, var_a.rws, primal, cpp2::move(fwd), cpp2::move(rws), "", "", ""); + } + } + } + +#line 5316 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in isas) -> void{ + CPP2_UFCS(error)(isas, "AD: Is as expressions are not yet handled."); + } + +#line 5320 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in prefix) -> void + { + auto ops {CPP2_UFCS(get_ops)(prefix)}; + + if (CPP2_UFCS(ssize)(ops) != 1) { + CPP2_UFCS(error)(prefix, "AD: Can only handle one prefix operation. Expression is: " + cpp2::to_string(CPP2_UFCS(to_string)(prefix)) + ""); + } + + autodiff_expression_handler ad {ctx}; + CPP2_UFCS(pre_traverse)(ad, CPP2_UFCS(get_postfix_expression)(prefix)); + append(ad); + + primal_expr = CPP2_ASSERT_IN_BOUNDS_LITERAL(ops, 0) + ad.primal_expr; + fwd_expr = CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(ops), 0) + cpp2::move(ad).fwd_expr; + } + +#line 5336 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in postfix) -> void + { + auto terms {CPP2_UFCS(get_terms)(postfix)}; + + auto is_func {false}; +{ +auto i{0}; + +#line 5343 "reflect.h2" + for ( auto const& term : terms ) { do { + if (CPP2_UFCS(get_op)(term) == ".") { + continue; + } + if (CPP2_UFCS(get_op)(term) == "(" && i + 1 == CPP2_UFCS(ssize)(terms)) {// Function operator has to be the last + is_func = true; + continue; + } + else { + CPP2_UFCS(error)(postfix, "AD: Unknown operator for postfix expression. op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + " expr: " + cpp2::to_string(postfix) + ""); + } + } while (false); i += 1; } +} + +#line 5356 "reflect.h2" + if (cpp2::move(is_func)) { + handle_function_call(postfix, true); + } + else { + // Member access + + auto primary {CPP2_UFCS(get_primary_expression)(postfix)}; + std::string obj_access {CPP2_UFCS(to_string)(cpp2::move(primary))}; + std::string obj_access_d {obj_access + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix}; + + for ( auto const& term : cpp2::move(terms) ) { + obj_access += CPP2_UFCS(get_op)(term) + CPP2_UFCS(to_string)(CPP2_UFCS(get_id_expression)(term)); + obj_access_d += CPP2_UFCS(get_op)(term) + CPP2_UFCS(to_string)(CPP2_UFCS(get_id_expression)(term)) + (*cpp2::impl::assert_not_null(ctx)).fwd_suffix; + } + + primal_expr = cpp2::move(obj_access); + fwd_expr = cpp2::move(obj_access_d); + } + } + +#line 5376 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in primary) -> void + { + if (CPP2_UFCS(is_identifier)(primary)) { + primal_expr = CPP2_UFCS(to_string)(primary); + fwd_expr = add_suffix_if_not_wildcard(primal_expr, (*cpp2::impl::assert_not_null(ctx)).fwd_suffix); + rws_expr = add_suffix_if_not_wildcard(primal_expr, (*cpp2::impl::assert_not_null(ctx)).rws_suffix); + + auto decl {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), primal_expr)}; + if (cpp2::move(decl).is_member) { + fwd_expr = "this" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + "." + fwd_expr; + rws_expr = "this" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + "." + rws_expr; + } + } + else {if (CPP2_UFCS(is_expression_list)(primary)) { + if (CPP2_UFCS(is_empty)(CPP2_UFCS(as_expression_list)(primary))) { + primal_expr = "()"; + fwd_expr = "()"; + rws_expr = "()"; // TODO: Check for reverse + } + else { + CPP2_UFCS(error)(primary, "AD: Do not know how to handle non empty expression list inside of primary_expression: " + cpp2::to_string(CPP2_UFCS(to_string)(primary)) + ""); + } + } + else {if (CPP2_UFCS(is_literal)(primary)) { + primal_expr = CPP2_UFCS(to_string)(primary); + fwd_expr = "()"; + rws_expr = "()"; // TODO: Check for reverse + } + else {if (CPP2_UFCS(is_declaration)(primary)) { + CPP2_UFCS(error)(primary, "AD: Do not know how to handle declaration inside of primary_expression: " + cpp2::to_string(CPP2_UFCS(to_string)(primary)) + ""); + } + else { + CPP2_UFCS(error)(primary, "AD: Unknown primary expression kind: " + cpp2::to_string(CPP2_UFCS(to_string)(primary)) + ""); + }}}} + } + +#line 5426 "reflect.h2" + autodiff_stmt_handler::autodiff_stmt_handler(cpp2::impl::in ctx_, cpp2::impl::in mf_) + : simple_traverser{ } + , autodiff_handler_base{ ctx_ } + , mf{ mf_ }{ + +#line 5429 "reflect.h2" + } + +#line 5431 "reflect.h2" + [[nodiscard]] auto autodiff_stmt_handler::handle_stmt_parameters(cpp2::impl::in> params) & -> autodiff_diff_code{ + autodiff_diff_code r {ctx}; + if (CPP2_UFCS(empty)(params)) { + return r; + } + + for ( auto const& param : params ) { + std::string name {CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param))}; + std::string type {CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))}; + + auto fwd_pass_style {to_string_view(CPP2_UFCS(get_passing_style)(param))}; + + autodiff_activity_check ada {ctx}; + CPP2_UFCS(pre_traverse)(ada, param); + + std::string init {""}; + std::string init_d {""}; + // TODO: Add handling for reverse expressions + + if (CPP2_UFCS(has_initializer)(CPP2_UFCS(get_declaration)(param))) { + autodiff_expression_handler ad {ctx}; + CPP2_UFCS(pre_traverse)(ad, CPP2_UFCS(get_initializer)(CPP2_UFCS(get_declaration)(param))); + init = " = " + cpp2::to_string(ad.primal_expr) + ""; + + if (ada.active) { + init_d = " = " + cpp2::to_string(cpp2::move(ad).fwd_expr) + ""; + } + } + +#line 5461 "reflect.h2" + CPP2_UFCS(add_forward)(r, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(type) + cpp2::to_string(init) + ", "); + CPP2_UFCS(add_reverse_primal)(r, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(type) + cpp2::to_string(cpp2::move(init)) + ", "); + if (ada.active) { + CPP2_UFCS(add_forward)(r, "" + cpp2::to_string(cpp2::move(fwd_pass_style)) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + cpp2::to_string(cpp2::move(init_d)) + ", "); + } + + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), cpp2::move(name), cpp2::move(type), cpp2::move(ada).active); + } + + return r; + } + +#line 5473 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in decl) -> void{ + base::traverse(decl); + } + +#line 5478 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in f) -> void{ + CPP2_UFCS(error)(f, "AD: Do not know how to handle function_declaration: " + cpp2::to_string(CPP2_UFCS(to_string)(f)) + ""); + } + +#line 5483 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in o) -> void{ + std::string lhs {CPP2_UFCS(name)(o)}; + auto type {o.type()}; + + auto active {false}; + if ("_" != type) { + active = CPP2_UFCS(is_type_active)((*cpp2::impl::assert_not_null(ctx)), type); + } + else { + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(has_initializer)(o)) ) { cpp2::cpp2_default.report_violation(""); } + + autodiff_activity_check ada {ctx}; + CPP2_UFCS(pre_traverse)(ada, CPP2_UFCS(get_initializer)(o)); + active = cpp2::move(ada).active; + } + + if (active) { + + auto fwd_ad_type {CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)}; + auto rws_ad_type {CPP2_UFCS(get_rws_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)}; + + std::string prim_init {""}; + std::string fwd_init {""}; + std::string rws_init {""}; + + if (CPP2_UFCS(has_initializer)(o)) { + autodiff_expression_handler ad {ctx}; + CPP2_UFCS(pre_traverse)(ad, CPP2_UFCS(get_initializer)(o)); + append(ad); + + prim_init = " = " + ad.primal_expr; + fwd_init = " = " + ad.fwd_expr; + rws_init = " = ()"; // TODO: Proper initialization. + + if (ad.rws_expr != "()") { + CPP2_UFCS(add_reverse_backprop)(diff, CPP2_UFCS(prepare_backprop)(ad, ad.rws_expr, lhs)); + } + + if (type == "_" && cpp2::move(ad).fwd_expr == "()") { + // Special handling for auto initialization from a literal. + fwd_init = " = " + CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), "double") + "()"; + } + } + + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(lhs) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + " : " + cpp2::to_string(cpp2::move(fwd_ad_type)) + cpp2::to_string(cpp2::move(fwd_init)) + ";\n"); + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(lhs) + " : " + cpp2::to_string(type) + cpp2::to_string(prim_init) + ";\n"); + + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(lhs) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + " : " + cpp2::to_string(cpp2::move(rws_ad_type)) + cpp2::to_string(cpp2::move(rws_init)) + ";\n"); + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(lhs) + " : " + cpp2::to_string(type) + cpp2::to_string(cpp2::move(prim_init)) + ";\n"); + } + else { + diff += "" + cpp2::to_string(lhs) + ": " + cpp2::to_string(type) + ""; + if (CPP2_UFCS(has_initializer)(o)) { + diff += " = " + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_initializer)(o))) + ""; + } + diff += ";\n"; + } + + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), cpp2::move(lhs), cpp2::move(type), cpp2::move(active)); + } + +#line 5545 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in t) -> void{ + CPP2_UFCS(error)(t, "AD: Do not know how to handle type_declaration: " + cpp2::to_string(CPP2_UFCS(to_string)(t)) + ""); + } + +#line 5550 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in t) -> void{ + CPP2_UFCS(error)(t, "AD: Do not know how to handle parameter_declaration: " + cpp2::to_string(CPP2_UFCS(to_string)(t)) + ""); + } + +#line 5555 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + // TODO: Remove this hack when statements like compound_statement can access their root statement. + last_params = CPP2_UFCS(get_parameters)(stmt); + base::traverse(stmt); + } + +#line 5562 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + autodiff_stmt_handler ad {ctx, mf}; + autodiff_stmt_handler ad_push_pop {ctx, mf}; + ad_push_pop.overwrite_push_pop = true; + + CPP2_UFCS(add_forward)(diff, "{\n"); + CPP2_UFCS(add_reverse_primal)(diff, "{\n"); + CPP2_UFCS(add_reverse_backprop)(diff, "}\n"); + + for ( auto const& cur : CPP2_UFCS(get_statements)(stmt) ) { + CPP2_UFCS(pre_traverse)(ad, cur); + CPP2_UFCS(pre_traverse)(ad_push_pop, cur); + } + + for ( auto const& cur : ad.overwritten ) { + auto r {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), cur)}; + CPP2_UFCS(add_reverse_primal)(diff, "cpp2::ad_stack::push<" + cpp2::to_string(cpp2::move(r).decl) + ">(" + cpp2::to_string(cur) + ");"); + } + + CPP2_UFCS(add_forward)(diff, ad.diff.fwd); + CPP2_UFCS(add_reverse_primal)(diff, ad.diff.rws_primal); + CPP2_UFCS(add_reverse_backprop)(diff, ad_push_pop.diff.rws_backprop); + CPP2_UFCS(add_reverse_backprop)(diff, cpp2::move(ad_push_pop).diff.rws_primal); + + for ( auto const& cur : cpp2::move(ad).overwritten ) { + auto r {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), cur)}; + CPP2_UFCS(add_reverse_backprop)(diff, "" + cpp2::to_string(cur) + " = cpp2::ad_stack::pop<" + cpp2::to_string(cpp2::move(r).decl) + ">();"); + } + + CPP2_UFCS(add_forward)(diff, "}\n"); + CPP2_UFCS(add_reverse_primal)(diff, "}\n"); + CPP2_UFCS(add_reverse_backprop)(diff, "{\n"); + } + +#line 5597 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + if (CPP2_UFCS(has_expression)(stmt)) { + // Return with expression. + // TODO: Remove assumptions + // - Return expression is always active. (Look this up in mf or so.) + // - Return was converted to a two parameter return with the name r. + autodiff_expression_handler ad {ctx}; + ad.pre_traverse(CPP2_UFCS(get_expression)(stmt)); + CPP2_UFCS(gen_assignment)(ad, "r"); + append(cpp2::move(ad)); + } + else { + diff += "return;\n"; + } + } + +#line 5613 "reflect.h2" + [[nodiscard]] auto autodiff_stmt_handler::reverse_next(cpp2::impl::in expr) const& -> std::string{ + if (CPP2_UFCS(contains)(expr, "+=")) { + return string_util::replace_all(expr, "+=", "-="); + } + else {if (CPP2_UFCS(contains)(expr, "-=")) { + return string_util::replace_all(expr, "-=", "+="); + }} + + CPP2_UFCS(error)(mf, "AD: Do not know how to reverse: " + cpp2::to_string(expr) + ""); + + return "Error"; + + } + +#line 5628 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + auto diff_params {handle_stmt_parameters(last_params)}; + + if (CPP2_UFCS(is_reverse)((*cpp2::impl::assert_not_null(ctx))) && (CPP2_UFCS(is_while)(stmt) || CPP2_UFCS(is_do)(stmt))) { + CPP2_UFCS(error)(stmt, "AD: Alpha limitiation now reverse mode for while or do while."); + } + + if (CPP2_UFCS(is_while)(stmt)) { + if (!(CPP2_UFCS(empty)(last_params))) { + CPP2_UFCS(add_forward)(diff, "(" + cpp2::move(diff_params).fwd + ")"); + } + // TODO: Assumption is here that nothing is in the condition + diff += "while " + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_do_while_condition)(stmt))) + " "; + if (CPP2_UFCS(has_next)(stmt)) { + // TODO: Assumption is here that nothing is in the next expression + diff += "next " + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_next_expression)(stmt))) + " "; + } + + pre_traverse(CPP2_UFCS(get_do_while_body)(stmt)); + } + else {if (CPP2_UFCS(is_do)(stmt)) { + if (!(CPP2_UFCS(empty)(last_params))) { + CPP2_UFCS(add_forward)(diff, "(" + cpp2::move(diff_params).fwd + ")"); + } + + // TODO: Assumption is here that nothing is in the condition + diff += "do "; + pre_traverse(CPP2_UFCS(get_do_while_body)(stmt)); + + if (CPP2_UFCS(has_next)(stmt)) { + // TODO: Assumption is here that nothing is in the next expression + diff += "next " + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_next_expression)(stmt))) + " "; + } + diff += "while " + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_do_while_condition)(stmt))) + ";"; + } + else { + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_for)(stmt)) ) { cpp2::cpp2_default.report_violation(""); } + // No zip view available in cpp 20 do a piggy back for range + + // TODO: Assumption that this is just an id expression. + auto range {CPP2_UFCS(to_string)(CPP2_UFCS(get_for_range)(stmt))}; + + auto param {CPP2_UFCS(get_for_parameter)(stmt)}; + auto param_style {to_string_view(CPP2_UFCS(get_passing_style)(param))}; + auto param_decl {CPP2_UFCS(get_declaration)(cpp2::move(param))}; + + std::string rws {"("}; + std::string rws_restore {""}; + CPP2_UFCS(add_forward)(diff, "(");// Open statment parameter scope. If the loop has parameters, they are alrady handled and the brace is left open. + CPP2_UFCS(add_reverse_primal)(diff, "{\n"); + if (!(CPP2_UFCS(empty)(last_params))) { + for ( auto const& cur : last_params ) { + if (CPP2_UFCS(has_initializer)(CPP2_UFCS(get_declaration)(cur))) { + // TODO: Handle no type and no initializer. Handle passing style. + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(cur))) + ": " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(cur))) + " = " + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_initializer)(CPP2_UFCS(get_declaration)(cur)))) + ";\n"); + rws_restore += "cpp2::ad_stack::push<" + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(cur))) + ">(" + cpp2::to_string(CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(cur))) + ");\n"; + rws += "" + cpp2::to_string(to_string_view(CPP2_UFCS(get_passing_style)(cur))) + " " + cpp2::to_string(CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(cur))) + ": " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(cur))) + " = cpp2::ad_stack::pop<" + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(cur))) + ">(), "; + } + } + CPP2_UFCS(add_forward)(diff, cpp2::move(diff_params).fwd); + } + CPP2_UFCS(add_forward)(diff, "copy " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + "_iter := " + cpp2::to_string(range) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ".begin())\n"); + CPP2_UFCS(add_forward)(diff, "for " + cpp2::to_string(range) + " next ("); + + rws += "copy " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + "_iter := " + cpp2::to_string(range) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + ".rbegin())\n"; + rws += "for std::ranges::reverse_view(" + cpp2::to_string(range) + ") next ("; + CPP2_UFCS(add_reverse_primal)(diff, "for " + cpp2::to_string(cpp2::move(range)) + " next ("); + if (CPP2_UFCS(has_next)(stmt)) { + // TODO: Assumption is here that nothing is in the next expression + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_next_expression)(stmt))) + ", "); + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_next_expression)(stmt))) + ", "); + rws += "" + cpp2::to_string(reverse_next(CPP2_UFCS(to_string)(CPP2_UFCS(get_next_expression)(stmt)))) + ", "; + } + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + "_iter++"); + CPP2_UFCS(add_forward)(diff, ") do (" + cpp2::to_string(param_style) + " " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + ": " + cpp2::to_string(CPP2_UFCS(type)(param_decl)) + ") {\n"); + rws += "" + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + "_iter++"; + rws += ") do (" + cpp2::to_string(param_style) + " " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + ": " + cpp2::to_string(CPP2_UFCS(type)(param_decl)) + ") {\n"; + rws += "(inout " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + " := " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + "_iter*)\n"; + + CPP2_UFCS(add_reverse_primal)(diff, ") do (" + cpp2::to_string(param_style) + " " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + ": " + cpp2::to_string(CPP2_UFCS(type)(param_decl)) + ")"); + CPP2_UFCS(add_forward)(diff, "(" + cpp2::to_string(cpp2::move(param_style)) + " " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ": " + cpp2::to_string(CPP2_UFCS(type)(param_decl)) + " = " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + "_iter*)"); + + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), "" + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + "", "" + cpp2::to_string(CPP2_UFCS(type)(param_decl)) + "", true);// TODO: Handle loop/compound context variable declarations. + CPP2_UFCS(add_reverse_backprop)(diff, "}\n"); + + pre_traverse(CPP2_UFCS(get_for_body)(stmt)); + CPP2_UFCS(add_forward)(diff, "}\n"); + + if (CPP2_UFCS(has_next)(stmt)) { + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(reverse_next(CPP2_UFCS(to_string)(CPP2_UFCS(get_next_expression)(stmt)))) + ";\n"); + } + CPP2_UFCS(add_reverse_primal)(diff, cpp2::move(rws_restore)); + CPP2_UFCS(add_reverse_primal)(diff, "}\n"); + CPP2_UFCS(add_reverse_backprop)(diff, cpp2::move(rws)); + }} + } + +#line 5726 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + // TODO: Currently assuming that nothing bad happens in the condition + diff += "if " + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_expression)(stmt))) + ""; + pre_traverse(CPP2_UFCS(get_true_branch)(stmt)); + + if (CPP2_UFCS(has_false_branch)(stmt)) { + diff += "else "; + pre_traverse(CPP2_UFCS(get_false_branch)(stmt)); + } + } + +#line 5737 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in expr) -> void{ + base::traverse(expr); + } + +#line 5741 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + autodiff_activity_check ada {ctx}; + CPP2_UFCS(pre_traverse)(ada, CPP2_UFCS(get_lhs_postfix_expression)(binexpr)); + if ("_" == CPP2_UFCS(to_string)(CPP2_UFCS(get_lhs_postfix_expression)(binexpr))) { + CPP2_UFCS(pre_traverse)(ada, CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS_LITERAL(CPP2_UFCS(get_terms)(binexpr), 1))); + } + + if (cpp2::move(ada).active) { + autodiff_expression_handler h_lhs {ctx}; + CPP2_UFCS(pre_traverse)(h_lhs, CPP2_UFCS(get_lhs_postfix_expression)(binexpr)); + + // Cpp2 doesn't allow chained assignment, so rhs must be a single logical_or_expression + auto assignment_terms {CPP2_UFCS(get_terms)(binexpr)}; + + autodiff_expression_handler h {ctx}; + CPP2_UFCS(pre_traverse)(h, CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(assignment_terms), 1))); + + auto is_overwrite {CPP2_UFCS(contains)(h.primal_expr, h_lhs.primal_expr)}; + if (overwrite_push_pop && is_overwrite) { + auto r {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), h_lhs.primal_expr)}; + CPP2_UFCS(add_reverse_primal)(diff, "cpp2::ad_stack::push<" + cpp2::to_string(cpp2::move(r).decl) + ">(" + cpp2::to_string(h_lhs.primal_expr) + ");"); + } + + if (is_overwrite && CPP2_UFCS(is_reverse)((*cpp2::impl::assert_not_null(ctx)))) { + auto t_b {CPP2_UFCS(gen_temporary)((*cpp2::impl::assert_not_null(ctx))) + (*cpp2::impl::assert_not_null(ctx)).rws_suffix}; + CPP2_UFCS(gen_assignment)(h, h_lhs.primal_expr, h_lhs.fwd_expr, t_b); + append(cpp2::move(h)); + CPP2_UFCS(add_reverse_backprop)(diff, "" + cpp2::to_string(h_lhs.rws_expr) + " = 0.0;\n"); + CPP2_UFCS(add_reverse_backprop)(diff, "" + cpp2::to_string(cpp2::move(t_b)) + " := " + cpp2::to_string(h_lhs.rws_expr) + ";\n"); + } + else { + CPP2_UFCS(gen_assignment)(h, h_lhs.primal_expr, h_lhs.fwd_expr, h_lhs.rws_expr); + append(cpp2::move(h)); + } + + if (overwrite_push_pop && is_overwrite) { + auto r {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), h_lhs.primal_expr)}; + CPP2_UFCS(add_reverse_backprop)(diff, "" + cpp2::to_string(h_lhs.primal_expr) + " = cpp2::ad_stack::pop<" + cpp2::to_string(cpp2::move(r).decl) + ">();"); + } -#line 3326 "reflect.h2" - for ( - auto const& term : CPP2_UFCS(get_terms)(qid) ) - { - if (!(first)) { - sample_print("op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + "", indent + 1); + // Simple overwrite check + if (cpp2::move(is_overwrite)) { + CPP2_UFCS(push_back)(overwritten, cpp2::move(h_lhs).primal_expr); + } + } + else { + CPP2_UFCS(add_forward)(diff, CPP2_UFCS(to_string)(binexpr) + ";\n"); + CPP2_UFCS(add_reverse_primal)(diff, CPP2_UFCS(to_string)(binexpr) + ";\n"); } - first = false; - sample_print("unqualified:", indent + 1); - sample_traverser(CPP2_UFCS(get_unqualified)(term), indent + 2); } -} -#line 3336 "reflect.h2" -} -#line 3339 "reflect.h2" -auto sample_traverser(cpp2::impl::in tid, cpp2::impl::in indent) -> void -{ - if (CPP2_UFCS(is_postfix_expression)(tid)) { - sample_traverser(CPP2_UFCS(as_postfix_expression)(tid), indent); +#line 5792 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Logical or expressions are not yet handled as standalone statements."); } - else {if (CPP2_UFCS(is_qualified_id)(tid)) { - sample_traverser(CPP2_UFCS(as_qualified_id)(tid), indent); + +#line 5796 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Logical and expressions are not yet handled as standalone statements."); } - else {if (CPP2_UFCS(is_unqualified_id)(tid)) { - sample_traverser(CPP2_UFCS(as_unqualified_id)(tid), indent); + +#line 5800 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Bit or expressions are not yet handled as standalone statements."); } - else { - sample_print(CPP2_UFCS(to_string)(tid), indent); - }}} -} -#line 3356 "reflect.h2" -auto sample_traverser(cpp2::impl::in primary, cpp2::impl::in indent) -> void -{ - if (CPP2_UFCS(is_identifier)(primary)) { - sample_print(CPP2_UFCS(as_identifier)(primary), indent + 1); +#line 5804 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Bit xor expressions are not yet handled as standalone statements."); } - else {if (CPP2_UFCS(is_expression_list)(primary)) { - sample_traverser(CPP2_UFCS(as_expression_list)(primary), indent + 1); + +#line 5808 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Bit and expressions are not yet handled as standalone statements."); } - else {if (CPP2_UFCS(is_literal)(primary)) { - sample_print(CPP2_UFCS(as_literal)(primary), indent + 1); + +#line 5812 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Equality or expressions are not yet handled as standalone statements."); } - else {if (CPP2_UFCS(is_declaration)(primary)) { - sample_traverser(CPP2_UFCS(as_declaration)(primary), indent + 1); + +#line 5816 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Relational expressions are not yet handled as standalone statements."); } - else { - sample_print(CPP2_UFCS(to_string)(primary), indent + 1); - }}}} -} -#line 3376 "reflect.h2" -auto sample_traverser(cpp2::impl::in idexpr, cpp2::impl::in indent) -> void -{ - if (CPP2_UFCS(is_identifier)(idexpr)) { - sample_print(CPP2_UFCS(as_identifier)(idexpr), indent + 1); +#line 5820 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Compare or expressions are not yet handled as standalone statements."); } - else {if (CPP2_UFCS(is_qualified)(idexpr)) { - sample_traverser(CPP2_UFCS(as_qualified)(idexpr), indent + 1); + +#line 5824 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Shift or expressions are not yet handled as standalone statements."); } - else {if (CPP2_UFCS(is_unqualified)(idexpr)) { - sample_traverser(CPP2_UFCS(as_unqualified)(idexpr), indent + 1); + +#line 5828 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Additive expressions are not yet handled as standalone statements."); } - else { - sample_print(CPP2_UFCS(to_string)(idexpr), indent + 1); - }}} -} -#line 3393 "reflect.h2" -//----------------------------------------------------------------------- -// -// autodiff - stub -// +#line 5832 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Multiplicative expressions are not yet handled as standalone statements."); + } -#line 3404 "reflect.h2" - [[nodiscard]] auto autodiff_impl::gen_temporary() & -> std::string{ - temporary_count += 1; - return "temp_" + cpp2::to_string(temporary_count) + ""; +#line 5836 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in isas) -> void{ + CPP2_UFCS(error)(isas, "AD: Is as expressions are not yet handled as standalone statements."); } -#line 3409 "reflect.h2" - [[nodiscard]] auto autodiff_impl::handle_expression_term([[maybe_unused]] auto& unnamed_param_2, auto const& term) & -> std::string{/*mf*/ - if (CPP2_UFCS(is_identifier)(term)) { - return CPP2_UFCS(to_string)(term); - } - else { - auto t {gen_temporary()}; - std::cout << "Handle generation for: " + cpp2::to_string(CPP2_UFCS(to_string)(term)) + "" << std::endl; - //handle_expression_terms(mf, t, term..get_expression_list()); - return t; - } +#line 5840 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in prefix) -> void + { + CPP2_UFCS(error)(prefix, "AD: Prefix expressions are not yet handled as standalone statements."); } -#line 3421 "reflect.h2" - auto autodiff_impl::handle_expression_terms(auto& mf, cpp2::impl::in lhs, auto const& terms) & -> void{ - // Handle binary || - auto logical_or_terms {terms}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(logical_or_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found as a grammatical - // identifier (this won't compile as Cpp1, but it will - // be visible via @print for development/debugging) - diff += "found_logical_or_with_____"; - auto count {0}; - for ( auto const& term : logical_or_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; - } - diff += ";"; +#line 5845 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in postfix) -> void + { + auto terms {CPP2_UFCS(get_terms)(postfix)}; - return ; - } + auto is_func {false}; +{ +auto i{0}; - // Handle binary && - if (CPP2_UFCS(ssize)(logical_or_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one logical or term here"); - } - auto logical_and_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(logical_or_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(logical_and_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_logical_and_with_____"; - auto count {0}; - for ( auto const& term : logical_and_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; +#line 5852 "reflect.h2" + for ( auto const& term : terms ) { do { + if (CPP2_UFCS(get_op)(term) == ".") { + continue; } - diff += ";"; + if (CPP2_UFCS(get_op)(term) == "(" && i + 1 == CPP2_UFCS(ssize)(terms)) {// Function operator has to be the last + is_func = true; + continue; + }else { + CPP2_UFCS(error)(postfix, "AD: Unknown operator for standalone postfix expression. op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + " expr: " + cpp2::to_string(postfix) + ""); + } + } while (false); i += 1; } +} + // Check for function call, everything else is not handled. +#line 5865 "reflect.h2" + if (!((cpp2::move(is_func)))) { + CPP2_UFCS(error)(postfix, "AD: Postfix expressions are only handled for function calls, or member function calls. Do not know how to handle: " + cpp2::to_string(CPP2_UFCS(to_string)(postfix)) + ""); return ; } - // Handle binary | - if (CPP2_UFCS(ssize)(logical_and_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one logical and term here"); - } - auto bit_or_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(logical_and_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(bit_or_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_bit_or_with_____"; - auto count {0}; - for ( auto const& term : bit_or_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; - } - diff += ";"; + autodiff_expression_handler ad {ctx}; + CPP2_UFCS(handle_function_call)(ad, postfix, false); + ad.diff += ad.fwd_expr + "\n"; + ad.diff += ad.primal_expr + "\n"; + append(cpp2::move(ad)); + } - return ; - } +#line 5877 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in primary) -> void + { + CPP2_UFCS(error)(primary, "AD: Primary expressions are not yet handled as standalone statements."); + } - // Handle binary ^ - if (CPP2_UFCS(ssize)(bit_or_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one bit or term here"); - } - auto bit_xor_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(bit_or_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(bit_xor_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_bit_xor_with_____"; - auto count {0}; - for ( auto const& term : bit_xor_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; - } - diff += ";"; +#line 5894 "reflect.h2" + autodiff_declaration_handler::autodiff_declaration_handler(cpp2::impl::in ctx_, cpp2::impl::in decl_) + : simple_traverser{ } + , autodiff_handler_base{ ctx_ } + , decl{ decl_ }{ - return ; - } +#line 5897 "reflect.h2" + } - // Handle binary & - if (CPP2_UFCS(ssize)(bit_xor_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one bit xor term here"); - } - auto bit_and_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(bit_xor_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(bit_and_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_bit_and_with_____"; - auto count {0}; - for ( auto const& term : bit_and_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; - } - diff += ";"; +#line 5899 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in decl_) -> void{ + base::traverse(decl_); + } - return ; - } +#line 5904 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in f) -> void{ + CPP2_UFCS(enter_function)((*cpp2::impl::assert_not_null(ctx))); - // Handle binary == and != - if (CPP2_UFCS(ssize)(bit_and_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one bit and term here"); - } - auto equality_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(bit_and_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(equality_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_equality_with_____"; - auto count {0}; - for ( auto const& term : equality_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; - } - diff += ";"; + // TODO: Add activity for member functions - return ; - } + CPP2_UFCS(add_forward)(diff, " " + cpp2::to_string(CPP2_UFCS(name)(f)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ": ("); + CPP2_UFCS(add_reverse_primal)(diff, " " + cpp2::to_string(CPP2_UFCS(name)(f)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + ": ("); - // Handle binary < > <= >= - if (CPP2_UFCS(ssize)(equality_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one equality term here"); - } - auto relational_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(equality_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(relational_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_relational_with_____"; - auto count {0}; - for ( auto const& term : relational_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; + // 1. Generate the modified signature + // a) Parameters + + for ( auto const& param : CPP2_UFCS(get_parameters)(f) ) { + std::string name {CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param))}; + + auto fwd_pass_style {to_string_view(CPP2_UFCS(get_passing_style)(param))}; + auto rws_pass_style {to_string_view(CPP2_UFCS(get_reverse_passing_style)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(get_passing_style)(param)))}; + + if ("this" == name) { + auto fwd_ad_type {CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), std::string(CPP2_UFCS(name)(decl)))}; + auto rws_ad_type {CPP2_UFCS(get_rws_ad_type)((*cpp2::impl::assert_not_null(ctx)), std::string(CPP2_UFCS(name)(decl)))}; + + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + ", "); + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ": " + cpp2::to_string(fwd_ad_type) + ", "); + + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + ", "); + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) {// Add forward type for higher order + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(cpp2::move(fwd_pass_style)) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ": " + cpp2::to_string(cpp2::move(fwd_ad_type)) + ", "); } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(cpp2::move(rws_pass_style)) + " " + cpp2::to_string(cpp2::move(name)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + ": " + cpp2::to_string(cpp2::move(rws_ad_type)) + ", "); } - diff += ";"; + else { + auto type {CPP2_UFCS(get_declaration)(param).type()}; - return ; - } + autodiff_activity_check ada {ctx}; + CPP2_UFCS(pre_traverse)(ada, param); - // Handle binary <=> - if (CPP2_UFCS(ssize)(relational_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one relational term here"); - } - auto compare_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(relational_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(compare_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_compare_with_____"; - auto count {0}; - for ( auto const& term : compare_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; + if (ada.active) { + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(type) + ", "); + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + ", "); + + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(type) + ", "); + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(cpp2::move(fwd_pass_style)) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + ", "); + } + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(cpp2::move(rws_pass_style)) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_rws_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + ", "); + } + else { + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(type) + ", "); + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(cpp2::move(fwd_pass_style)) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(type) + ", "); } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; - } - diff += ";"; - return ; + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), cpp2::move(name), cpp2::move(type), cpp2::move(ada).active); + } } - // Handle binary << and >> - if (CPP2_UFCS(ssize)(compare_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one compare term here"); - } - auto shift_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(compare_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(shift_terms),1)) - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_shift_with_____"; - auto count {0}; - for ( auto const& term : shift_terms ) { - if (cpp2::impl::cmp_greater(++count,1)) { - diff += CPP2_UFCS(get_op)(term) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; + // b) Add arguments for returns that become inputs + + if (CPP2_UFCS(has_non_void_return_type)(f) && CPP2_UFCS(empty)(CPP2_UFCS(get_returns)(f))) {// TODO: has_non_void_return_type is true for return lists: (r: double) bug/feature? + // TODO: check if name "r" is available. (Also needs inspection of functions at call sides.) + if (CPP2_UFCS(has_deduced_return_type)(f)) { + // TODO: Take care of initialization order error. + CPP2_UFCS(add_reverse_primal)(diff, "inout r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + ", "); + } + else { + CPP2_UFCS(add_reverse_primal)(diff, "inout r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + ": " + cpp2::to_string(CPP2_UFCS(get_rws_ad_type)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(get_unnamed_return_type)(f))) + ", "); } - diff += ";"; + } + else { + for ( auto const& param : CPP2_UFCS(get_returns)(f) ) { + auto name {CPP2_UFCS(get_declaration)(param).name()}; + auto type {CPP2_UFCS(get_declaration)(param).type()}; - return ; + auto rws_pass_style {to_string_view(CPP2_UFCS(get_reverse_passing_style)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(get_passing_style)(param)))}; + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(cpp2::move(rws_pass_style)) + " " + cpp2::to_string(cpp2::move(name)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).rws_suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_rws_ad_type)((*cpp2::impl::assert_not_null(ctx)), cpp2::move(type))) + " , "); + } } - // Handle binary + and - - if (CPP2_UFCS(ssize)(shift_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one shift term here"); + CPP2_UFCS(add_forward)(diff, ") -> ("); + CPP2_UFCS(add_reverse_primal)(diff, ") -> ("); + + // c) Returns + + if (CPP2_UFCS(has_non_void_return_type)(f) && CPP2_UFCS(empty)(CPP2_UFCS(get_returns)(f))) {// TODO: has_non_void_return_type is true for return lists: (r: double) bug/feature? + // TODO: check if name "r" is available. (Also needs inspection of functions at call sides.) + if (CPP2_UFCS(has_deduced_return_type)(f)) { + // TODO: Take care of initialization order error. + CPP2_UFCS(add_forward)(diff, "r, r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ", "); + CPP2_UFCS(add_reverse_primal)(diff, "r, "); + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_reverse_primal)(diff, "r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ","); + } + } + else { + CPP2_UFCS(add_forward)(diff, "r: " + cpp2::to_string(CPP2_UFCS(get_unnamed_return_type)(f)) + " = (), r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ": " + cpp2::to_string(CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(get_unnamed_return_type)(f))) + " = (), "); + CPP2_UFCS(add_reverse_primal)(diff, "r: " + cpp2::to_string(CPP2_UFCS(get_unnamed_return_type)(f)) + " = (), "); + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_reverse_primal)(diff, "r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ": " + cpp2::to_string(CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(get_unnamed_return_type)(f))) + " = (), "); + } + } } - auto additive_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(shift_terms))))}; - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(additive_terms),1)) - { - auto first {true}; - std::string fwd {"" + cpp2::to_string(lhs) + "_d = "}; - std::string primal {"" + cpp2::to_string(lhs) + " = "}; - for ( auto const& term : additive_terms ) { - if (!(first)) { - auto op {CPP2_UFCS(to_string)(CPP2_UFCS(get_op)(term))}; - fwd += " " + cpp2::to_string(op) + " "; - primal += " " + cpp2::to_string(cpp2::move(op)) + " "; + else { + for ( auto const& param : CPP2_UFCS(get_returns)(f) ) { + auto name {CPP2_UFCS(get_declaration)(param).name()}; + auto type {CPP2_UFCS(get_declaration)(param).type()}; + + auto fwd_pass_style {to_string_view(CPP2_UFCS(get_passing_style)(param))}; + //rws_pass_style := to_string_view(ctx*.get_reverse_passing_style(param.get_passing_style())); + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))) + " = 0.0, "); + CPP2_UFCS(add_forward)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + " = 0.0, "); + + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(fwd_pass_style) + " " + cpp2::to_string(name) + " : " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))) + " = 0.0, "); + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_reverse_primal)(diff, "" + cpp2::to_string(cpp2::move(fwd_pass_style)) + " " + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + " = 0.0, "); } - auto var {handle_expression_term(mf, CPP2_UFCS(get_term)(term))}; - fwd += "" + cpp2::to_string(var) + "_d"; - primal += "" + cpp2::to_string(cpp2::move(var)) + ""; - - first = false; + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), "" + cpp2::to_string(cpp2::move(name)) + "", "" + cpp2::to_string(cpp2::move(type)) + "", true);// TODO_a: Add acitivty check } + } - fwd += ";"; - primal += ";"; + CPP2_UFCS(add_forward)(diff, ") = {"); + CPP2_UFCS(add_reverse_primal)(diff, ") = {"); - diff += cpp2::move(fwd) + cpp2::move(primal); + // Generate the body + if (!(CPP2_UFCS(has_compound_body)(f))) { + CPP2_UFCS(error)(f, "temporary alpha limitation: a differentiable function must have a {}-enclosed body"); return ; } - // Handle binary * / % - if (CPP2_UFCS(ssize)(additive_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one additive term here"); - } - auto multiplicative_terms {CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_UFCS(front)(cpp2::move(additive_terms))))}; +#line 6034 "reflect.h2" + autodiff_stmt_handler ad_impl {&*cpp2::impl::assert_not_null(ctx), f}; - // Temporary test loop - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(multiplicative_terms),1)) +#line 6037 "reflect.h2" + for ( auto const& stmt : CPP2_UFCS(get_statements)(CPP2_UFCS(get_compound_body)(f)) ) { - std::cout << "debug: found " + cpp2::to_string(CPP2_UFCS(ssize)(multiplicative_terms)) + " is_as_expressions\n"; - for ( auto const& isas : multiplicative_terms ) { - std::cout << "debug: is_as term: \"" + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(isas))) + "\"\n"; - if (CPP2_UFCS(is_identifier)(CPP2_UFCS(get_term)(isas))) { - std::cout << "debug: identifier: " + cpp2::to_string(CPP2_UFCS(get_identifier)(CPP2_UFCS(get_term)(isas))) + "\n"; - } - } + ad_impl.pre_traverse(stmt); } + CPP2_UFCS(add_forward)(diff, ad_impl.diff.fwd); + CPP2_UFCS(add_reverse_primal)(diff, ad_impl.diff.rws_primal); + CPP2_UFCS(add_reverse_primal)(diff, cpp2::move(ad_impl).diff.rws_backprop); - if (cpp2::impl::cmp_greater(CPP2_UFCS(ssize)(multiplicative_terms),1)) - { - auto arg_a {handle_expression_term(mf, CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS_LITERAL(multiplicative_terms, 0)))}; + CPP2_UFCS(add_forward)(diff, "}"); + CPP2_UFCS(add_reverse_primal)(diff, "}"); - int i {1}; - for( ; cpp2::impl::cmp_less(i,CPP2_UFCS(ssize)(multiplicative_terms)); i += 1 ) { - auto arg_b {handle_expression_term(mf, CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS(multiplicative_terms, i)))}; + CPP2_UFCS(leave_function)((*cpp2::impl::assert_not_null(ctx))); - auto op {CPP2_UFCS(to_string)(CPP2_UFCS(get_op)(CPP2_ASSERT_IN_BOUNDS(multiplicative_terms, i)))}; + if (CPP2_UFCS(is_forward)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_member)(decl, diff.fwd); + } + if (CPP2_UFCS(is_reverse)((*cpp2::impl::assert_not_null(ctx)))) { + CPP2_UFCS(add_member)(decl, diff.rws_primal); + } + CPP2_UFCS(reset)(diff); - std::string fwd {""}; - std::string primal {""}; + CPP2_UFCS(add_as_differentiated)((*cpp2::impl::assert_not_null(ctx)), f); + } - if ("*" == op) { - fwd = "" + cpp2::to_string(arg_a) + " * " + cpp2::to_string(arg_b) + "_d + " + cpp2::to_string(arg_b) + " * " + cpp2::to_string(arg_a) + "_d"; - primal = "" + cpp2::to_string(arg_a) + " * " + cpp2::to_string(cpp2::move(arg_b)) + ""; - } - else {if ("/" == op) { - fwd = "" + cpp2::to_string(arg_a) + "_d / " + cpp2::to_string(arg_b) + " - " + cpp2::to_string(arg_a) + " * " + cpp2::to_string(arg_b) + "_d / (" + cpp2::to_string(arg_b) + " * " + cpp2::to_string(arg_b) + ")"; - primal = "" + cpp2::to_string(arg_a) + " / " + cpp2::to_string(cpp2::move(arg_b)) + ""; - } - else { - CPP2_UFCS(error)(mf, "unkown multiplicative operator '" + cpp2::to_string(cpp2::move(op)) + "'"); - }} +#line 6062 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in o) -> void{ + std::string ad_name {"" + cpp2::to_string(CPP2_UFCS(name)(o)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + ""}; + std::string fwd_ad_type {CPP2_UFCS(get_fwd_ad_type)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(type)(o))}; + std::string ad_init {""}; -#line 3695 "reflect.h2" - if (i + 1 == CPP2_UFCS(ssize)(multiplicative_terms)) { - // Last item - diff += "" + cpp2::to_string(lhs) + "_d = " + cpp2::to_string(cpp2::move(fwd)) + ";"; - diff += "" + cpp2::to_string(lhs) + " = " + cpp2::to_string(cpp2::move(primal)) + ";"; - } - else { - // Temporary - auto t {gen_temporary()}; - // TODO: Get type of expression, in order to define the type of t. - diff += "" + cpp2::to_string(t) + "_d := " + cpp2::to_string(cpp2::move(fwd)) + ";"; - diff += "" + cpp2::to_string(t) + " := " + cpp2::to_string(cpp2::move(primal)) + ";"; + if (CPP2_UFCS(has_initializer)(o)) { + autodiff_expression_handler ad {ctx}; + CPP2_UFCS(pre_traverse)(ad, CPP2_UFCS(get_initializer)(o)); - arg_a = cpp2::move(t); - } - } + if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(empty)(ad.diff)) ) { cpp2::cpp2_default.report_violation(""); } + ad_init = " = " + cpp2::move(ad).fwd_expr; + } + + diff = "" + cpp2::to_string(cpp2::move(ad_name)) + " : " + cpp2::to_string(cpp2::move(fwd_ad_type)) + cpp2::to_string(cpp2::move(ad_init)) + ";"; + + if (is_type_context) { + + diff_ad_type += "public " + cpp2::to_string(diff.fwd) + "\n"; + } + else { + CPP2_UFCS(add_member)(decl, diff.fwd); } + diff = ""; + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), "" + cpp2::to_string(CPP2_UFCS(name)(o)) + "", "" + cpp2::to_string(CPP2_UFCS(type)(o)) + "", true, true);// TODO_a: Add acitivty check } -#line 3714 "reflect.h2" - auto autodiff_impl::handle_expression_statement(auto& mf, auto const& expr) & -> void{ - if (CPP2_UFCS(is_simple_assignment)(expr)) - { - // If this is not an assignment to a parameter or return object, skip it - auto lhs_rhs {CPP2_UFCS(get_lhs_rhs_if_simple_assignment)(expr)}; - auto lhs {CPP2_UFCS(get_first_token_ignoring_this)(cpp2::move(lhs_rhs).lhs)}; - if (!(CPP2_UFCS(has_parameter_or_return_named)(mf, lhs))) - { - return ; - } +#line 6090 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in t) -> void{ + CPP2_UFCS(push_stack)((*cpp2::impl::assert_not_null(ctx)), t); + autodiff_declaration_handler ad {ctx, t}; + ad.is_type_context = true; - auto assignment {CPP2_UFCS(as_assignment_expression)(expr)}; + for ( + auto const& m : CPP2_UFCS(get_members)(t) ) + { + CPP2_UFCS(pre_traverse)(ad, m); + } - // Cpp2 doesn't allow chained assignment, so rhs must be a single logical_or_expression - auto assignment_terms {CPP2_UFCS(get_terms)(cpp2::move(assignment))}; - if (CPP2_UFCS(ssize)(assignment_terms) != 2) { - CPP2_UFCS(error)(mf, "an assignment must have exactly one right-hand side expression"); - } + CPP2_UFCS(pop_stack)((*cpp2::impl::assert_not_null(ctx))); - // Now we handle sequences of binary "expr1 @ expr2 @ ..." where each - // @ is one of a list of operators at the same grammar precedence + if (!(CPP2_UFCS(empty)(ad.diff_ad_type))) { + diff = "" + cpp2::to_string(CPP2_UFCS(name)(t)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).fwd_suffix) + " : type = {\n"; + diff += "" + cpp2::to_string(cpp2::move(ad).diff_ad_type) + ""; + diff += "}"; - handle_expression_terms(mf, CPP2_UFCS(to_string)(cpp2::move(lhs)), CPP2_UFCS(get_terms)(CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS_LITERAL(cpp2::move(assignment_terms), 1)))); + CPP2_UFCS(add_member)(decl, diff.fwd); + diff = ""; } } -#line 3741 "reflect.h2" -auto autodiff(meta::type_declaration& t) -> void -{ - for ( - auto const& m : CPP2_UFCS(get_members)(t) ) - if ( CPP2_UFCS(is_function)(m)) - { - auto mf {CPP2_UFCS(as_function)(m)}; +#line 6114 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in t) -> void{ + CPP2_UFCS(error)(t, "AD: Do not know how to handle parameter_declaration: " + cpp2::to_string(CPP2_UFCS(to_string)(t)) + ""); + } - std::string diff {" " + cpp2::to_string(CPP2_UFCS(name)(mf)) + "_diff: ("}; +#line 6119 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in stmt) -> void{ + CPP2_UFCS(error)(stmt, "AD: Do not know how to handle statement in declaration context: " + cpp2::to_string(CPP2_UFCS(to_string)(stmt)) + ""); + } - // 1. Generate the modified signature - // a) Parameters +#line 6125 "reflect.h2" +auto autodiff(meta::type_declaration& t) -> void +{ - for ( auto const& param : CPP2_UFCS(get_parameters)(mf) ) { - diff += "" + cpp2::to_string(CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param))) + " : " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))) + ", "; - diff += "" + cpp2::to_string(CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param))) + "_d : " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))) + ", "; - } + std::string_view constexpr suffix_token{ "suffix=" }; + std::string_view constexpr rws_suffix_token{ "rws_suffix=" }; + std::string_view constexpr order_token{ "order=" }; + std::string_view constexpr reverse_token{ "reverse" }; - diff += ") -> ("; + auto args {CPP2_UFCS(get_arguments)(t)}; - // b) Returns + std::string suffix {"_d"}; + std::string rws_suffix {"_b"}; + int order {1}; + bool reverse {false}; + for ( auto const& arg_str : cpp2::move(args) ) { + if (CPP2_UFCS(starts_with)(arg_str, "\"") && CPP2_UFCS(ends_with)(arg_str, "\"")) { + auto arg {CPP2_UFCS(substr)(arg_str, 1, CPP2_UFCS(ssize)(arg_str) - 2)}; - for ( auto const& param : CPP2_UFCS(get_returns)(mf) ) { - diff += "" + cpp2::to_string(CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param))) + " : " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))) + " = 1, "; - diff += "" + cpp2::to_string(CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param))) + "_d : " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))) + " = 1, "; + if (CPP2_UFCS(starts_with)(arg, suffix_token)) { + suffix = CPP2_UFCS(substr)(cpp2::move(arg), CPP2_UFCS(size)(suffix_token)); + continue; + } + else {if (CPP2_UFCS(starts_with)(arg, rws_suffix_token)) { + suffix = CPP2_UFCS(substr)(cpp2::move(arg), CPP2_UFCS(size)(rws_suffix_token)); + continue; + } + else {if (CPP2_UFCS(starts_with)(arg, order_token)) { + if (!(string_util::string_to_int(CPP2_UFCS(substr)(arg, CPP2_UFCS(size)(order_token)), order))) { + CPP2_UFCS(error)(t, "AD: Could not parse derivative order: " + cpp2::to_string(CPP2_UFCS(substr)(cpp2::move(arg), CPP2_UFCS(size)(order_token))) + ""); + return ; + } + continue; + } + else {if (cpp2::move(arg) == reverse_token) { + reverse = true; + continue; + }}}} } - diff += ") = {"; + CPP2_UFCS(error)(t, "AD: Unknown argument: " + cpp2::to_string(arg_str) + ""); + return ; + } - // Generate the body + autodiff_context ad_ctx {order, reverse}; + ad_ctx.fwd_suffix = cpp2::move(suffix); + ad_ctx.rws_suffix = cpp2::move(rws_suffix); - if (!(CPP2_UFCS(has_compound_body)(mf))) { - CPP2_UFCS(error)(mf, "temporary alpha limitation: a differentiable function must have a {}-enclosed body"); - return ; - } + if (CPP2_UFCS(parent_is_nonglobal_namespace)(t)) { + auto p {CPP2_UFCS(as_nonglobal_namespace)(CPP2_UFCS(get_parent)(t))}; + CPP2_UFCS(create_namespace_stack)(ad_ctx, p); + autodiff_declaration_handler ad {&ad_ctx, cpp2::move(p)}; + CPP2_UFCS(pre_traverse)(cpp2::move(ad), t); - autodiff_impl ad_impl {}; + } + else {if (CPP2_UFCS(parent_is_type)(t)) { + auto p {CPP2_UFCS(as_type)(CPP2_UFCS(get_parent)(t))}; + CPP2_UFCS(create_namespace_stack)(ad_ctx, p); + autodiff_declaration_handler ad {&ad_ctx, cpp2::move(p)}; + CPP2_UFCS(pre_traverse)(cpp2::move(ad), t); + } + else { + // TODO: Remove when global namespace is available. + // Traverse without parent context + CPP2_UFCS(push_stack)(ad_ctx, t); + autodiff_declaration_handler ad {&ad_ctx, t}; -#line 3780 "reflect.h2" - for ( auto const& stmt : CPP2_UFCS(get_statements)(CPP2_UFCS(get_compound_body)(mf)) ) + for ( + auto const& m : CPP2_UFCS(get_members)(t) ) + if ( CPP2_UFCS(is_function)(m)) { - if (CPP2_UFCS(is_expression_statement)(stmt)) - { - CPP2_UFCS(handle_expression_statement)(ad_impl, mf, CPP2_UFCS(get_expression)(CPP2_UFCS(as_expression_statement)(stmt))); - } + CPP2_UFCS(pre_traverse)(ad, m); } - diff += cpp2::move(ad_impl).diff; - - diff += "}"; + CPP2_UFCS(pop_stack)(ad_ctx); + }} - CPP2_UFCS(add_member)(t, cpp2::move(diff)); + if (1 != cpp2::move(order)) { + CPP2_UFCS(add_runtime_support_include)(t, "cpp2taylor.h"); + } + if (cpp2::move(reverse)) { + CPP2_UFCS(add_runtime_support_include)(t, "cpp2ad_stack.h"); } + + CPP2_UFCS(finish)(ad_ctx); + + static_cast(cpp2::move(ad_ctx)); } @@ -6896,7 +10319,7 @@ return expression_flags::none; [[nodiscard]] auto expression_flags::from_code(cpp2::impl::in s) -> expression_flags{ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::move(str), "expression_flags::", "")); } -#line 3796 "reflect.h2" +#line 6213 "reflect.h2" //----------------------------------------------------------------------- // // regex - creates regular expressions from members @@ -6912,11 +10335,11 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov // ``` // -#line 3812 "reflect.h2" +#line 6229 "reflect.h2" // Possible modifiers for a regular expression. // -#line 3816 "reflect.h2" +#line 6233 "reflect.h2" // mod: i // mod: m // mod: s @@ -6924,116 +10347,116 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov // mod: x // mod: xx -#line 3825 "reflect.h2" +#line 6242 "reflect.h2" // Tokens for regular expressions. // // Basic class for a regex token. // -#line 3834 "reflect.h2" +#line 6251 "reflect.h2" regex_token::regex_token(cpp2::impl::in str) : string_rep{ str }{ -#line 3836 "reflect.h2" +#line 6253 "reflect.h2" } -#line 3838 "reflect.h2" +#line 6255 "reflect.h2" regex_token::regex_token() : string_rep{ "" }{ -#line 3840 "reflect.h2" +#line 6257 "reflect.h2" } //parse: (inout ctx: parse_context) -> token_ptr; // Generate the matching code. // Create a reverse token for look behind expressions. -#line 3846 "reflect.h2" +#line 6263 "reflect.h2" auto regex_token::add_groups([[maybe_unused]] std::set& unnamed_param_2) const -> void{}// Adds all group indices to the set. -#line 3847 "reflect.h2" +#line 6264 "reflect.h2" [[nodiscard]] auto regex_token::to_string() const& -> std::string{return string_rep; }// Create a string representation. -#line 3848 "reflect.h2" +#line 6265 "reflect.h2" auto regex_token::set_string(cpp2::impl::in s) & -> void{string_rep = s; } regex_token::~regex_token() noexcept{}// Set the string representation. -#line 3863 "reflect.h2" +#line 6280 "reflect.h2" regex_token_check::regex_token_check(cpp2::impl::in str, cpp2::impl::in check_) : regex_token{ str } , check{ check_ }{ -#line 3866 "reflect.h2" +#line 6283 "reflect.h2" } -#line 3868 "reflect.h2" +#line 6285 "reflect.h2" auto regex_token_check::generate_code(generation_context& ctx) const -> void{ ctx.add_check(check + "(" + ctx.match_parameters() + ")"); } -#line 3872 "reflect.h2" +#line 6289 "reflect.h2" [[nodiscard]] auto regex_token_check::reverse() const -> token_ptr { return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, CPP2_UFCS(to_string)((*this)), (*this).check); } regex_token_check::~regex_token_check() noexcept{} -#line 3884 "reflect.h2" +#line 6301 "reflect.h2" regex_token_code::regex_token_code(cpp2::impl::in str, cpp2::impl::in code_) : regex_token{ str } , code{ code_ }{ -#line 3887 "reflect.h2" +#line 6304 "reflect.h2" } -#line 3889 "reflect.h2" +#line 6306 "reflect.h2" auto regex_token_code::generate_code(generation_context& ctx) const -> void{ ctx.add(code); } -#line 3893 "reflect.h2" +#line 6310 "reflect.h2" [[nodiscard]] auto regex_token_code::reverse() const -> token_ptr { return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, CPP2_UFCS(to_string)((*this)), (*this).code); } regex_token_code::~regex_token_code() noexcept{} -#line 3903 "reflect.h2" +#line 6320 "reflect.h2" regex_token_empty::regex_token_empty(cpp2::impl::in str) : regex_token{ str }{ -#line 3905 "reflect.h2" +#line 6322 "reflect.h2" } -#line 3907 "reflect.h2" +#line 6324 "reflect.h2" auto regex_token_empty::generate_code([[maybe_unused]] generation_context& unnamed_param_2) const -> void{ // Nothing. } -#line 3911 "reflect.h2" +#line 6328 "reflect.h2" [[nodiscard]] auto regex_token_empty::reverse() const -> token_ptr { return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, CPP2_UFCS(to_string)((*this))); } regex_token_empty::~regex_token_empty() noexcept{} -#line 3923 "reflect.h2" +#line 6340 "reflect.h2" regex_token_list::regex_token_list(cpp2::impl::in t) : regex_token{ gen_string(t) } , tokens{ t }{ -#line 3926 "reflect.h2" +#line 6343 "reflect.h2" } -#line 3928 "reflect.h2" +#line 6345 "reflect.h2" auto regex_token_list::generate_code(generation_context& ctx) const -> void{ for ( auto const& token : tokens ) { (*cpp2::impl::assert_not_null(token)).generate_code(ctx); } } -#line 3934 "reflect.h2" +#line 6351 "reflect.h2" auto regex_token_list::add_groups(std::set& groups) const -> void{ for ( auto const& token : tokens ) { (*cpp2::impl::assert_not_null(token)).add_groups(groups); } } -#line 3940 "reflect.h2" +#line 6357 "reflect.h2" [[nodiscard]] auto regex_token_list::gen_string(cpp2::impl::in vec) -> std::string{ std::string r {""}; for ( auto const& token : vec ) { @@ -7042,7 +10465,7 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov return r; } -#line 3948 "reflect.h2" +#line 6365 "reflect.h2" [[nodiscard]] auto regex_token_list::reverse() const -> token_ptr{ int s {cpp2::unchecked_narrow(tokens.size())}; @@ -7058,7 +10481,7 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov regex_token_list::~regex_token_list() noexcept{} -#line 3976 "reflect.h2" +#line 6393 "reflect.h2" auto parse_context_group_state::next_alternative() & -> void{ token_vec new_list {}; std::swap(new_list, cur_match_list); @@ -7066,14 +10489,14 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov static_cast(alternate_match_lists.insert(alternate_match_lists.end(), CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, cpp2::move(new_list)))); } -#line 3984 "reflect.h2" +#line 6401 "reflect.h2" auto parse_context_group_state::swap(parse_context_group_state& t) & -> void{// NOLINT(performance-noexcept-swap) std::swap(cur_match_list, t.cur_match_list); std::swap(alternate_match_lists, t.alternate_match_lists); std::swap(modifiers, t.modifiers); } -#line 3991 "reflect.h2" +#line 6408 "reflect.h2" [[nodiscard]] auto parse_context_group_state::get_as_token() & -> token_ptr{ if (alternate_match_lists.empty()) { post_process_list(cur_match_list); @@ -7085,15 +10508,15 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov } } -#line 4003 "reflect.h2" +#line 6420 "reflect.h2" auto parse_context_group_state::add(cpp2::impl::in token) & -> void{ cur_match_list.push_back(token); } -#line 4008 "reflect.h2" +#line 6425 "reflect.h2" [[nodiscard]] auto parse_context_group_state::empty() const& -> bool { return cur_match_list.empty(); } -#line 4012 "reflect.h2" +#line 6429 "reflect.h2" auto parse_context_group_state::post_process_list(token_vec& list) -> void{ // Merge all characters auto merge_pos {list.begin()}; @@ -7114,7 +10537,7 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov , modifiers{ modifiers_ }{} parse_context_group_state::parse_context_group_state(){} -#line 4038 "reflect.h2" +#line 6455 "reflect.h2" [[nodiscard]] auto parse_context_branch_reset_state::next() & -> int{ auto g {cur_group}; cur_group += 1; @@ -7123,20 +10546,20 @@ parse_context_group_state::parse_context_group_state(){} return g; } -#line 4047 "reflect.h2" +#line 6464 "reflect.h2" auto parse_context_branch_reset_state::set_next(cpp2::impl::in g) & -> void{ cur_group = g; max_group = max(max_group, g); } -#line 4053 "reflect.h2" +#line 6470 "reflect.h2" auto parse_context_branch_reset_state::next_alternative() & -> void{ if (is_active) { cur_group = from; } } -#line 4060 "reflect.h2" +#line 6477 "reflect.h2" auto parse_context_branch_reset_state::set_active_reset(cpp2::impl::in restart) & -> void{ is_active = true; cur_group = restart; @@ -7151,16 +10574,16 @@ parse_context_group_state::parse_context_group_state(){} , from{ from_ }{} parse_context_branch_reset_state::parse_context_branch_reset_state(){} -#line 4090 "reflect.h2" +#line 6507 "reflect.h2" parse_context::parse_context(cpp2::impl::in r, auto const& e) : regex{ r } , root{ CPP2_UFCS_TEMPLATE_NONLOCAL(cpp2_new)(cpp2::shared, "") } , error_out{ e }{ -#line 4094 "reflect.h2" +#line 6511 "reflect.h2" } -#line 4100 "reflect.h2" +#line 6517 "reflect.h2" [[nodiscard]] auto parse_context::start_group() & -> parse_context_group_state { parse_context_group_state old_state {}; @@ -7170,7 +10593,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return old_state; } -#line 4110 "reflect.h2" +#line 6527 "reflect.h2" [[nodiscard]] auto parse_context::end_group(cpp2::impl::in old_state) & -> token_ptr { auto inner {cur_group_state.get_as_token()}; @@ -7178,17 +10601,17 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return inner; } -#line 4117 "reflect.h2" +#line 6534 "reflect.h2" [[nodiscard]] auto parse_context::get_modifiers() const& -> expression_flags{ return cur_group_state.modifiers; } -#line 4121 "reflect.h2" +#line 6538 "reflect.h2" auto parse_context::set_modifiers(cpp2::impl::in mod) & -> void{ cur_group_state.modifiers = mod; } -#line 4128 "reflect.h2" +#line 6545 "reflect.h2" [[nodiscard]] auto parse_context::branch_reset_new_state() & -> parse_context_branch_reset_state { parse_context_branch_reset_state old_state {}; @@ -7198,7 +10621,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return old_state; } -#line 4137 "reflect.h2" +#line 6554 "reflect.h2" auto parse_context::branch_reset_restore_state(cpp2::impl::in old_state) & -> void { auto max_group {cur_branch_reset_state.max_group}; @@ -7206,24 +10629,24 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} cur_branch_reset_state.set_next(cpp2::move(max_group)); } -#line 4144 "reflect.h2" +#line 6561 "reflect.h2" auto parse_context::next_alternative() & -> void { cur_group_state.next_alternative(); cur_branch_reset_state.next_alternative(); } -#line 4152 "reflect.h2" +#line 6569 "reflect.h2" auto parse_context::add_token(cpp2::impl::in token) & -> void{ cur_group_state.add(token); } -#line 4156 "reflect.h2" +#line 6573 "reflect.h2" [[nodiscard]] auto parse_context::has_token() const& -> bool{ return !(cur_group_state.empty()); } -#line 4160 "reflect.h2" +#line 6577 "reflect.h2" [[nodiscard]] auto parse_context::pop_token() & -> token_ptr { token_ptr r {nullptr}; @@ -7235,22 +10658,22 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return r; } -#line 4171 "reflect.h2" +#line 6588 "reflect.h2" [[nodiscard]] auto parse_context::get_as_token() & -> token_ptr{ return root; } -#line 4177 "reflect.h2" +#line 6594 "reflect.h2" [[nodiscard]] auto parse_context::get_cur_group() const& -> int{ return cur_branch_reset_state.cur_group; } -#line 4181 "reflect.h2" +#line 6598 "reflect.h2" [[nodiscard]] auto parse_context::next_group() & -> int{ return cur_branch_reset_state.next(); } -#line 4185 "reflect.h2" +#line 6602 "reflect.h2" auto parse_context::set_named_group(cpp2::impl::in name, cpp2::impl::in id) & -> void { if (!(named_groups.contains(name))) {// Redefinition of group name is not an error. The left most one is retained. @@ -7258,7 +10681,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4192 "reflect.h2" +#line 6609 "reflect.h2" [[nodiscard]] auto parse_context::get_named_group(cpp2::impl::in name) const& -> int { auto iter {named_groups.find(name)}; @@ -7270,10 +10693,10 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4205 "reflect.h2" +#line 6622 "reflect.h2" [[nodiscard]] auto parse_context::current() const& -> char{return CPP2_ASSERT_IN_BOUNDS(regex, pos); } -#line 4208 "reflect.h2" +#line 6625 "reflect.h2" [[nodiscard]] auto parse_context::get_next_position(cpp2::impl::in in_class, cpp2::impl::in no_skip) const& -> size_t { auto perl_syntax {false}; @@ -7313,7 +10736,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return cur; } -#line 4248 "reflect.h2" +#line 6665 "reflect.h2" [[nodiscard]] auto parse_context::next_impl(cpp2::impl::in in_class, cpp2::impl::in no_skip) & -> bool { pos = get_next_position(in_class, no_skip); @@ -7325,14 +10748,14 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4259 "reflect.h2" +#line 6676 "reflect.h2" [[nodiscard]] auto parse_context::next() & -> decltype(auto) { return next_impl(false, false); } -#line 4260 "reflect.h2" +#line 6677 "reflect.h2" [[nodiscard]] auto parse_context::next_in_class() & -> decltype(auto) { return next_impl(true, false); } -#line 4261 "reflect.h2" +#line 6678 "reflect.h2" [[nodiscard]] auto parse_context::next_no_skip() & -> decltype(auto) { return next_impl(false, true); } -#line 4263 "reflect.h2" +#line 6680 "reflect.h2" [[nodiscard]] auto parse_context::next_n(cpp2::impl::in n) & -> bool{ auto r {true}; auto cur {0}; @@ -7342,10 +10765,10 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return r; } -#line 4272 "reflect.h2" +#line 6689 "reflect.h2" [[nodiscard]] auto parse_context::has_next() const& -> bool{return cpp2::impl::cmp_less(pos,regex.size()); } -#line 4274 "reflect.h2" +#line 6691 "reflect.h2" [[nodiscard]] auto parse_context::grab_until_impl(cpp2::impl::in e, cpp2::impl::out r, cpp2::impl::in any) & -> bool { auto end {pos}; // NOLINT(clang-analyzer-deadcode.DeadStores) @@ -7367,14 +10790,14 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4295 "reflect.h2" +#line 6712 "reflect.h2" [[nodiscard]] auto parse_context::grab_until(cpp2::impl::in e, cpp2::impl::out r) & -> decltype(auto) { return grab_until_impl(e, cpp2::impl::out(&r), false); } -#line 4296 "reflect.h2" +#line 6713 "reflect.h2" [[nodiscard]] auto parse_context::grab_until(cpp2::impl::in e, cpp2::impl::out r) & -> decltype(auto) { return grab_until_impl(std::string(1, e), cpp2::impl::out(&r), false); } -#line 4297 "reflect.h2" +#line 6714 "reflect.h2" [[nodiscard]] auto parse_context::grab_until_one_of(cpp2::impl::in e, cpp2::impl::out r) & -> decltype(auto) { return grab_until_impl(e, cpp2::impl::out(&r), true); } -#line 4299 "reflect.h2" +#line 6716 "reflect.h2" [[nodiscard]] auto parse_context::grab_n(cpp2::impl::in n, cpp2::impl::out r) & -> bool { if (cpp2::impl::cmp_less_eq(pos + cpp2::impl::as_(n),regex.size())) { @@ -7388,7 +10811,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4312 "reflect.h2" +#line 6729 "reflect.h2" [[nodiscard]] auto parse_context::grab_number() & -> std::string { auto start {pos}; @@ -7410,7 +10833,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return cpp2::move(r.value()); } -#line 4333 "reflect.h2" +#line 6750 "reflect.h2" [[nodiscard]] auto parse_context::peek_impl(cpp2::impl::in in_class) const& -> char{ auto next_pos {get_next_position(in_class, false)}; if (cpp2::impl::cmp_less(next_pos,regex.size())) { @@ -7421,12 +10844,12 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4343 "reflect.h2" +#line 6760 "reflect.h2" [[nodiscard]] auto parse_context::peek() const& -> decltype(auto) { return peek_impl(false); } -#line 4344 "reflect.h2" +#line 6761 "reflect.h2" [[nodiscard]] auto parse_context::peek_in_class() const& -> decltype(auto) { return peek_impl(true); } -#line 4349 "reflect.h2" +#line 6766 "reflect.h2" [[nodiscard]] auto parse_context::parser_group_modifiers(cpp2::impl::in change_str, expression_flags& parser_modifiers) & -> bool { auto is_negative {false}; @@ -7481,7 +10904,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return true; } -#line 4403 "reflect.h2" +#line 6820 "reflect.h2" [[nodiscard]] auto parse_context::parse_until(cpp2::impl::in term) & -> bool{ token_ptr cur_token {}; @@ -7521,7 +10944,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return true; } -#line 4442 "reflect.h2" +#line 6859 "reflect.h2" [[nodiscard]] auto parse_context::parse(cpp2::impl::in modifiers) & -> bool { @@ -7537,21 +10960,21 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return r; } -#line 4459 "reflect.h2" +#line 6876 "reflect.h2" [[nodiscard]] auto parse_context::get_pos() const& -> decltype(auto) { return pos; } -#line 4460 "reflect.h2" +#line 6877 "reflect.h2" [[nodiscard]] auto parse_context::get_range(cpp2::impl::in start, cpp2::impl::in end) const& -> decltype(auto) { return std::string(regex.substr(start, end - start + 1)); } -#line 4461 "reflect.h2" +#line 6878 "reflect.h2" [[nodiscard]] auto parse_context::valid() const& -> bool{return has_next() && !(has_error); } -#line 4463 "reflect.h2" +#line 6880 "reflect.h2" [[nodiscard]] auto parse_context::error(cpp2::impl::in err) & -> token_ptr{ has_error = true; error_out("Error during parsing of regex '" + cpp2::to_string(regex) + "' at position '" + cpp2::to_string(pos) + "': " + cpp2::to_string(err) + ""); return nullptr; } -#line 4478 "reflect.h2" +#line 6895 "reflect.h2" auto generation_function_context::add_tabs(cpp2::impl::in c) & -> void{ int i {0}; for( ; cpp2::impl::cmp_less(i,c); i += 1 ) { @@ -7559,7 +10982,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4485 "reflect.h2" +#line 6902 "reflect.h2" auto generation_function_context::remove_tabs(cpp2::impl::in c) & -> void{ tabs = tabs.substr(0, (cpp2::impl::as_(c)) * 2); } @@ -7569,22 +10992,22 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} , tabs{ tabs_ }{} generation_function_context::generation_function_context(){} -#line 4503 "reflect.h2" +#line 6920 "reflect.h2" [[nodiscard]] auto generation_context::match_parameters() const& -> std::string{return "r.pos, ctx"; } -#line 4508 "reflect.h2" +#line 6925 "reflect.h2" auto generation_context::add(cpp2::impl::in s) & -> void{ auto cur {get_current()}; (*cpp2::impl::assert_not_null(cur)).code += "" + cpp2::to_string((*cpp2::impl::assert_not_null(cur)).tabs) + cpp2::to_string(s) + "\n"; } -#line 4514 "reflect.h2" +#line 6931 "reflect.h2" auto generation_context::add_check(cpp2::impl::in check) & -> void{ auto cur {get_current()}; (*cpp2::impl::assert_not_null(cur)).code += "" + cpp2::to_string((*cpp2::impl::assert_not_null(cur)).tabs) + "if !cpp2::regex::" + cpp2::to_string(check) + " { r.matched = false; break; }\n"; } -#line 4520 "reflect.h2" +#line 6937 "reflect.h2" auto generation_context::add_statefull(cpp2::impl::in next_func, cpp2::impl::in check) & -> void { end_func_statefull(check); @@ -7593,7 +11016,7 @@ generation_function_context::generation_function_context(){} start_func_named(cpp2::move(name)); } -#line 4528 "reflect.h2" +#line 6945 "reflect.h2" auto generation_context::start_func_named(cpp2::impl::in name) & -> void { auto cur {new_context()}; @@ -7605,7 +11028,7 @@ generation_function_context::generation_function_context(){} (*cpp2::impl::assert_not_null(cpp2::move(cur))).add_tabs(3); } -#line 4539 "reflect.h2" +#line 6956 "reflect.h2" [[nodiscard]] auto generation_context::start_func() & -> std::string { auto name {gen_func_name()}; @@ -7613,7 +11036,7 @@ generation_function_context::generation_function_context(){} return cpp2::move(name) + "()"; } -#line 4546 "reflect.h2" +#line 6963 "reflect.h2" auto generation_context::end_func_statefull(cpp2::impl::in s) & -> void { auto cur {get_current()}; @@ -7634,7 +11057,7 @@ generation_function_context::generation_function_context(){} finish_context(); } -#line 4567 "reflect.h2" +#line 6984 "reflect.h2" [[nodiscard]] auto generation_context::generate_func(cpp2::impl::in token) & -> std::string { auto name {start_func()}; @@ -7644,7 +11067,7 @@ generation_function_context::generation_function_context(){} return name; } -#line 4577 "reflect.h2" +#line 6994 "reflect.h2" [[nodiscard]] auto generation_context::generate_reset(cpp2::impl::in> groups) & -> std::string { if (groups.empty()) { @@ -7667,33 +11090,33 @@ generation_function_context::generation_function_context(){} return cpp2::move(name) + "()"; } -#line 4601 "reflect.h2" +#line 7018 "reflect.h2" [[nodiscard]] auto generation_context::gen_func_name() & -> std::string{ auto cur_id {matcher_func}; matcher_func += 1; return "func_" + cpp2::to_string(cpp2::move(cur_id)) + ""; } -#line 4607 "reflect.h2" +#line 7024 "reflect.h2" [[nodiscard]] auto generation_context::next_func_name() & -> std::string{ return gen_func_name() + "()"; } -#line 4611 "reflect.h2" +#line 7028 "reflect.h2" [[nodiscard]] auto generation_context::gen_reset_func_name() & -> std::string{ auto cur_id {reset_func}; reset_func += 1; return "reset_" + cpp2::to_string(cpp2::move(cur_id)) + ""; } -#line 4617 "reflect.h2" +#line 7034 "reflect.h2" [[nodiscard]] auto generation_context::gen_temp() & -> std::string{ auto cur_id {temp_name}; temp_name += 1; return "tmp_" + cpp2::to_string(cpp2::move(cur_id)) + ""; } -#line 4625 "reflect.h2" +#line 7042 "reflect.h2" [[nodiscard]] auto generation_context::new_context() & -> generation_function_context*{ gen_stack.push_back(generation_function_context()); auto cur {get_current()}; @@ -7702,7 +11125,7 @@ generation_function_context::generation_function_context(){} return cur; } -#line 4633 "reflect.h2" +#line 7050 "reflect.h2" auto generation_context::finish_context() & -> void{ auto cur {get_current()}; auto base {get_base()}; @@ -7711,22 +11134,22 @@ generation_function_context::generation_function_context(){} gen_stack.pop_back(); } -#line 4643 "reflect.h2" +#line 7060 "reflect.h2" [[nodiscard]] auto generation_context::get_current() & -> generation_function_context*{ return &gen_stack.back(); } -#line 4647 "reflect.h2" +#line 7064 "reflect.h2" [[nodiscard]] auto generation_context::get_base() & -> generation_function_context*{ return &CPP2_ASSERT_IN_BOUNDS_LITERAL(gen_stack, 0); } -#line 4651 "reflect.h2" +#line 7068 "reflect.h2" [[nodiscard]] auto generation_context::get_entry_func() const& -> std::string{ return entry_func; } -#line 4655 "reflect.h2" +#line 7072 "reflect.h2" [[nodiscard]] auto generation_context::create_named_group_lookup(cpp2::impl::in> named_groups) const& -> std::string { std::string res {"get_named_group_index: (name) -> int = {\n"}; @@ -7750,18 +11173,18 @@ generation_function_context::generation_function_context(){} return res; } -#line 4680 "reflect.h2" +#line 7097 "reflect.h2" [[nodiscard]] auto generation_context::run(cpp2::impl::in token) & -> std::string{ entry_func = generate_func(token); return (*cpp2::impl::assert_not_null(get_base())).code; } -#line 4695 "reflect.h2" +#line 7112 "reflect.h2" alternative_token::alternative_token() : regex_token_empty{ "" }{} -#line 4697 "reflect.h2" +#line 7114 "reflect.h2" [[nodiscard]] auto alternative_token::parse(parse_context& ctx) -> token_ptr{ if (ctx.current() != '|') {return nullptr; } @@ -7772,15 +11195,15 @@ generation_function_context::generation_function_context(){} alternative_token::~alternative_token() noexcept{} -#line 4712 "reflect.h2" +#line 7129 "reflect.h2" alternative_token_gen::alternative_token_gen(cpp2::impl::in a) : regex_token{ gen_string(a) } , alternatives{ a }{ -#line 4715 "reflect.h2" +#line 7132 "reflect.h2" } -#line 4717 "reflect.h2" +#line 7134 "reflect.h2" auto alternative_token_gen::generate_code(generation_context& ctx) const -> void { std::string functions {""}; @@ -7798,7 +11221,7 @@ generation_function_context::generation_function_context(){} ctx.add_statefull(next_name, "cpp2::regex::alternative_token_matcher::match(" + cpp2::to_string(ctx.match_parameters()) + ", other, " + cpp2::to_string(next_name) + " " + cpp2::to_string(cpp2::move(functions)) + ")"); } -#line 4734 "reflect.h2" +#line 7151 "reflect.h2" auto alternative_token_gen::add_groups(std::set& groups) const -> void { for ( auto const& cur : alternatives ) { @@ -7806,7 +11229,7 @@ generation_function_context::generation_function_context(){} } } -#line 4741 "reflect.h2" +#line 7158 "reflect.h2" [[nodiscard]] auto alternative_token_gen::gen_string(cpp2::impl::in a) -> std::string { std::string r {""}; @@ -7820,7 +11243,7 @@ generation_function_context::generation_function_context(){} return r; } -#line 4754 "reflect.h2" +#line 7171 "reflect.h2" [[nodiscard]] auto alternative_token_gen::reverse() const -> token_ptr{ int s {cpp2::unchecked_narrow(alternatives.size())}; @@ -7836,14 +11259,14 @@ generation_function_context::generation_function_context(){} alternative_token_gen::~alternative_token_gen() noexcept{} -#line 4775 "reflect.h2" +#line 7192 "reflect.h2" any_token::any_token(cpp2::impl::in single_line) : regex_token_check{ ".", "any_token_matcher" }{ -#line 4777 "reflect.h2" +#line 7194 "reflect.h2" } -#line 4779 "reflect.h2" +#line 7196 "reflect.h2" [[nodiscard]] auto any_token::parse(parse_context& ctx) -> token_ptr{ if ('.' != ctx.current()) {return nullptr; } @@ -7852,11 +11275,11 @@ generation_function_context::generation_function_context(){} any_token::~any_token() noexcept{} -#line 4794 "reflect.h2" +#line 7211 "reflect.h2" atomic_group_token::atomic_group_token() : regex_token{ "" }{} -#line 4796 "reflect.h2" +#line 7213 "reflect.h2" [[nodiscard]] auto atomic_group_token::reverse() const -> token_ptr{ auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared)}; (*cpp2::impl::assert_not_null(r)).inner_token = CPP2_UFCS(reverse)((*cpp2::impl::assert_not_null(inner_token))); @@ -7864,7 +11287,7 @@ generation_function_context::generation_function_context(){} return r; } -#line 4803 "reflect.h2" +#line 7220 "reflect.h2" auto atomic_group_token::generate_code(generation_context& ctx) const -> void { auto inner_name {ctx.generate_func(inner_token)}; @@ -7873,37 +11296,37 @@ generation_function_context::generation_function_context(){} ctx.add_statefull(next_name, "cpp2::regex::atomic_group_matcher(" + cpp2::to_string(ctx.match_parameters()) + ", " + cpp2::to_string(cpp2::move(inner_name)) + ", other, " + cpp2::to_string(next_name) + ")"); } -#line 4811 "reflect.h2" +#line 7228 "reflect.h2" auto atomic_group_token::add_groups(std::set& groups) const -> void{ (*cpp2::impl::assert_not_null(inner_token)).add_groups(groups); } atomic_group_token::~atomic_group_token() noexcept{} -#line 4825 "reflect.h2" +#line 7242 "reflect.h2" char_token::char_token(cpp2::impl::in t, cpp2::impl::in ignore_case_) : regex_token{ std::string(1, t) } , token{ t } , ignore_case{ ignore_case_ }{ -#line 4829 "reflect.h2" +#line 7246 "reflect.h2" } -#line 4831 "reflect.h2" +#line 7248 "reflect.h2" char_token::char_token(cpp2::impl::in t, cpp2::impl::in ignore_case_) : regex_token{ t } , token{ t } , ignore_case{ ignore_case_ }{ -#line 4835 "reflect.h2" +#line 7252 "reflect.h2" } -#line 4837 "reflect.h2" +#line 7254 "reflect.h2" [[nodiscard]] auto char_token::parse(parse_context& ctx) -> token_ptr{ return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, ctx.current(), ctx.get_modifiers().has(expression_flags::case_insensitive)); } -#line 4841 "reflect.h2" +#line 7258 "reflect.h2" auto char_token::generate_code(generation_context& ctx) const -> void { if (ignore_case) { @@ -7912,14 +11335,14 @@ generation_function_context::generation_function_context(){} { size_t i{0}; -#line 4847 "reflect.h2" +#line 7264 "reflect.h2" for( ; cpp2::impl::cmp_less(i,token.size()); i += 1 ) { CPP2_ASSERT_IN_BOUNDS(lower, i) = string_util::safe_tolower(CPP2_ASSERT_IN_BOUNDS(token, i)); CPP2_ASSERT_IN_BOUNDS(upper, i) = string_util::safe_toupper(CPP2_ASSERT_IN_BOUNDS(token, i)); } } -#line 4852 "reflect.h2" +#line 7269 "reflect.h2" if (upper != lower) { gen_case_insensitive(cpp2::move(lower), cpp2::move(upper), ctx); } @@ -7932,7 +11355,7 @@ size_t i{0}; } } -#line 4864 "reflect.h2" +#line 7281 "reflect.h2" auto char_token::gen_case_insensitive(cpp2::impl::in lower, cpp2::impl::in upper, generation_context& ctx) const& -> void { std::string name {"str_" + cpp2::to_string(ctx.gen_temp()) + ""}; @@ -7954,7 +11377,7 @@ size_t i{0}; ctx.add("else { break; }"); } -#line 4885 "reflect.h2" +#line 7302 "reflect.h2" auto char_token::gen_case_sensitive(generation_context& ctx) const& -> void { std::string name {"str_" + cpp2::to_string(ctx.gen_temp()) + ""}; @@ -7973,7 +11396,7 @@ size_t i{0}; ctx.add("else { break; }"); } -#line 4903 "reflect.h2" +#line 7320 "reflect.h2" [[nodiscard]] auto char_token::add_escapes(std::string str) const& -> std::string { str = string_util::replace_all(str, "\\", "\\\\"); @@ -7989,14 +11412,14 @@ size_t i{0}; return cpp2::move(str); } -#line 4918 "reflect.h2" +#line 7335 "reflect.h2" [[nodiscard]] auto char_token::reverse() const -> token_ptr{ std::string reverse_str {token}; std::reverse(reverse_str.begin(), reverse_str.end()); return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, cpp2::move(reverse_str), ignore_case); } -#line 4924 "reflect.h2" +#line 7341 "reflect.h2" auto char_token::append(char_token const& that) & -> void{ (*this).token += that.token; (*this).string_rep += that.string_rep; @@ -8004,19 +11427,19 @@ size_t i{0}; char_token::~char_token() noexcept{} -#line 4941 "reflect.h2" +#line 7358 "reflect.h2" class_token::class_token(cpp2::impl::in negate_, cpp2::impl::in case_insensitive_, cpp2::impl::in class_str_, cpp2::impl::in str) : regex_token{ str } , negate{ negate_ } , case_insensitive{ case_insensitive_ } , class_str{ class_str_ } -#line 4942 "reflect.h2" +#line 7359 "reflect.h2" { -#line 4947 "reflect.h2" +#line 7364 "reflect.h2" } -#line 4950 "reflect.h2" +#line 7367 "reflect.h2" [[nodiscard]] auto class_token::parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '[') {return nullptr; } @@ -8142,7 +11565,7 @@ size_t i{0}; ); } -#line 5075 "reflect.h2" +#line 7492 "reflect.h2" [[nodiscard]] auto class_token::reverse() const -> token_ptr{ return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, negate, @@ -8152,13 +11575,13 @@ size_t i{0}; ); } -#line 5084 "reflect.h2" +#line 7501 "reflect.h2" auto class_token::generate_code(generation_context& ctx) const -> void { ctx.add_check("class_token_matcher::match(" + cpp2::to_string(ctx.match_parameters()) + ")"); } -#line 5089 "reflect.h2" +#line 7506 "reflect.h2" [[nodiscard]] auto class_token::create_matcher(cpp2::impl::in name, cpp2::impl::in template_arguments) -> std::string { auto sep {", "}; @@ -8169,12 +11592,12 @@ size_t i{0}; class_token::~class_token() noexcept{} -#line 5101 "reflect.h2" +#line 7518 "reflect.h2" [[nodiscard]] auto escape_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } -#line 5106 "reflect.h2" +#line 7523 "reflect.h2" if (std::string::npos == std::string("afenrt^.[]()*{}?+|\\").find(ctx.peek())) { return nullptr; } @@ -8208,7 +11631,7 @@ size_t i{0}; } -#line 5142 "reflect.h2" +#line 7559 "reflect.h2" [[nodiscard]] auto global_group_reset_token_parse(parse_context& ctx) -> token_ptr { if (!((ctx.current() == '\\' && ctx.peek() == 'K'))) {return nullptr; } @@ -8217,19 +11640,19 @@ size_t i{0}; return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, "\\K", "ctx..set_group_start(0, r.pos);"); } -#line 5165 "reflect.h2" +#line 7582 "reflect.h2" group_ref_token::group_ref_token(cpp2::impl::in id_, cpp2::impl::in case_insensitive_, cpp2::impl::in reverse_, cpp2::impl::in str) : regex_token{ str } , id{ id_ } , case_insensitive{ case_insensitive_ } , reverse_eval{ reverse_ } -#line 5166 "reflect.h2" +#line 7583 "reflect.h2" { -#line 5171 "reflect.h2" +#line 7588 "reflect.h2" } -#line 5173 "reflect.h2" +#line 7590 "reflect.h2" [[nodiscard]] auto group_ref_token::parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8331,19 +11754,19 @@ size_t i{0}; return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, cpp2::move(group_id), ctx.get_modifiers().has(expression_flags::case_insensitive), false, cpp2::move(str)); } -#line 5274 "reflect.h2" +#line 7691 "reflect.h2" [[nodiscard]] auto group_ref_token::reverse() const -> token_ptr{ return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, id, case_insensitive, !(reverse_eval), to_string()); } -#line 5278 "reflect.h2" +#line 7695 "reflect.h2" auto group_ref_token::generate_code(generation_context& ctx) const -> void{ ctx.add_check("group_ref_token_matcher(" + cpp2::to_string(ctx.match_parameters()) + ")"); } group_ref_token::~group_ref_token() noexcept{} -#line 5302 "reflect.h2" +#line 7719 "reflect.h2" [[nodiscard]] auto group_token::parse_lookahead_lookbehind(parse_context& ctx, cpp2::impl::in syntax, cpp2::impl::in lookahead, cpp2::impl::in positive) -> token_ptr { static_cast(ctx.next());// Skip last token defining the syntax @@ -8362,7 +11785,7 @@ size_t i{0}; return r; } -#line 5320 "reflect.h2" +#line 7737 "reflect.h2" [[nodiscard]] auto group_token::parse_atomic_pattern(parse_context& ctx, cpp2::impl::in syntax) -> token_ptr { static_cast(ctx.next());// Skip last token defining the syntax @@ -8377,7 +11800,7 @@ size_t i{0}; return r; } -#line 5334 "reflect.h2" +#line 7751 "reflect.h2" [[nodiscard]] auto group_token::parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '(') {return nullptr; } @@ -8537,7 +11960,7 @@ size_t i{0}; } } -#line 5493 "reflect.h2" +#line 7910 "reflect.h2" [[nodiscard]] auto group_token::reverse() const -> token_ptr{ auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared)}; (*cpp2::impl::assert_not_null(r)).number = number; @@ -8546,7 +11969,7 @@ size_t i{0}; return r; } -#line 5501 "reflect.h2" +#line 7918 "reflect.h2" [[nodiscard]] auto group_token::gen_string(cpp2::impl::in name, cpp2::impl::in name_brackets, cpp2::impl::in has_modifier, cpp2::impl::in modifiers, cpp2::impl::in inner_) -> std::string { std::string start {"("}; @@ -8565,7 +11988,7 @@ size_t i{0}; return cpp2::move(start) + (*cpp2::impl::assert_not_null(inner_)).to_string() + ")"; } -#line 5519 "reflect.h2" +#line 7936 "reflect.h2" auto group_token::generate_code(generation_context& ctx) const -> void { if (-1 != number) { @@ -8597,7 +12020,7 @@ size_t i{0}; } } -#line 5550 "reflect.h2" +#line 7967 "reflect.h2" auto group_token::add_groups(std::set& groups) const -> void { (*cpp2::impl::assert_not_null(inner)).add_groups(groups); @@ -8608,7 +12031,7 @@ size_t i{0}; group_token::~group_token() noexcept{} -#line 5562 "reflect.h2" +#line 7979 "reflect.h2" [[nodiscard]] auto hexadecimal_token_parse(parse_context& ctx) -> token_ptr { if (!((ctx.current() == '\\' && ctx.peek() == 'x'))) {return nullptr; } @@ -8647,7 +12070,7 @@ size_t i{0}; return r; } -#line 5603 "reflect.h2" +#line 8020 "reflect.h2" [[nodiscard]] auto line_end_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() == '$' || (ctx.current() == '\\' && ctx.peek() == '$')) { @@ -8665,7 +12088,7 @@ size_t i{0}; }} } -#line 5623 "reflect.h2" +#line 8040 "reflect.h2" [[nodiscard]] auto line_start_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '^' && !((ctx.current() == '\\' && ctx.peek() == 'A'))) {return nullptr; } @@ -8679,16 +12102,16 @@ size_t i{0}; } } -#line 5649 "reflect.h2" +#line 8066 "reflect.h2" lookahead_lookbehind_token::lookahead_lookbehind_token(cpp2::impl::in lookahead_, cpp2::impl::in positive_) : regex_token{ "" } , lookahead{ lookahead_ } , positive{ positive_ }{ -#line 5652 "reflect.h2" +#line 8069 "reflect.h2" } -#line 5654 "reflect.h2" +#line 8071 "reflect.h2" auto lookahead_lookbehind_token::generate_code(generation_context& ctx) const -> void{ auto inner_name {ctx.generate_func(inner)}; @@ -8700,7 +12123,7 @@ size_t i{0}; } } -#line 5665 "reflect.h2" +#line 8082 "reflect.h2" [[nodiscard]] auto lookahead_lookbehind_token::reverse() const -> token_ptr{ auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, lookahead, positive)}; (*cpp2::impl::assert_not_null(r)).inner = inner;// We do not reverse here. Nested lookahead and lookbehind stay as they are. @@ -8708,14 +12131,14 @@ size_t i{0}; return r; } -#line 5672 "reflect.h2" +#line 8089 "reflect.h2" auto lookahead_lookbehind_token::add_groups(std::set& groups) const -> void{ (*cpp2::impl::assert_not_null(inner)).add_groups(groups); } lookahead_lookbehind_token::~lookahead_lookbehind_token() noexcept{} -#line 5680 "reflect.h2" +#line 8097 "reflect.h2" [[nodiscard]] auto named_class_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8741,7 +12164,7 @@ size_t i{0}; return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, "\\" + cpp2::to_string(ctx.current()) + "", "" + cpp2::to_string(cpp2::move(name)) + "::match"); } -#line 5708 "reflect.h2" +#line 8125 "reflect.h2" [[nodiscard]] auto octal_token_parse(parse_context& ctx) -> token_ptr { if (!((ctx.current() == '\\' && ctx.peek() == 'o'))) {return nullptr; } @@ -8767,11 +12190,11 @@ size_t i{0}; return r; } -#line 5745 "reflect.h2" +#line 8162 "reflect.h2" range_token::range_token() : regex_token{ "" }{} -#line 5747 "reflect.h2" +#line 8164 "reflect.h2" [[nodiscard]] auto range_token::parse(parse_context& ctx) -> token_ptr { auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared)}; @@ -8845,7 +12268,7 @@ size_t i{0}; return nullptr; } -#line 5820 "reflect.h2" +#line 8237 "reflect.h2" auto range_token::parse_modifier(parse_context& ctx) & -> void { if (ctx.peek() == '?') { @@ -8858,7 +12281,7 @@ size_t i{0}; }} } -#line 5832 "reflect.h2" +#line 8249 "reflect.h2" [[nodiscard]] auto range_token::gen_mod_string() const& -> std::string { if (kind == range_flags::not_greedy) { @@ -8872,7 +12295,7 @@ size_t i{0}; }} } -#line 5845 "reflect.h2" +#line 8262 "reflect.h2" [[nodiscard]] auto range_token::gen_range_string() const& -> std::string { std::string r {""}; @@ -8892,7 +12315,7 @@ size_t i{0}; return r; } -#line 5864 "reflect.h2" +#line 8281 "reflect.h2" [[nodiscard]] auto range_token::reverse() const -> token_ptr{ auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared)}; (*cpp2::impl::assert_not_null(r)).min_count = min_count; @@ -8903,7 +12326,7 @@ size_t i{0}; return r; } -#line 5874 "reflect.h2" +#line 8291 "reflect.h2" auto range_token::generate_code(generation_context& ctx) const -> void { auto inner_name {ctx.generate_func(inner_token)}; @@ -8915,14 +12338,14 @@ size_t i{0}; ctx.add_statefull(next_name, "cpp2::regex::range_token_matcher::match(" + cpp2::to_string(ctx.match_parameters()) + ", " + cpp2::to_string(cpp2::move(inner_name)) + ", " + cpp2::to_string(cpp2::move(reset_name)) + ", other, " + cpp2::to_string(next_name) + ")"); } -#line 5885 "reflect.h2" +#line 8302 "reflect.h2" auto range_token::add_groups(std::set& groups) const -> void{ (*cpp2::impl::assert_not_null(inner_token)).add_groups(groups); } range_token::~range_token() noexcept{} -#line 5897 "reflect.h2" +#line 8314 "reflect.h2" [[nodiscard]] auto special_range_token::parse(parse_context& ctx) -> token_ptr { auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared)}; @@ -8946,7 +12369,7 @@ size_t i{0}; if (!(ctx.has_token())) {return ctx.error("'" + cpp2::to_string(ctx.current()) + "' without previous element."); } -#line 5921 "reflect.h2" +#line 8338 "reflect.h2" (*cpp2::impl::assert_not_null(r)).parse_modifier(ctx); (*cpp2::impl::assert_not_null(r)).inner_token = ctx.pop_token(); @@ -8956,7 +12379,7 @@ size_t i{0}; special_range_token::~special_range_token() noexcept{} -#line 5933 "reflect.h2" +#line 8350 "reflect.h2" [[nodiscard]] auto start_match_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8972,7 +12395,7 @@ size_t i{0}; } } -#line 5953 "reflect.h2" +#line 8370 "reflect.h2" [[nodiscard]] auto word_boundary_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8990,15 +12413,15 @@ size_t i{0}; }} } -#line 5989 "reflect.h2" +#line 8406 "reflect.h2" template regex_generator::regex_generator(cpp2::impl::in r, Error_out const& e) : regex{ r } , error_out{ e }{ -#line 5992 "reflect.h2" +#line 8409 "reflect.h2" } -#line 5994 "reflect.h2" +#line 8411 "reflect.h2" template [[nodiscard]] auto regex_generator::parse() & -> std::string { // Extract modifiers and adapt regex. @@ -9034,7 +12457,7 @@ size_t i{0}; return source; } -#line 6029 "reflect.h2" +#line 8446 "reflect.h2" template auto regex_generator::extract_modifiers() & -> void { if (regex.find_first_of("'/") == 0) { @@ -9050,7 +12473,7 @@ size_t i{0}; } } -#line 6045 "reflect.h2" +#line 8462 "reflect.h2" template [[nodiscard]] auto generate_regex(cpp2::impl::in regex, Err const& err) -> std::string { regex_generator parser {regex, err}; @@ -9059,7 +12482,7 @@ template [[nodiscard]] auto generate_regex(cpp2::impl::in void { auto has_default {false}; @@ -9114,7 +12537,7 @@ auto regex_gen(meta::type_declaration& t) -> void CPP2_UFCS(add_runtime_support_include)(t, "cpp2regex.h"); } -#line 6114 "reflect.h2" +#line 8531 "reflect.h2" [[nodiscard]] auto apply_metafunctions( declaration_node& n, type_declaration& rtype, @@ -9242,7 +12665,7 @@ auto regex_gen(meta::type_declaration& t) -> void return true; } -#line 6242 "reflect.h2" +#line 8659 "reflect.h2" } } diff --git a/source/reflect.h2 b/source/reflect.h2 index bfbfd3527..f7811b410 100644 --- a/source/reflect.h2 +++ b/source/reflect.h2 @@ -229,6 +229,9 @@ reflection_base: @polymorphic_base @copy_constructible type = position: (override this) -> source_position = n*.position(); print: (this) -> std::string = n*.pretty_print_visualize(0); + + is_same: (this, o: reflection_base) -> bool = n == o.n; // Test pointers + is_same: (this, _: reflection_base) -> bool = false; // Different types => false } @@ -572,6 +575,7 @@ type_or_namespace_declaration: @copy_constructible type = if !decl*.is_declaration() { error("cannot add a member that is not a declaration"); } + require( n*.add_type_or_namespace_member(move decl), std::string("unexpected error while attempting to add member:\n") + source ); } @@ -2610,1186 +2614,3599 @@ sample_print: (s: std::string_view, indent: i32) = << "\n"; } +simple_traverser: type = { -//----------------------------------------------------------------------- -// -// sample_traverser serves two purposes: -// -// - infrastructure for writing reflection API test cases -// -// - a sample for how code can use the reflection API, notably -// for reflecting on function bodies (statements, expressions) -// + pre_traverse: (virtual inout this, decl: meta::declaration) = { + traverse(decl); + } -sample_traverser: (decl: meta::declaration, indent: i32) = -{ - sample_print("Declaration: (decl.name())$", indent); + traverse: (virtual inout this, decl: meta::declaration) = + { + if decl.is_function() { + pre_traverse(decl.as_function()); + } - if decl.is_function() { - sample_traverser(decl.as_function(), indent+1); - } + if decl.is_object() { + pre_traverse(decl.as_object()); + } - if decl.is_object() { - sample_traverser(decl.as_object(), indent+1); - } + if decl.is_type() { + pre_traverse(decl.as_type()); + } - if decl.is_type() { - sample_traverser(decl.as_type(), indent+1); + // ... + // ... extend as desired to namespace, alias, etc. + // ... } - // ... - // ... extend as desired to namespace, alias, etc. - // ... -} - -sample_traverser: (f: meta::function_declaration, indent: i32 = 0) = -{ - sample_print("Function: (f.name())$", indent+1); + pre_traverse: (virtual inout this, f: meta::function_declaration) = { + traverse(f); + } - parameters := f.get_parameters(); - if !parameters.empty() { - sample_print("Parameters:", indent+2); + traverse: (virtual inout this, f: meta::function_declaration) = + { + parameters := f.get_parameters(); for parameters do (param) { - sample_traverser(param, indent+3); + pre_traverse(param); } - } - returns := f.get_returns(); - if !returns.empty() { - sample_print("Returns:", indent+2); + returns := f.get_returns(); for returns do (param) { - sample_traverser(param, indent+3); + pre_traverse(param); + } + + if !f.has_compound_body() { + pre_traverse(f.get_body()); + } + else { + pre_traverse(f.get_compound_body()); } } - sample_print("Body:", indent+2); - if !f.has_compound_body() { - sample_traverser(f.get_body(), indent+3); + + pre_traverse: (virtual inout this, o: meta::object_declaration) = { + traverse(o); } - else { - sample_traverser(f.get_compound_body(), indent+3); + + traverse: (virtual inout this, o: meta::object_declaration) = + { + if o.has_initializer() { + pre_traverse(o.get_initializer()); + } } -} -sample_traverser: (o: meta::object_declaration, indent: i32) = -{ - sample_print("Object: name (o.name())$, type (o.type())$", indent); - if o.has_initializer() { - sample_print("Initializer:", indent+1); - sample_traverser(o.get_initializer(), indent+2); + pre_traverse: (virtual inout this, t: meta::type_declaration) = { + traverse(t); } -} + traverse: (virtual inout this, t: meta::type_declaration) = + { + for t.get_members() do (m) { + pre_traverse(m); + } + } -sample_traverser: (t: meta::type_declaration, indent: i32 = 0) = -{ - sample_print("Type: (t.name())$", indent); - if t.parent_is_nonglobal_namespace() + pre_traverse: (virtual inout this, t: meta::parameter_declaration) = { + traverse(t); + } + + traverse: (virtual inout this, t: meta::parameter_declaration) = { - ns := t.get_parent().as_nonglobal_namespace(); - sample_print("is a member of namespace (ns.name())$ which contains the following names:", indent+1); - for ns.get_members() do (m) { - sample_print(m.name(), indent+2); - } - ns.add_member( "add_1: (x) = x+1;"); - _ = ns; + pre_traverse(t.get_declaration()); } - for t.get_members() do (m) { - sample_traverser(m, indent+1); + pre_traverse: (virtual inout this, stmt: meta::statement) = { + traverse(stmt); } -} + traverse: (virtual inout this, stmt: meta::statement) = + { + if stmt.is_expression_statement() { + pre_traverse(stmt.as_expression_statement().get_expression()); + } -sample_traverser: (t: meta::parameter_declaration, indent: i32 = 0) = -{ - sample_print("parameter:", indent); + if stmt.is_compound_statement() { + pre_traverse(stmt.as_compound_statement()); + } - pass := t.get_passing_style(); - if pass == passing_style::in { sample_print("passing style: in", indent+1 ); } - if pass == passing_style::in_ref { sample_print("passing style: in_ref", indent+1 ); } - if pass == passing_style::copy { sample_print("passing style: copy", indent+1 ); } - if pass == passing_style::inout { sample_print("passing style: inout", indent+1 ); } - if pass == passing_style::out { sample_print("passing style: out", indent+1 ); } - if pass == passing_style::move { sample_print("passing style: move", indent+1 ); } - if pass == passing_style::forward { sample_print("passing style: forward", indent+1 ); } - if pass == passing_style::forward_ref { sample_print("passing style: forward_ref", indent+1 ); } + if stmt.is_selection_statement() + { + pre_traverse(stmt.as_selection_statement()); + } - sample_print("declaration:", indent+1); - sample_traverser(t.get_declaration(), indent+2); -} + if stmt.is_declaration() { + pre_traverse(stmt.as_declaration()); + } + if stmt.is_return_statement() { + pre_traverse(stmt.as_return_statement()); + } -sample_traverser: (stmt: meta::statement, indent: i32) = -{ - params := stmt.get_parameters(); - if !params.empty() { - sample_print("statement parameters: ", indent); - for params do (param) { - sample_traverser( param, indent+1 ); + if stmt.is_iteration_statement() { + pre_traverse(stmt.as_iteration_statement()); } - } - if stmt.is_expression_statement() { - sample_traverser(stmt.as_expression_statement().get_expression(), indent); + // TODO: + // using + // contract + // inspect + // jump } - if stmt.is_compound_statement() { - sample_traverser(stmt.as_compound_statement(), indent); + + pre_traverse: (virtual inout this, stmt: meta::compound_statement) = { + traverse(stmt); } - if stmt.is_selection_statement() + traverse: (virtual inout this, stmt: meta::compound_statement) = { - sel := stmt.as_selection_statement(); - sample_print("(sel.get_identifier())$ statement", indent); + stmts := stmt.get_statements(); - sample_print("condition:", indent+1); - sample_traverser(sel.get_expression(), indent+2); - - sample_print("true branch:", indent+1); - sample_traverser(sel.get_true_branch(), indent+2); - - if sel.has_false_branch() { - sample_print("false branch:", indent+1); - sample_traverser(sel.get_false_branch(), indent+2); + for stmts do (cur) { + pre_traverse(cur); } } - if stmt.is_declaration() { - sample_traverser(stmt.as_declaration(), indent+1); - } - if stmt.is_return_statement() { - sample_traverser(stmt.as_return_statement(), indent+1); + pre_traverse: (virtual inout this, stmt: meta::return_statement) = { + traverse(stmt); } - if stmt.is_iteration_statement() { - sample_traverser(stmt.as_iteration_statement(), indent+1); + traverse: (virtual inout this, stmt: meta::return_statement) = + { + if stmt.has_expression() { + pre_traverse(stmt.get_expression()); + } } - // TODO: - // using - // contract - // inspect - // jump -} - - -sample_traverser: (stmt: meta::compound_statement, indent: i32) = -{ - stmts := stmt.get_statements(); - if stmts.empty() { - sample_print("compound statement (empty)", indent); - return; + pre_traverse: (virtual inout this, stmt: meta::iteration_statement) = { + traverse(stmt); } - // Else - sample_print("compound statement", indent); - for stmts do (stmt2) { - sample_traverser(stmt2, indent+1); + traverse: (virtual inout this, stmt: meta::iteration_statement) = + { + if stmt.is_do() || stmt.is_while() { + pre_traverse(stmt.get_do_while_condition()); + pre_traverse(stmt.get_do_while_body()); + } + else { + assert(stmt.is_for()); + pre_traverse(stmt.get_for_range()); + pre_traverse(stmt.get_for_parameter()); + pre_traverse(stmt.get_for_body()); + } + + if stmt.has_next() { + pre_traverse(stmt.get_next_expression()); + } } -} -sample_traverser: (stmt: meta::return_statement, indent: i32) = -{ - sample_print("return statement", indent); - if stmt.has_expression() { - sample_print("expression", indent+1); - sample_traverser(stmt.get_expression(), indent+2); + pre_traverse: (virtual inout this, stmt: meta::selection_statement) = { + traverse(stmt); } -} + traverse: (virtual inout this, stmt: meta::selection_statement) = + { + pre_traverse(stmt.get_expression()); + pre_traverse(stmt.get_true_branch()); -sample_traverser: (stmt: meta::iteration_statement, indent: i32) = -{ - if stmt.is_do() || stmt.is_while() { - if stmt.is_do() { - sample_print("do loop:", indent); + if stmt.has_false_branch() { + pre_traverse(stmt.get_false_branch()); } - else { - sample_print("while loop:", indent); - } - sample_print("condition:", indent+1); - sample_traverser(stmt.get_do_while_condition(), indent+2); - sample_print("body:", indent+1); - sample_traverser(stmt.get_do_while_body(), indent+2); - } - else { - assert(stmt.is_for()); - sample_print("for loop:", indent); - sample_print("range:", indent+1); - sample_traverser(stmt.get_for_range(), indent+2); - sample_print("parameter:", indent+1); - sample_traverser(stmt.get_for_parameter(), indent+2); - sample_print("body:", indent+1); - sample_traverser(stmt.get_for_body(), indent+2); } - if stmt.has_next() { - sample_print("next expression:", indent+1); - sample_traverser(stmt.get_next_expression(), indent+2); + + pre_traverse: (virtual inout this, expr: meta::expression) = + { + // Nothing to select here. + traverse(expr); } -} + traverse: (virtual inout this, expr: meta::expression) = + { + // An expression has other shortcuts to query deeper properties, + // but let's just traverse all the nested grammer elements to + // show how that traversal works -sample_traverser: (expr: meta::expression, indent: i32) = -{ - // An expression has other shortcuts to query deeper properties, - // but let's just traverse all the nested grammar elements to - // show how that traversal works + // The expressions use the pre_traverse function to decide which expression + // they are. The correct one calls traverse only once. - // The expression's basic payload is just an assignment expression - // today - this can change when we add try-expressions - if expr.is_assignment_expression() { - sample_traverser(expr.as_assignment_expression(), indent); + // The expression's basic payload is just an assignment expression + pre_traverse(expr.as_assignment_expression()); } -} -sample_traverser: (binexpr: meta::assignment_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + pre_traverse: (virtual inout this, binexpr: meta::assignment_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); - // If this has only one term, it's not an actual assignment, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // If this has only one term, it's not an actual assignment, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("assignment", indent); + traverse: (virtual inout this, binexpr: meta::assignment_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, binexpr: meta::logical_or_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); -sample_traverser: (binexpr: meta::logical_or_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + // If this has only one term, it's not an actual logical-or, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } - // If this has only one term, it's not an actual logical-or, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("logical-or", indent); + traverse: (virtual inout this, binexpr: meta::logical_or_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} -sample_traverser: (binexpr: meta::logical_and_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + pre_traverse: (virtual inout this, binexpr: meta::logical_and_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); - // If this has only one term, it's not an actual logical-and, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // If this has only one term, it's not an actual logical-and, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("logical-and", indent); + traverse: (virtual inout this, binexpr: meta::logical_and_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, binexpr: meta::bit_or_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); -sample_traverser: (binexpr: meta::bit_or_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + // If this has only one term, it's not an actual bit-or, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } - // If this has only one term, it's not an actual bit-or, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("bit-or", indent); + traverse: (virtual inout this, binexpr: meta::bit_or_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, binexpr: meta::bit_xor_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); -sample_traverser: (binexpr: meta::bit_xor_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + // If this has only one term, it's not an actual bit-xor, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } - // If this has only one term, it's not an actual bit-xor, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("bit-xor", indent); + traverse: (virtual inout this, binexpr: meta::bit_xor_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} -sample_traverser: (binexpr: meta::bit_and_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + pre_traverse: (virtual inout this, binexpr: meta::bit_and_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); - // If this has only one term, it's not an actual bit-and, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // If this has only one term, it's not an actual bit-and, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("bit-and", indent); + traverse: (virtual inout this, binexpr: meta::bit_and_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} -sample_traverser: (binexpr: meta::equality_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + pre_traverse: (virtual inout this, binexpr: meta::equality_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); - // If this has only one term, it's not an actual equality, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // If this has only one term, it's not an actual equality, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("equality", indent); + traverse: (virtual inout this, binexpr: meta::equality_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, binexpr: meta::relational_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); -sample_traverser: (binexpr: meta::relational_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + // If this has only one term, it's not an actual relational, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } - // If this has only one term, it's not an actual relational, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("relational", indent); + traverse: (virtual inout this, binexpr: meta::relational_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, binexpr: meta::compare_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); -sample_traverser: (binexpr: meta::compare_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + // If this has only one term, it's not an actual compare, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } - // If this has only one term, it's not an actual compare, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("compare", indent); + traverse: (virtual inout this, binexpr: meta::compare_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, binexpr: meta::shift_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); -sample_traverser: (binexpr: meta::shift_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + // If this has only one term, it's not an actual shift, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } - // If this has only one term, it's not an actual shift, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("shift", indent); + traverse: (virtual inout this, binexpr: meta::shift_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, binexpr: meta::additive_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); -sample_traverser: (binexpr: meta::additive_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + // If this has only one term, it's not an actual additive, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } - // If this has only one term, it's not an actual additive, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("additive", indent); + traverse: (virtual inout this, binexpr: meta::additive_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} -sample_traverser: (binexpr: meta::multiplicative_expression, indent: i32) = -{ - terms := binexpr.get_terms(); - assert(!terms.empty()); + pre_traverse: (virtual inout this, binexpr: meta::multiplicative_expression) = + { + terms := binexpr.get_terms(); + assert(!terms.empty()); - // If this has only one term, it's not an actual multiplicative, - // it's holding a lower grammar production so go traverse that - if terms.ssize() == 1 { - sample_traverser(terms.front().get_term(), indent); + // If this has only one term, it's not an actual multiplicative, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + pre_traverse(terms.front().get_term()); + } + + // Else we're at an actual binary expression with a rhs + else { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("multiplicative", indent); + traverse: (virtual inout this, binexpr: meta::multiplicative_expression) = + { + terms := binexpr.get_terms(); - (copy first := true) for terms do (term) { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("term:", indent+1); - sample_traverser(term.get_term(), indent+2); + traverse(term.get_term()); } } -} + pre_traverse: (virtual inout this, isas: meta::is_as_expression) = + { + terms := isas.get_terms(); -sample_traverser: (isas: meta::is_as_expression, indent: i32) = -{ - terms := isas.get_terms(); + // If this has no additional terms, it's not an actual is-as, + // it's holding a lower grammar production so go traverse that + if terms.empty() { + pre_traverse(isas.get_expression()); + } - // If this has no additional terms, it's not an actual is-as, - // it's holding a lower grammar production so go traverse that - if terms.empty() { - sample_traverser(isas.get_expression(), indent); + // Else we're at an actual is-as expression with a rhs + else { + traverse(isas); + } } - // Else we're at an actual is-as expression with a rhs - else { - sample_print("is-as expression", indent); + traverse: (virtual inout this, isas: meta::is_as_expression) = + { + terms := isas.get_terms(); - sample_print("expression", indent+1); - sample_traverser(isas.get_expression(), indent+2); + pre_traverse(isas.get_expression()); for terms do (term) { - sample_print("op: (term.get_op())$", indent+1); - sample_print("term:", indent+1); - sample_traverser(term.get_expr(), indent+2); + traverse(term.get_expr()); + } + } + + traverse: (virtual inout this, exprs: meta::expression_list) = + { + for exprs.get_expressions() do (expr) { + traverse(expr); + } + } + + pre_traverse: (virtual inout this, prefix: meta::prefix_expression) = + { + ops := prefix.get_ops(); + + // If this has no additional ops, it's not a naked prefix expr, + // it's holding a lower grammar production so go traverse that + if ops.empty() { + pre_traverse(prefix.get_postfix_expression(),); + } + + // Else we're at an actual prefix expression with ops + else { + traverse(prefix); + } + } + + traverse: (virtual inout this, prefix: meta::prefix_expression) = + { + pre_traverse(prefix.get_postfix_expression()); + } + + pre_traverse: (virtual inout this, postfix: meta::postfix_expression) = + { + terms := postfix.get_terms(); + + // If this has no additional terms, it's not a naked postfix expr, + // it's holding a lower grammar production so go traverse that + if terms.empty() { + traverse(postfix.get_primary_expression()); + } + + // Else we're at an actual postfix expression with ops + else { + traverse(postfix); + } + } + + traverse: (virtual inout this, postfix: meta::postfix_expression) = + { + terms := postfix.get_terms(); + + traverse(postfix.get_primary_expression()); + + for terms do (term) { + if term.is_id_expression() { + traverse(term.get_id_expression()); + } + else if term.is_expression_list() { + traverse(term.get_expression_list()); + } + else if term.is_expression() { + traverse(term.get_expression()); + } + } + } + + traverse: (virtual inout this, uid: meta::unqualified_id) = + { + _ = uid; + } + + + traverse: (virtual inout this, qid: meta::qualified_id) = + { + for qid.get_terms() + do (term) + { + traverse(term.get_unqualified()); + } + } + + + traverse: (virtual inout this, tid: meta::type_id) = + { + if tid.is_postfix_expression() { + traverse(tid.as_postfix_expression()); + } + else if tid.is_qualified_id() { + traverse(tid.as_qualified_id()); + } + else if tid.is_unqualified_id() { + traverse(tid.as_unqualified_id()); + } + else { + // Regular type_id + } + } + + + traverse: (virtual inout this, primary: meta::primary_expression) = + { + if primary.is_identifier() { + // Regular identifier + } + else if primary.is_expression_list() { + traverse(primary.as_expression_list()); + } + else if primary.is_literal() { + // Regular literal + } + else if primary.is_declaration() { + // TODO: traverse(primary.as_declaration()); + } + else { + // Regular primary + } + } + + + traverse: (virtual inout this, idexpr: meta::id_expression) = + { + if idexpr.is_identifier() { + // Regular id + } + else if idexpr.is_qualified() { + traverse(idexpr.as_qualified()); + } + else if idexpr.is_unqualified() { + traverse(idexpr.as_unqualified()); + } + else { + // Regular id expr } } } -sample_traverser: (exprs: meta::expression_list, indent: i32) = +//----------------------------------------------------------------------- +// +// sample_traverser serves two purposes: +// +// - infrastructure for writing reflection API test cases +// +// - a sample for how code can use the reflection API, notably +// for reflecting on function bodies (statements, expressions) +// + +sample_traverser: (decl: meta::declaration, indent: i32) = { - if exprs.is_empty() { - sample_print("()", indent); + sample_print("Declaration: (decl.name())$", indent); + + if decl.is_function() { + sample_traverser(decl.as_function(), indent+1); } - else { - sample_print("(", indent); - for exprs.get_expressions() do (expr) { - sample_traverser(expr, indent+1); - } - sample_print(")", indent); + + if decl.is_object() { + sample_traverser(decl.as_object(), indent+1); + } + + if decl.is_type() { + sample_traverser(decl.as_type(), indent+1); } + + // ... + // ... extend as desired to namespace, alias, etc. + // ... } -sample_traverser: (prefix: meta::prefix_expression, indent: i32) = +sample_traverser: (f: meta::function_declaration, indent: i32 = 0) = { - ops := prefix.get_ops(); + sample_print("Function: (f.name())$", indent+1); - // If this has no additional ops, it's not a naked prefix expr, - // it's holding a lower grammar production so go traverse that - if ops.empty() { - sample_traverser(prefix.get_postfix_expression(), indent); + parameters := f.get_parameters(); + if !parameters.empty() { + sample_print("Parameters:", indent+2); + for parameters do (param) { + sample_traverser(param, indent+3); + } } - // Else we're at an actual prefix expression with ops + returns := f.get_returns(); + if !returns.empty() { + sample_print("Returns:", indent+2); + for returns do (param) { + sample_traverser(param, indent+3); + } + } + + sample_print("Body:", indent+2); + if !f.has_compound_body() { + sample_traverser(f.get_body(), indent+3); + } else { - sample_print("prefix expression", indent); + sample_traverser(f.get_compound_body(), indent+3); + } +} - for ops do (op) { - sample_print("op: (op)$", indent+1); + +sample_traverser: (o: meta::object_declaration, indent: i32) = +{ + sample_print("Object: name (o.name())$, type (o.type())$", indent); + if o.has_initializer() { + sample_print("Initializer:", indent+1); + sample_traverser(o.get_initializer(), indent+2); + } +} + + +sample_traverser: (t: meta::type_declaration, indent: i32 = 0) = +{ + sample_print("Type: (t.name())$", indent); + + if t.parent_is_nonglobal_namespace() + { + ns := t.get_parent().as_nonglobal_namespace(); + sample_print("is a member of namespace (ns.name())$ which contains the following names:", indent+1); + for ns.get_members() do (m) { + sample_print(m.name(), indent+2); } + ns.add_member( "add_1: (x) = x+1;"); + _ = ns; + } - sample_print("expression", indent+1); - sample_traverser(prefix.get_postfix_expression(), indent+2); + for t.get_members() do (m) { + sample_traverser(m, indent+1); } } -sample_traverser: (postfix: meta::postfix_expression, indent: i32) = +sample_traverser: (t: meta::parameter_declaration, indent: i32 = 0) = { - terms := postfix.get_terms(); + sample_print("parameter:", indent); - // If this has no additional terms, it's not a naked postfix expr, - // it's holding a lower grammar production so go traverse that - if terms.empty() { - sample_traverser(postfix.get_primary_expression(), indent); + pass := t.get_passing_style(); + if pass == passing_style::in { sample_print("passing style: in", indent+1 ); } + if pass == passing_style::in_ref { sample_print("passing style: in_ref", indent+1 ); } + if pass == passing_style::copy { sample_print("passing style: copy", indent+1 ); } + if pass == passing_style::inout { sample_print("passing style: inout", indent+1 ); } + if pass == passing_style::out { sample_print("passing style: out", indent+1 ); } + if pass == passing_style::move { sample_print("passing style: move", indent+1 ); } + if pass == passing_style::forward { sample_print("passing style: forward", indent+1 ); } + if pass == passing_style::forward_ref { sample_print("passing style: forward_ref", indent+1 ); } + + sample_print("declaration:", indent+1); + sample_traverser(t.get_declaration(), indent+2); +} + + +sample_traverser: (stmt: meta::statement, indent: i32) = +{ + params := stmt.get_parameters(); + if !params.empty() { + sample_print("statement parameters: ", indent); + for params do (param) { + sample_traverser( param, indent+1 ); + } + } + + if stmt.is_expression_statement() { + sample_traverser(stmt.as_expression_statement().get_expression(), indent); + } + + if stmt.is_compound_statement() { + sample_traverser(stmt.as_compound_statement(), indent); + } + + if stmt.is_selection_statement() + { + sel := stmt.as_selection_statement(); + sample_print("(sel.get_identifier())$ statement", indent); + + sample_print("condition:", indent+1); + sample_traverser(sel.get_expression(), indent+2); + + sample_print("true branch:", indent+1); + sample_traverser(sel.get_true_branch(), indent+2); + + if sel.has_false_branch() { + sample_print("false branch:", indent+1); + sample_traverser(sel.get_false_branch(), indent+2); + } + } + + if stmt.is_declaration() { + sample_traverser(stmt.as_declaration(), indent+1); + } + + if stmt.is_return_statement() { + sample_traverser(stmt.as_return_statement(), indent+1); + } + + if stmt.is_iteration_statement() { + sample_traverser(stmt.as_iteration_statement(), indent+1); + } + + // TODO: + // using + // contract + // inspect + // jump +} + + +sample_traverser: (stmt: meta::compound_statement, indent: i32) = +{ + stmts := stmt.get_statements(); + + if stmts.empty() { + sample_print("compound statement (empty)", indent); + return; + } + + // Else + sample_print("compound statement", indent); + for stmts do (stmt2) { + sample_traverser(stmt2, indent+1); + } +} + + +sample_traverser: (stmt: meta::return_statement, indent: i32) = +{ + sample_print("return statement", indent); + if stmt.has_expression() { + sample_print("expression", indent+1); + sample_traverser(stmt.get_expression(), indent+2); + } +} + + +sample_traverser: (stmt: meta::iteration_statement, indent: i32) = +{ + if stmt.is_do() || stmt.is_while() { + if stmt.is_do() { + sample_print("do loop:", indent); + } + else { + sample_print("while loop:", indent); + } + sample_print("condition:", indent+1); + sample_traverser(stmt.get_do_while_condition(), indent+2); + sample_print("body:", indent+1); + sample_traverser(stmt.get_do_while_body(), indent+2); + } + else { + assert(stmt.is_for()); + sample_print("for loop:", indent); + sample_print("range:", indent+1); + sample_traverser(stmt.get_for_range(), indent+2); + sample_print("parameter:", indent+1); + sample_traverser(stmt.get_for_parameter(), indent+2); + sample_print("body:", indent+1); + sample_traverser(stmt.get_for_body(), indent+2); + } + + if stmt.has_next() { + sample_print("next expression:", indent+1); + sample_traverser(stmt.get_next_expression(), indent+2); + } +} + + +sample_traverser: (expr: meta::expression, indent: i32) = +{ + // An expression has other shortcuts to query deeper properties, + // but let's just traverse all the nested grammar elements to + // show how that traversal works + + // The expression's basic payload is just an assignment expression + // today - this can change when we add try-expressions + if expr.is_assignment_expression() { + sample_traverser(expr.as_assignment_expression(), indent); + } +} + + +sample_traverser: (binexpr: meta::assignment_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual assignment, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("assignment", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::logical_or_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual logical-or, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("logical-or", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::logical_and_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual logical-and, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("logical-and", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::bit_or_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual bit-or, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("bit-or", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::bit_xor_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual bit-xor, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("bit-xor", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::bit_and_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual bit-and, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("bit-and", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::equality_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual equality, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("equality", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::relational_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual relational, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("relational", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::compare_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual compare, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("compare", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::shift_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual shift, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("shift", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::additive_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual additive, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("additive", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (binexpr: meta::multiplicative_expression, indent: i32) = +{ + terms := binexpr.get_terms(); + assert(!terms.empty()); + + // If this has only one term, it's not an actual multiplicative, + // it's holding a lower grammar production so go traverse that + if terms.ssize() == 1 { + sample_traverser(terms.front().get_term(), indent); + } + + // Else we're at an actual binary expression with a rhs + else { + sample_print("multiplicative", indent); + + (copy first := true) + for terms + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("term:", indent+1); + sample_traverser(term.get_term(), indent+2); + } + } +} + + +sample_traverser: (isas: meta::is_as_expression, indent: i32) = +{ + terms := isas.get_terms(); + + // If this has no additional terms, it's not an actual is-as, + // it's holding a lower grammar production so go traverse that + if terms.empty() { + sample_traverser(isas.get_expression(), indent); + } + + // Else we're at an actual is-as expression with a rhs + else { + sample_print("is-as expression", indent); + + sample_print("expression", indent+1); + sample_traverser(isas.get_expression(), indent+2); + + for terms do (term) { + sample_print("op: (term.get_op())$", indent+1); + sample_print("term:", indent+1); + sample_traverser(term.get_expr(), indent+2); + } + } +} + + +sample_traverser: (exprs: meta::expression_list, indent: i32) = +{ + if exprs.is_empty() { + sample_print("()", indent); + } + else { + sample_print("(", indent); + for exprs.get_expressions() do (expr) { + sample_traverser(expr, indent+1); + } + sample_print(")", indent); + } +} + + +sample_traverser: (prefix: meta::prefix_expression, indent: i32) = +{ + ops := prefix.get_ops(); + + // If this has no additional ops, it's not a naked prefix expr, + // it's holding a lower grammar production so go traverse that + if ops.empty() { + sample_traverser(prefix.get_postfix_expression(), indent); + } + + // Else we're at an actual prefix expression with ops + else { + sample_print("prefix expression", indent); + + for ops do (op) { + sample_print("op: (op)$", indent+1); + } + + sample_print("expression", indent+1); + sample_traverser(prefix.get_postfix_expression(), indent+2); + } +} + + +sample_traverser: (postfix: meta::postfix_expression, indent: i32) = +{ + terms := postfix.get_terms(); + + // If this has no additional terms, it's not a naked postfix expr, + // it's holding a lower grammar production so go traverse that + if terms.empty() { + sample_traverser(postfix.get_primary_expression(), indent); + } + + // Else we're at an actual postfix expression with ops + else { + sample_print("postfix expression", indent); + + sample_print("expression", indent+1); + sample_traverser(postfix.get_primary_expression(), indent+2); + + for terms do (term) { + sample_print("op: (term.get_op())$", indent+1); + if term.is_id_expression() { + sample_traverser(term.get_id_expression(), indent+1); + } + else if term.is_expression_list() { + sample_traverser(term.get_expression_list(), indent+1); + } + else if term.is_expression() { + sample_traverser(term.get_expression(), indent+1); + } + } + } +} + + +sample_traverser: (uid: meta::unqualified_id, indent: i32) = +{ + if uid.is_identifier() { + sample_print(uid.get_identifier(), indent); + } + else { + sample_print(uid.to_string(), indent+1); + } +} + + +sample_traverser: (qid: meta::qualified_id, indent: i32) = +{ + (copy first := true) + for qid.get_terms() + do (term) + { + if !first { + sample_print("op: (term.get_op())$", indent+1); + } + first = false; + sample_print("unqualified:", indent+1); + sample_traverser(term.get_unqualified(), indent+2); + } +} + + +sample_traverser: (tid: meta::type_id, indent: i32) = +{ + if tid.is_postfix_expression() { + sample_traverser(tid.as_postfix_expression(), indent); + } + else if tid.is_qualified_id() { + sample_traverser(tid.as_qualified_id(), indent); + } + else if tid.is_unqualified_id() { + sample_traverser(tid.as_unqualified_id(), indent); + } + else { + sample_print(tid.to_string(), indent); + } +} + + +sample_traverser: (primary: meta::primary_expression, indent: i32) = +{ + if primary.is_identifier() { + sample_print(primary.as_identifier(), indent+1); + } + else if primary.is_expression_list() { + sample_traverser(primary.as_expression_list(), indent+1); + } + else if primary.is_literal() { + sample_print(primary.as_literal(), indent+1); + } + else if primary.is_declaration() { + sample_traverser(primary.as_declaration(), indent+1); + } + else { + sample_print(primary.to_string(), indent+1); + } +} + + +sample_traverser: (idexpr: meta::id_expression, indent: i32) = +{ + if idexpr.is_identifier() { + sample_print(idexpr.as_identifier(), indent+1); + } + else if idexpr.is_qualified() { + sample_traverser(idexpr.as_qualified(), indent+1); + } + else if idexpr.is_unqualified() { + sample_traverser(idexpr.as_unqualified(), indent+1); + } + else { + sample_print(idexpr.to_string(), indent+1); + } +} + + +//----------------------------------------------------------------------- +// +// autodiff +// + +autodiff_special_func: type = { + public name : std::string; + public n_args : int; + public is_member : bool; + + public code_primal : std::string; + public code_fwd : std::string; + public code_rws : std::string; + public code_primal_higher_order: std::string; + public code_fwd_higher_order : std::string; + public code_rws_higher_order : std::string; + + operator=: (out this, name_: std::string, n_args_: int, is_member_: bool, code_primal_: std::string = "", code_fwd_: std::string = "", + code_rws_: std::string = "", code_primal_higher_order_: std::string = "", code_fwd_higher_order_: std::string = "", + code_rws_higher_order_: std::string = "") = { + name = name_; + n_args = n_args_; + is_member = is_member_; + + code_primal = code_primal_; + code_fwd = code_fwd_; + code_rws = code_rws_; + code_primal_higher_order = code_primal_higher_order_; + code_fwd_higher_order = code_fwd_higher_order_; + code_rws_higher_order = code_rws_higher_order_; + + if code_primal_higher_order.empty() { + code_primal_higher_order = code_primal; + } + if code_fwd_higher_order.empty() { + code_fwd_higher_order = code_fwd; + } + if code_rws_higher_order.empty() { + code_rws_higher_order = code_rws; + } + } + + operator=: (out this, that) = {} // Default copy. + + is_match: (this, o: autodiff_special_func) -> bool = { + return name == o.name && n_args == o.n_args && is_member == o.is_member; + } +} + +autodiff_declared_variable: @copy_constructible type = { + public name : std::string = ""; + public decl : std::string = ""; // TODO: Maybe use variant here. + public is_active: bool = false; + public is_member: bool = false; + + operator=:(out this) = {} + + operator=:(out this, name_: std::string, decl_: std::string, is_active_: bool, is_member_: bool) = { + name = name_; + decl = decl_; + is_active = is_active_; + is_member = is_member_; + } + + operator=:(out this, that) = {} +} + +autodiff_declaration_stack_item: @copy_constructible type = { + public full_name: std::string; // namespace + type name + public decl: meta::type_or_namespace_declaration; + + public diff_request: std::vector = (); + public diff_done: std::vector = (); + + public declared_variables_stack: std::vector> = (1); + + operator=: (out this, full_name_: std::string, decl_: meta::type_or_namespace_declaration) = { + full_name = full_name_; + decl = decl_; + } + + lookup_declaration: (this, decl_name: std::string) -> (r: std::vector = ()) = { + for decl.get_members() do (cur) { + if cur.has_name() && decl_name == cur.name() { + r.push_back(cur); + + // Do not break for overloads. <3 + } + } + } + + lookup_variable_declaration: (this, decl_name: std::string) -> (found: bool = false, r: autodiff_declared_variable = ()) = { + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + (copy cur_context := declared_variables_stack.rbegin()) + while cur_context != declared_variables_stack.rend() + next cur_context++ + { + for cur_context* do (cur) { + if cur.name == decl_name { + found = true; + r = cur; + return; + } + } + } + } + + +} + +autodiff_context: type = { + private temporary_count : int = 0; + + // Code in special function is replaced. Placeholders are: + // _o_ : name of object for member functions. + // _o_ : name of derivative object for member functions. + // _a1_ : First argument value + // _ad1_: First derivative argument value + // _a2_ : Second argument value + // _ad2_: Second derivative argument value + public special_funcs : std::vector = ( + autodiff_special_func("sin", 1, /* is_member = */ false, + "sin(_a1_)", + "cos(_a1_) * _ad1_", + "_ab1_ += cos(_a1_) * _rb_;\n", + "sin(_a1_)", + "_ad1_.sin(_a1_)", + "TODO", + + ), + autodiff_special_func("cos", 1, /* is_member = */ false, + "cos(_a1_)", + "-sin(_a1_) * _ad1_", + "_ab1_ += -sin(_a1_) * _rb_;\n", + "cos(_a1_)", + "_ad1_.cos(_a1_)", + "TODO", + ), + autodiff_special_func("exp", 1, /* is_member = */ false, + "exp(_a1_)", + "exp(_a1_) * _ad1_", + "_ab1_ += exp(_a1_) * _rb_;\n", + "exp(_a1_)", + "_ad1_.exp(_a1_)", + "TODO", + ), + autodiff_special_func("sqrt", 1, /* is_member = */ false, + "sqrt(_a1_)", + "0.5 * _ad1_ / sqrt(_a1_)", + "_ab1_ += 0.5 * _rb_ / sqrt(_a1_);\n", + "sqrt(_a1_)", + "_ad1_.sqrt(_a1_)", + "TODO", + ), + autodiff_special_func("push_back", 1, /* is_member = */ true, + "_o_.push_back(_a1_);", + "_od_.push_back(_ad1_);", + "TODO") + ); + + public fwd_suffix : std::string = "_d"; + public rws_suffix : std::string = "_b"; + private order : int = 1; + public reverse: bool = false; + + // Members depending on order + public fwd_ad_type: std::string = "double"; + public rws_ad_type: std::string = "double"; + + public declaration_map : std::map> = (); + public declaration_stack: std::vector = (); + + operator=:(out this) = {} + operator=:(out this, order_: int, reverse_: bool) = { + order = order_; + reverse = reverse_; + + if 1 != order { + if reverse { + fwd_ad_type = "cpp2::taylor"; + rws_ad_type = "cpp2::taylor"; + } + else { + fwd_ad_type = "cpp2::taylor"; + } + } + + } + + add_variable_declaration: (inout this, name: std::string, type: std::string, is_active: bool, is_member: bool = false) = { + declaration_stack.back().declared_variables_stack.back().push_back(autodiff_declared_variable(name, type, is_active, is_member)); + } + + is_variable_active: (inout this, name: std::string) -> bool = { + return lookup_variable_declaration(name).is_active; + } + + create_namespace_stack: (inout this, t: meta::type_or_namespace_declaration) = { + if t.parent_is_nonglobal_namespace() { + create_namespace_stack(t.get_parent().as_nonglobal_namespace()); + } + else if t.parent_is_type() { + create_namespace_stack(t.get_parent().as_type()); + } + + full_name: std::string = "::"; + if !declaration_stack.empty() { + full_name = declaration_stack.back().full_name + "::"; + } + full_name += t.name(); + + _ = declaration_stack.push_back(autodiff_declaration_stack_item(full_name, t)); + } + + is_forward: (this) = !reverse || (reverse && order != 1); + is_reverse: (this) = reverse; + is_taylor : (this) = order != 1; + + gen_temporary : (inout this) -> std::string = { + temporary_count += 1; + return "temp_(temporary_count)$"; + } + + is_type_active: (inout this, type: std::string) -> bool = { + decls := lookup_type_declaration(type); + r := false; + + if !decls.empty() { + assert(decls.ssize() == 1); + ada: autodiff_activity_check = (this&); + ada.pre_traverse(decls[0]); + r = ada.active; + } + + // TODO: Add template activity lookup. + + if !r { + // Declaration lookup did not yield an activity: Apply some heuristics. + r = type.contains("double"); + } + + return r; + } + + get_fwd_ad_type: (inout this, type: std::string) -> std::string = { + type_d := type; + + if "double" != type { + type_decls := lookup_type_declaration(type); + if !type_decls.empty() { + // We found a cpp2 type declaration, mark it for differentiation. + add_for_differentiation(type_decls[0]); + + // Add the AD suffix to the type + type_d += fwd_suffix; + } + } + + // Replace with AD type for the AD order. + return string_util::replace_all(type_d, "double", fwd_ad_type); + } + + get_rws_ad_type: (inout this, type: std::string) -> std::string = { + type_d := type; + + if "double" != type { + type_decls := lookup_type_declaration(type); + if !type_decls.empty() { + // We found a cpp2 type declaration, mark it for differentiation. + add_for_differentiation(type_decls[0]); + + // Add the AD suffix to the type + type_d += rws_suffix; + } + } + + // Replace with AD type for the AD order. + return string_util::replace_all(type_d, "double", rws_ad_type); + } + + get_reverse_passing_style: (this, p: passing_style) -> passing_style = { + // TODO: inspect does not work here: error: error: no matching function for call to ‘is(const cpp2::passing_style&)’ + // return inspect p -> passing_style { + // is passing_style::in = passing_style::inout; + // is passing_style::in_ref = passing_style::inout; + // is passing_style::copy = passing_style::inout; + // is passing_style::inout = passing_style::inout; + // is passing_style::out = passing_style::inout; + // is passing_style::move = passing_style::inout; + // is passing_style::forward = passing_style::inout; + // is passing_style::forward_ref = passing_style::inout; + // is _ = passing_style::inout; + // }; + if p == passing_style::in { return passing_style::inout; } + if p == passing_style::in_ref { return passing_style::inout; } + if p == passing_style::copy { return passing_style::inout; } + if p == passing_style::inout { return passing_style::inout; } + if p == passing_style::out { return passing_style::inout; } + if p == passing_style::move { return passing_style::inout; } + if p == passing_style::forward { return passing_style::inout; } + if p == passing_style::forward_ref { return passing_style::inout; } + + + declaration_stack.back().decl.error("AD: Do not know how to handle passing style:(p)$"); + + return passing_style::inout; + } + + lookup_declaration: (inout this, decl_name: std::string) -> (r : std::vector = ()) = { + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + (copy cur := declaration_stack.rbegin()) + while cur != declaration_stack.rend() + next cur++ + { + cur_full_name : std::string = cur*.full_name + "::" + decl_name; + ele := declaration_map.find(cur_full_name); + if ele == declaration_map.end() { + ele = declaration_map.insert_or_assign(cur_full_name, cur*.lookup_declaration(decl_name)).first; + } + + if !ele*.second.empty() { + // A simple assignment or emplace_back did not work. It tired to use move copy operators. + for ele*.second do (cp) { + r.push_back(cp); + } + //r = ele*.second; + break; + // TODO: For overload resolution we may want to continue here and just add everything for all parent namespaces. + } + } + + return; + } + + lookup_variable_declaration: (inout this, name: std::string) -> autodiff_declared_variable = { + if name == "_" { + return autodiff_declared_variable(name, "_", false, false); + } + + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + (copy cur_context := declaration_stack.rbegin()) + while cur_context != declaration_stack.rend() + next cur_context++ + { + r := cur_context*.lookup_variable_declaration(name); + if r.found { + return r.r; + } + } + + declaration_stack.back().decl.error("AD: Could not find declaration of variable with name `(name)$`."); + + return autodiff_declared_variable(); + } + + lookup_function_declaration: (inout this, decl_name: std::string) -> (r : std::vector = ()) = { + r_all := lookup_declaration(decl_name); + + for r_all do (cur) { + if cur.is_function() { + r.push_back(cur.as_function()); + } + } + } + + lookup_member_function_declaration: (inout this, obj_type: meta::type_declaration, decl_name: std::string) -> (r : std::vector = ()) = { + for obj_type.get_members() do (cur) { + if cur.is_function() && cur.has_name() && decl_name == cur.name() { + r.push_back(cur.as_function()); + + // Do not break for overloads. <3 + } + } + } + + lookup_type_declaration: (inout this, decl_name: std::string) -> (r : std::vector = ()) = { + r_all := lookup_declaration(decl_name); + + for r_all do (cur) { + if cur.is_type() { + r.push_back(cur.as_type()); + } + } + } + + lookup_special_function_handling: (this, func_name: std::string, n_args: int, is_member: bool) -> (m: bool, code_primal: std::string, code_fwd: std::string, code_rws: std::string) = { + lookup : autodiff_special_func = (func_name, n_args, is_member); + + m = false; + code_primal = ""; + code_fwd = ""; + code_rws = ""; + for special_funcs do (func) { + if func.is_match(lookup) { + m = true; + if is_taylor() { + code_primal = func.code_primal_higher_order; + code_fwd = func.code_fwd_higher_order; + code_rws = func.code_rws_higher_order; + } + else { + code_primal = func.code_primal; + code_fwd = func.code_fwd; + code_rws = func.code_rws; + } + return; + } + } + } + + add_as_differentiated: (inout this, t: meta::declaration) = { + top := declaration_stack.back()&; + + assert(t.get_parent().is_same(top*.decl)); + + top*.diff_done.push_back(t); + } + + add_for_differentiation: (inout this, t: meta::declaration) = { + t_parent := t.get_parent(); + + found := false; + + // Note: Not using "for std::ranges::views::reverse(...)" because + // that does not work correctly in Clang 12 + older libstdc++ + (copy cur := declaration_stack.rbegin()) + while cur != declaration_stack.rend() + next cur++ + { + if t_parent.is_same(cur*.decl) { + if !is_in_list(t, cur*.diff_request) { + cur*.diff_request.push_back(t); + } + + found = true; + break; + } + } + + if !found { + t.error("AD: Could not find parent type/namespace for: (t)$"); + } + } + + is_in_list: (v: meta::declaration, list: std::vector) -> bool = { + for list do (cur) { + if cur.is_same(v) { + return true; + } + } + + return false; + } + + enter_function: (inout this) = { + temporary_count = 0; + declaration_stack.back().declared_variables_stack.push_back(std::vector()); + } + + leave_function: (inout this) = { + declaration_stack.back().declared_variables_stack.pop_back(); + } + + push_stack: (inout this, decl: meta::type_or_namespace_declaration) = { + full_name: std::string = ""; + + if !declaration_stack.empty() { + full_name += declaration_stack.back().full_name; + } + + full_name += "::"; + full_name += decl.name(); + + declaration_stack.push_back(autodiff_declaration_stack_item(full_name, decl)); + } + + pop_stack: (inout this) = { + assert(!declaration_stack.empty()); + + top := declaration_stack.back()&; + ad: autodiff_declaration_handler = (this&, top*.decl); + + for top*.diff_request do (cur) { + if !is_in_list(cur, top*.diff_done) { + ad.pre_traverse(cur); + } + } + + declaration_stack.pop_back(); + } + + finish: (inout this) = { + while !declaration_stack.empty() { + pop_stack(); + } + } +} + +autodiff_diff_code: type = { + public ctx: *autodiff_context; + + public fwd : std::string = ""; + public rws_primal : std::string = ""; + public rws_backprop: std::string = ""; + + operator=:(out this, ctx_: *autodiff_context) = { + ctx = ctx_; + } + operator=:(out this, that) = {} + + add_forward : (inout this, v: std::string) = { if ctx*.is_forward() { fwd += v; }} + add_reverse_primal : (inout this, v: std::string) = { if ctx*.is_reverse() { rws_primal += v; }} + add_reverse_backprop: (inout this, v: std::string) = { if ctx*.is_reverse() { rws_backprop = v + rws_backprop; }} + + reset: (inout this) = { + fwd = ""; + rws_primal = ""; + rws_backprop = ""; + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. + operator=:(inout this, v: std::string) = { + ctx = ctx; + fwd = v; + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. + operator+=: (inout this, v: std::string) = { + fwd += v; + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. + operator+=: (inout this, v: autodiff_diff_code) = { + fwd += v.fwd; + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. + empty: (this) -> bool = { + return fwd.empty(); + } +} + +// // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. +// to_string: (v: autodiff_diff_code) -> std::string = { +// return v.fwd; +// } + +autodiff_activity_check: type = { + this: simple_traverser = (); + + public ctx : *autodiff_context; + public active: bool = false; + + operator=: (out this, ctx_: *autodiff_context) = { + ctx = ctx_; + } + + traverse: (override inout this, t: meta::type_declaration) = { + for t.get_members() + do (m) + { + if m.is_object() || m.is_member_object() { + pre_traverse(m); + } + + // TODO: Maybe also add functions. + } + } + + traverse: (override inout this, o: meta::object_declaration) = { + + type := o.type(); + + if "_" == type { + if o.has_initializer() { + pre_traverse(o.get_initializer()); + } + else { + // Assume active + active = true; + } + } + else { + active |= ctx*.is_type_active(type); + } + } + + traverse: (override inout this, primary: meta::primary_expression) = + { + if primary.is_identifier() { + active |= ctx*.is_variable_active(primary.to_string()); + } + else if primary.is_expression_list() { + for primary.as_expression_list().get_expressions() do (cur) { + pre_traverse(cur); + } + } + else if primary.is_literal() { + // TODO: Improve check + if primary.to_string().contains(".") { + active = true; + } + } + else if primary.is_declaration() { + pre_traverse(primary.as_declaration()); + } + else { + primary.error("AD: Unknown primary expression kind: (primary.to_string())$"); + } + } + + traverse: (override inout this, postfix: meta::postfix_expression) = + { + terms := postfix.get_terms(); + + is_func := false; + + (copy i := 0) + for terms next i += 1 do (term) { + if term.get_op() == "." { + continue; + } + if term.get_op() == "(" && i + 1 == terms.ssize() { // Function operator has to be the last + is_func = true; + continue; + } + else { + postfix.error("AD: Unknown operator for postfix expression. op: (term.get_op())$ expr: (postfix)$"); + } + } + + // TODO: Really check for members + if !is_func || terms.ssize() != 1 { + active |= ctx*.is_variable_active(postfix.get_primary_expression().to_string()); + } + + if is_func { + // Check arguments of function + for terms.back().get_expression_list().get_expressions() do (cur) { + pre_traverse(cur); + } + } + } +} + +autodiff_handler_base: type = { + public ctx: *autodiff_context; + + public diff : autodiff_diff_code; + + operator=: (out this, ctx_: *autodiff_context) = { + ctx = ctx_; + diff = (ctx); + } + + // Temporary: TODO: remove when everything has been adapted to primal, fwd, rws pushes. + append: (inout this, in_ref o: autodiff_handler_base) = { + diff.fwd += o.diff.fwd; + diff.rws_primal += o.diff.rws_primal; + diff.rws_backprop = o.diff.rws_backprop + diff.rws_backprop; + } +} + +autodiff_expression_handler: type = { + this: simple_traverser = (); + this: autodiff_handler_base; + + base: type == simple_traverser; + + public primal_expr: std::string = ""; + public fwd_expr : std::string = ""; + public rws_expr : std::string = ""; + + operator=: (out this, ctx_: *autodiff_context) = { + autodiff_handler_base = (ctx_); + } + + add_suffix_if_not_wildcard: (this, lhs: std::string, suffix: std::string) -> std::string = { + if "_" == lhs { + return lhs; + } + else { + return lhs + suffix; + } + } + + prepare_backprop: (this, rhs_b: std::string, lhs: std::string, lhs_d: std::string, lhs_b: std::string) -> std::string = { + r := rhs_b; + r = string_util::replace_all(r, "_r_", lhs); + r = string_util::replace_all(r, "_rd_", lhs_d); + r = string_util::replace_all(r, "_rb_", lhs_b); + + return r; + } + prepare_backprop: (this, rhs_b: std::string, lhs: std::string) -> std::string = prepare_backprop(rhs_b, lhs, lhs + ctx*.fwd_suffix, lhs + ctx*.rws_suffix); + + gen_assignment: (inout this, lhs: std::string, lhs_d: std::string, lhs_b: std::string, rhs: std::string, rhs_d: std::string, rhs_b: std::string) = { + diff.add_forward("(lhs_d)$ = (rhs_d)$;\n"); + diff.add_forward("(lhs)$ = (rhs)$;\n"); + + if ctx*.is_taylor() { + diff.add_reverse_primal("(lhs_d)$ = (rhs_d)$;\n"); + } + diff.add_reverse_primal("(lhs)$ = (rhs)$;\n"); + diff.add_reverse_backprop("(lhs_b)$ = 0.0;\n"); + diff.add_reverse_backprop(prepare_backprop(rhs_b, lhs, lhs_d, lhs_b)); + } + gen_assignment: (inout this, lhs: std::string, lhs_d: std::string, lhs_b: std::string) + = gen_assignment(lhs, lhs_d, lhs_b, primal_expr, fwd_expr, rws_expr); + gen_assignment: (inout this, lhs: std::string) + = gen_assignment(lhs, add_suffix_if_not_wildcard(lhs, ctx*.fwd_suffix), add_suffix_if_not_wildcard(lhs, ctx*.rws_suffix), primal_expr, fwd_expr, rws_expr); + + + gen_declaration: (inout this, lhs: std::string, lhs_d: std::string, lhs_b: std::string, rhs: std::string, rhs_d: std::string, rhs_b: std::string, type: std::string, type_d: std::string, type_b: std::string) = { + diff.add_forward("(lhs_d)$: (type_d)$ = (rhs_d)$;\n"); + diff.add_forward("(lhs)$ : (type)$ = (rhs)$;\n"); + + if ctx*.is_taylor() { + diff.add_reverse_primal("(lhs_d)$: (type_d)$ = (rhs_d)$;\n"); + } + diff.add_reverse_primal("(lhs_b)$ : (type_b)$ = 0.0;\n"); + diff.add_reverse_primal("(lhs)$ : (type)$ = (rhs)$;\n"); + diff.add_reverse_backprop("(lhs_b)$ = 0.0;\n"); + diff.add_reverse_backprop(prepare_backprop(rhs_b, lhs, lhs_d, lhs_b)); + } + gen_declaration: (inout this, lhs: std::string, lhs_d: std::string, lhs_b: std::string, rhs: std::string, rhs_d: std::string, rhs_b: std::string, type: std::string) + = gen_declaration(lhs, lhs_d, lhs_b, rhs, rhs_d, rhs_b, type, ctx*.get_fwd_ad_type(type) , ctx*.get_rws_ad_type(type)); + gen_declaration: (inout this, lhs: std::string, lhs_d: std::string, lhs_b: std::string, type: std::string) + = gen_declaration(lhs, lhs_d, lhs_b, primal_expr, fwd_expr, rws_expr, type); + gen_declaration: (inout this, lhs: std::string, type: std::string) + = gen_declaration(lhs, lhs + ctx*.fwd_suffix, lhs + ctx*.rws_suffix, type); + + + + primal_fwd_rws_name: @struct type = { + primal: std::string = ""; + fwd : std::string = ""; + rws : std::string = ""; + active: bool = false; + } + + handle_expression_list: (inout this, list: meta::expression_list) -> std::vector = { + args : std::vector = (); + for list.get_expressions() do (expr) { + args.push_back(handle_expression_term(expr)); + } + + return args; + } + + handle_expression_term :(inout this, term) -> primal_fwd_rws_name = { + if term.is_identifier() { + primal := term.to_string(); + fwd := primal + ctx*.fwd_suffix; + rws := primal + ctx*.rws_suffix; + + decl := ctx*.lookup_variable_declaration(primal); + if decl.is_member { + fwd = "this(ctx*.fwd_suffix)$." + fwd; + rws = "this(ctx*.rws_suffix)$." + rws; + } + + if decl.is_active { + return (primal, fwd, rws, true); + } + else { + return (primal, "", "", false); + } + + } + else if term.is_expression_list() { + exprs := term..as_expression_list()..get_expressions(); + if exprs.ssize() != 1 { + term.error("Can not handle multiple expressions. (term.to_string())"); + return ("error", "", "", false); + } + expr := exprs[0]; + bin_expr := expr..as_assignment_expression(); + + if bin_expr.terms_size() != 0 { + term.error("Can not handle assign expr inside of expression. (expr.to_string())$"); + return ("error", "", "", false); + } + + return handle_expression_term(bin_expr.get_terms().front().get_term()); + } + else { + // Nothing special. A regular expression. + expr := term; + + ada: autodiff_activity_check = (ctx); + ada.pre_traverse(expr); + + if ada.active { + + ad : autodiff_expression_handler = (ctx); + ad..pre_traverse(expr); + t := ctx*.gen_temporary(); + ad.gen_declaration(t, "double"); // TODO: get type of expression + append(ad); + + r : primal_fwd_rws_name = (t, t + ctx*.fwd_suffix, t + ctx*.rws_suffix, true); // TODO: Check why on return (t, t + ctx*.fwd_suffix) the primal is initialized empty. Probably because of the move(t) + _ = t; + return r; + } + else { + return (expr.to_string(), "", "", false); + } + } + } + + handle_function_call: (inout this, postfix: meta::postfix_expression, has_return: bool) = { + terms := postfix.get_terms(); + + is_func := true; + + (copy i := 0) + for terms next i += 1 do (term) { + if term.get_op() == "." { + continue; + } + if term.get_op() == "(" && i + 1 == terms.ssize() { // Function operator has to be the last + continue; + } + + is_func = false; + } + + // Check for function call, everything else is not handled. + if !(is_func) { + postfix.error( "AD: Postfix expressions are only handled for function calls, or member function calls. Do not know how to handle: (postfix.to_string())$" ); + return; + } + + object : std::string = ""; + object_d : std::string = ""; + object_b : std::string = ""; + function_name : std::string = ""; + args : std::vector = (); + + primary := postfix.get_primary_expression(); + + if 1 != terms.ssize() { + object = primary.to_string(); + object_d = primary.to_string() + ctx*.fwd_suffix; + object_b = primary.to_string() + ctx*.rws_suffix; + } + else { + function_name = primary.to_string(); + } + + (copy i := 0) + for terms next i += 1 do (term) { + if term.get_op() == "." { + assert(term.is_id_expression()); + name := term.get_id_expression().to_string(); + + if i + 2 == terms.ssize() { // Second last term is function name, last term is function argument list + function_name = name; + } + else { + object += "." + name; + object_d += "." + name + ctx*.fwd_suffix; + } + } + else if term.get_op() == "(" { + assert(term.is_expression_list()); + + args = handle_expression_list(term.get_expression_list()); + } + else { + postfix.error("AD: Do not know how to handle postfix term: (term.to_string())$"); + } + } + + if handle_special_function(object, object_d, object_b, function_name, args) { + return; + } + + if object.contains(".") { + postfix.error("AD: can not handle nested member function calls: (postfix.to_string())$"); + return; + } + + call_primal: std::string = ""; + call_fwd : std::string = ""; + call_rws : std::string = ""; + + // All arguments have now been handled. Form the function call + ret_temp : std::string = ""; + if has_return { + ret_temp = ctx*.gen_temporary(); + call_fwd += "(ret_temp)$ := "; + } + + // TODO: This is untested for functions with no return value. Requires handling of out and inout parameters in functions. + if !object.empty() { // Prepend object call + call_primal += "(object)$."; + call_fwd += "(object)$."; + call_rws += "(object)$."; + } + call_primal += "(function_name)$("; + call_fwd += "(function_name)$(ctx*.fwd_suffix)$("; + call_rws += "(function_name)$(ctx*.rws_suffix)$("; + if !object.empty() { // Add this_d argument. + call_fwd += "(object_d)$, "; + call_rws += "(object_b)$, "; + } + for args do (arg) { + // TODO: Add taylor reverse handling. + call_primal += "(arg.primal)$, "; + call_fwd += "(arg.primal)$, "; + call_rws += "(arg.primal)$, "; + if arg.active { + call_fwd += "(arg.fwd)$, "; + call_rws += "(arg.rws)$, "; + } + } + + if has_return { + functions : std::vector = (); + if !object.empty() { + obj_decl := ctx*.lookup_variable_declaration(object); + obj_decl_types := ctx*.lookup_type_declaration(obj_decl.decl); + + if obj_decl_types.empty() { + postfix.error("AD: Could not find type declaration for `(object)$ with type (obj_decl.decl)$`.\n" + " If cpp2 object: this is an alpha limitation, please declare it befor the current declaration.\n" + " If cpp function: please add a special handling for this member function."); + return; + } + functions = ctx*.lookup_member_function_declaration(obj_decl_types[0], function_name); + + ctx*.add_for_differentiation(obj_decl_types[0]); // TODO: Add more fine grained differentiation. + } + else { + functions = ctx*.lookup_function_declaration(function_name); + if functions.ssize() == 0 { + postfix.error("AD: Could not find function declaration for `(function_name)$`.\n" + " If cpp2 function: this is an alpha limitation, please declare it befor the current declaration.\n" + " If cpp function: please add a special handling for this function."); + return; + } + else if functions.ssize() != 1 { + postfix.error("AD: No handling for overload resultion is currently implemented."); + return; + } + + ctx*.add_for_differentiation(functions[0]); + } + + ret_name : std::string = "r"; // Default for regular return. + returns := functions[0].get_returns(); + if !returns.empty() { + if returns.ssize() != 1 { + postfix.error("AD: Expecting single return."); + } + + for returns do (cur) { + ret_name = cur.get_declaration().name(); + } + } + + ret_name_d : std::string = ret_name + ctx*.fwd_suffix; + ret_name_b : std::string = ret_name + ctx*.rws_suffix; + + call_rws += "_rb_, "; + + call_primal += ")"; + call_fwd += ");\n"; + call_rws += ");\n"; + + diff.add_forward(call_fwd); + + primal_expr = call_primal; + fwd_expr = "(ret_temp)$.(ret_name_d)$"; + rws_expr = "_ = (call_rws)$"; + } + else { + call_primal += ");\n"; + call_fwd += ");\n"; + call_rws += ");\n"; + + diff.add_forward(call_fwd); + diff.add_reverse_primal(call_primal); + diff.add_reverse_backprop(call_rws); + } + + // TODO: Add function to list of functions/objects for differentiation for the no return case. + } + + handle_special_function: (inout this, object: std::string, object_d: std::string, object_b: std::string, function_name: std::string, args: std::vector) -> bool = { + + r := ctx*.lookup_special_function_handling(function_name, unchecked_narrow(args.ssize()), !object.empty()); + + if !r.m { + return false; // No match + } + + // Have a match, do the replacement + code_primal: std::string = r.code_primal; + code_fwd : std::string = r.code_fwd; + code_rws : std::string = r.code_rws; + + if !object.empty() { + code_primal = string_util::replace_all(code_primal, "_o_", object); + code_primal = string_util::replace_all(code_primal, "_od_", object_d); + + code_fwd = string_util::replace_all(code_fwd, "_o_", object); + code_fwd = string_util::replace_all(code_fwd, "_od_", object_d); + + code_rws = string_util::replace_all(code_fwd, "_o_", object); + code_rws = string_util::replace_all(code_rws, "_od_", object_d); + code_rws = string_util::replace_all(code_fwd, "_ob_", object_b); + } + + (copy i := 1) + for args do (arg) { + code_primal = string_util::replace_all(code_primal, "_a(i)$_", arg.primal); + code_primal = string_util::replace_all(code_primal, "_ad(i)$_", arg.fwd); + + code_fwd = string_util::replace_all(code_fwd, "_a(i)$_", arg.primal); + code_fwd = string_util::replace_all(code_fwd, "_ad(i)$_", arg.fwd); + + code_rws = string_util::replace_all(code_rws, "_a(i)$_", arg.primal); + code_rws = string_util::replace_all(code_rws, "_ad(i)$_", arg.fwd); + code_rws = string_util::replace_all(code_rws, "_ab(i)$_", arg.rws); + } + + primal_expr = code_primal; + fwd_expr = code_fwd; + rws_expr = code_rws; + + return true; + } + + traverse: (override inout this, expr: meta::expression) = { + base::traverse(expr); + } + + traverse: (override inout this, binexpr: meta::assignment_expression) = { + binexpr.error( "AD: Assign expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::logical_or_expression) = { + binexpr.error( "AD: Logical or expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::logical_and_expression) = { + binexpr.error( "AD: Logical and expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::bit_or_expression) = { + binexpr.error( "AD: Bit or expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::bit_xor_expression) = { + binexpr.error( "AD: Bit xor expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::bit_and_expression) = { + binexpr.error( "AD: Bit and expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::equality_expression) = { + binexpr.error( "AD: Equality or expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::relational_expression) = { + binexpr.error( "AD: Relational expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::compare_expression) = { + binexpr.error( "AD: Compare or expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::shift_expression) = { + binexpr.error( "AD: Shift or expressions are not yet handled." ); + } + + traverse: (override inout this, binexpr: meta::additive_expression) = { + terms := binexpr.get_terms(); + + first := true; + first_fwd := true; + op : std::string = "+"; + fwd : std::string = ""; + rws : std::string = ""; + primal: std::string = ""; + for terms do (term) { + if !first { + op = term.get_op().to_string(); + primal += " (op)$ "; + } + + var := handle_expression_term(term.get_term()); + if var.active { + if first_fwd { + if op == "-" {// Special handling for first fwd termn with minus + fwd += "-(var.fwd)$"; + } + else { // Special handling for first fwd term with plus + fwd += var.fwd; + } + } + else { + fwd += "(op)$ (var.fwd)$"; + } + rws += "(var.rws)$ (op)$= _rb_;\n"; + + first_fwd = false; + } + primal += var.primal; + + first = false; + } + + primal_expr = primal; + fwd_expr = fwd; + rws_expr = rws; + } + + traverse: (override inout this, binexpr: meta::multiplicative_expression) = { + terms := binexpr.get_terms(); + + var_a := handle_expression_term(terms[0].get_term()); + + i : int = 1; + while i < terms.ssize() next i += 1 { + var_b := handle_expression_term(terms[i].get_term()); + + op := terms[i].get_op().to_string(); + + fwd : std::string = ""; + rws : std::string = ""; + primal : std::string = ""; + + if "*" == op { + if ctx*.is_taylor() { + // TODO: Add taylor overloads + fwd = "(var_a.fwd)$..mul((var_b.fwd)$, (var_a.primal)$, (var_b.primal)$)"; + if var_a.active { + //fwd += "(var_b.primal)$ * (var_a.fwd)$"; + rws += "(var_a.rws)$ += (var_b.fwd)$..mul(_rb_, (var_b.primal)$, _r_);\n"; + } + if var_b.active { + //if !fwd.empty() { fwd += " + "; } + //fwd += "(var_a.primal)$ * (var_b.fwd)$"; + rws += "(var_b.rws)$ += (var_a.fwd)$..mul(_rb_, (var_a.primal)$, _r_);\n"; + } + } + else { + if var_a.active { + fwd += "(var_b.primal)$ * (var_a.fwd)$"; + rws += "(var_a.rws)$ += (var_b.primal)$ * _rb_;\n"; + } + if var_b.active { + if !fwd.empty() { fwd += " + "; } + fwd += "(var_a.primal)$ * (var_b.fwd)$"; + rws += "(var_b.rws)$ += (var_a.primal)$ * _rb_;\n"; + } + } + primal = "(var_a.primal)$ * (var_b.primal)$"; + } + else if "/" == op { + if ctx*.is_taylor() { + // TODO: Add taylor overloads + fwd = "(var_a.fwd)$.div((var_b.fwd)$, (var_a.primal)$, (var_b.primal)$)"; + if var_a.active { + rws += "(var_a.rws)$ += _rb_.div((var_b.fwd)$, _r_, (var_b.primal)$);\n"; + } + if var_b.active { + rws += "(var_b.rws)$ -= (var_a.fwd)$.mul(_rb_, (var_a.primal)$, _r_).div((var_b.fwd)$.mul((var_b.fwd)$, (var_b.primal)$, (var_b.primal)$), (var_a.primal)$ * _r_, (var_b.primal)$ * (var_b.primal)$);\n"; + } + } + else { + if var_a.active { + fwd += "(var_a.fwd)$ / (var_b.primal)$"; + rws = "(var_a.rws)$ += _rb_ / (var_b.primal)$;\n"; + } + if var_b.active { + if !fwd.empty() { fwd += " + "; } + fwd += "-(var_a.primal)$ * (var_b.fwd)$ / ((var_b.primal)$ * (var_b.primal)$)"; + rws += "(var_b.rws)$ -= (var_a.primal)$ * _rb_ / ((var_b.primal)$ * (var_b.primal)$);\n"; + } + } + primal = "(var_a.primal)$ / (var_b.primal)$"; + } + else { + binexpr.error( "unkown multiplicative operator '(op)$'"); + } + + + if i + 1 == terms.ssize() { + primal_expr = primal; + fwd_expr = fwd; + rws_expr = rws; + } + else { + // Temporary + var_a.primal = ctx*.gen_temporary(); + var_a.fwd = var_a.primal + ctx*.fwd_suffix; + var_a.rws = var_a.primal + ctx*.rws_suffix; + var_a.active = var_a.active | var_b.active; + gen_declaration(var_a.primal, var_a.fwd, var_a.rws, primal, fwd, rws, "", "", ""); + } + } + } + + traverse: (override inout this, isas: meta::is_as_expression) = { + isas.error( "AD: Is as expressions are not yet handled." ); + } + + traverse: (override inout this, prefix: meta::prefix_expression) = + { + ops := prefix.get_ops(); + + if ops.ssize() != 1 { + prefix.error( "AD: Can only handle one prefix operation. Expression is: (prefix.to_string())$" ); + } + + ad: autodiff_expression_handler = (ctx); + ad.pre_traverse(prefix.get_postfix_expression()); + append(ad); + + primal_expr = ops[0] + ad.primal_expr; + fwd_expr = ops[0] + ad.fwd_expr; + } + + traverse: (override inout this, postfix: meta::postfix_expression) = + { + terms := postfix.get_terms(); + + is_func := false; + + (copy i := 0) + for terms next i += 1 do (term) { + if term.get_op() == "." { + continue; + } + if term.get_op() == "(" && i + 1 == terms.ssize() { // Function operator has to be the last + is_func = true; + continue; + } + else { + postfix.error("AD: Unknown operator for postfix expression. op: (term.get_op())$ expr: (postfix)$"); + } + } + + if is_func { + handle_function_call(postfix, true); + } + else { + // Member access + + primary : = postfix.get_primary_expression(); + obj_access : std::string = primary.to_string(); + obj_access_d : std::string = obj_access + ctx*.fwd_suffix; + + for terms do (term) { + obj_access += term.get_op() + term.get_id_expression().to_string(); + obj_access_d += term.get_op() + term.get_id_expression().to_string() + ctx*.fwd_suffix; + } + + primal_expr = obj_access; + fwd_expr = obj_access_d; + } + } + + traverse: (override inout this, primary: meta::primary_expression) = + { + if primary.is_identifier() { + primal_expr = primary.to_string(); + fwd_expr = add_suffix_if_not_wildcard(primal_expr, ctx*.fwd_suffix); + rws_expr = add_suffix_if_not_wildcard(primal_expr, ctx*.rws_suffix); + + decl := ctx*.lookup_variable_declaration(primal_expr); + if decl.is_member { + fwd_expr = "this(ctx*.fwd_suffix)$." + fwd_expr; + rws_expr = "this(ctx*.rws_suffix)$." + rws_expr; + } + } + else if primary.is_expression_list() { + if primary.as_expression_list().is_empty() { + primal_expr = "()"; + fwd_expr = "()"; + rws_expr = "()"; // TODO: Check for reverse + } + else { + primary.error("AD: Do not know how to handle non empty expression list inside of primary_expression: (primary.to_string())$"); + } + } + else if primary.is_literal() { + primal_expr = primary.to_string(); + fwd_expr = "()"; + rws_expr = "()"; // TODO: Check for reverse + } + else if primary.is_declaration() { + primary.error("AD: Do not know how to handle declaration inside of primary_expression: (primary.to_string())$"); + } + else { + primary.error("AD: Unknown primary expression kind: (primary.to_string())$"); + } + } +} + +autodiff_stmt_handler: type = { + this: simple_traverser = (); + this: autodiff_handler_base; + + base: type == simple_traverser; + + mf: meta::function_declaration; + + last_params: std::vector = (); + overwritten: std::vector = (); + + overwrite_push_pop: bool = false; + + operator=: (out this, ctx_: *autodiff_context, mf_: meta::function_declaration) = { + autodiff_handler_base = (ctx_); + mf = mf_; + } + + handle_stmt_parameters: (inout this, params: std::vector) -> autodiff_diff_code = { + r : autodiff_diff_code = (ctx); + if params.empty() { + return r; + } + + for params do (param) { + name: std::string = param.get_declaration().name(); + type: std::string = param.get_declaration().type(); + + fwd_pass_style := to_string_view(param.get_passing_style()); + + ada: autodiff_activity_check = (ctx); + ada.pre_traverse(param); + + init : std::string = ""; + init_d: std::string = ""; + // TODO: Add handling for reverse expressions + + if param.get_declaration().has_initializer() { + ad: autodiff_expression_handler = (ctx); + ad.pre_traverse(param.get_declaration().get_initializer()); + init = " = (ad.primal_expr)$"; + + if ada.active { + init_d = " = (ad.fwd_expr)$"; + } + } + + + r.add_forward("(fwd_pass_style)$ (name)$ : (type)$(init)$, "); + r.add_reverse_primal("(fwd_pass_style)$ (name)$ : (type)$(init)$, "); + if ada.active { + r.add_forward("(fwd_pass_style)$ (name)$(ctx*.fwd_suffix)$ : (ctx*.get_fwd_ad_type(type))$(init_d)$, "); + } + + ctx*.add_variable_declaration(name, type, ada.active); + } + + return r; + } + + traverse: (override inout this, decl: meta::declaration) = { + base::traverse(decl); + } + + + traverse: (override inout this, f: meta::function_declaration) = { + f.error("AD: Do not know how to handle function_declaration: (f.to_string())$"); + } + + + traverse: (override inout this, o: meta::object_declaration) = { + lhs : std::string = o.name(); + type : = o.type(); + + active := false; + if "_" != type { + active = ctx*.is_type_active(type); + } + else { + assert(o.has_initializer()); + + ada: autodiff_activity_check = (ctx); + ada.pre_traverse(o.get_initializer()); + active = ada.active; + } + + if active { + + fwd_ad_type : = ctx*.get_fwd_ad_type(type); + rws_ad_type : = ctx*.get_rws_ad_type(type); + + prim_init: std::string = ""; + fwd_init : std::string = ""; + rws_init : std::string = ""; + + if o.has_initializer() { + ad: autodiff_expression_handler = (ctx); + ad.pre_traverse(o.get_initializer()); + append(ad); + + prim_init = " = " + ad.primal_expr; + fwd_init = " = " + ad.fwd_expr; + rws_init = " = ()"; // TODO: Proper initialization. + + if ad.rws_expr != "()" { + diff.add_reverse_backprop(ad.prepare_backprop(ad.rws_expr, lhs)); + } + + if type == "_" && ad.fwd_expr == "()" { + // Special handling for auto initialization from a literal. + fwd_init = " = " + ctx*.get_fwd_ad_type("double") + "()"; + } + } + + diff.add_forward("(lhs)$(ctx*.fwd_suffix)$ : (fwd_ad_type)$(fwd_init)$;\n"); + diff.add_forward("(lhs)$ : (type)$(prim_init)$;\n"); + + diff.add_reverse_primal("(lhs)$(ctx*.rws_suffix)$ : (rws_ad_type)$(rws_init)$;\n"); + diff.add_reverse_primal("(lhs)$ : (type)$(prim_init)$;\n"); + } + else { + diff += "(lhs)$: (type)$"; + if o.has_initializer() { + diff += " = (o.get_initializer().to_string())$"; + } + diff += ";\n"; + } + + ctx*.add_variable_declaration(lhs, type, active); + } + + + traverse: (override inout this, t: meta::type_declaration) = { + t.error("AD: Do not know how to handle type_declaration: (t.to_string())$"); + } + + + traverse: (override inout this, t: meta::parameter_declaration) = { + t.error("AD: Do not know how to handle parameter_declaration: (t.to_string())$"); + } + + + traverse: (override inout this, stmt: meta::statement) = { + // TODO: Remove this hack when statements like compound_statement can access their root statement. + last_params = stmt.get_parameters(); + base::traverse(stmt); + } + + + traverse: (override inout this, stmt: meta::compound_statement) = { + ad : autodiff_stmt_handler = (ctx, mf); + ad_push_pop: autodiff_stmt_handler = (ctx, mf); + ad_push_pop.overwrite_push_pop = true; + + diff.add_forward("{\n"); + diff.add_reverse_primal("{\n"); + diff.add_reverse_backprop("}\n"); + + for stmt.get_statements() do (cur) { + ad.pre_traverse(cur); + ad_push_pop.pre_traverse(cur); + } + + for ad.overwritten do (cur) { + r := ctx*.lookup_variable_declaration(cur); + diff.add_reverse_primal("cpp2::ad_stack::push<(r.decl)$>((cur)$);"); + } + + diff.add_forward(ad.diff.fwd); + diff.add_reverse_primal(ad.diff.rws_primal); + diff.add_reverse_backprop(ad_push_pop.diff.rws_backprop); + diff.add_reverse_backprop(ad_push_pop.diff.rws_primal); + + for ad.overwritten do (cur) { + r := ctx*.lookup_variable_declaration(cur); + diff.add_reverse_backprop("(cur)$ = cpp2::ad_stack::pop<(r.decl)$>();"); + } + + diff.add_forward("}\n"); + diff.add_reverse_primal("}\n"); + diff.add_reverse_backprop("{\n"); + } + + + traverse: (override inout this, stmt: meta::return_statement) = { + if stmt.has_expression() { + // Return with expression. + // TODO: Remove assumptions + // - Return expression is always active. (Look this up in mf or so.) + // - Return was converted to a two parameter return with the name r. + ad: autodiff_expression_handler = (ctx); + ad..pre_traverse(stmt.get_expression()); + ad.gen_assignment("r",); + append(ad); + } + else { + diff += "return;\n"; + } + } + + reverse_next: (this, expr: std::string) -> std::string = { + if expr.contains("+=") { + return string_util::replace_all(expr, "+=", "-="); + } + else if expr.contains("-=") { + return string_util::replace_all(expr, "-=", "+="); + } + + mf.error("AD: Do not know how to reverse: (expr)$"); + + return "Error"; + + } + + + traverse: (override inout this, stmt: meta::iteration_statement) = { + diff_params := handle_stmt_parameters(last_params); + + if ctx*.is_reverse() && (stmt.is_while() || stmt.is_do()) { + stmt.error("AD: Alpha limitiation now reverse mode for while or do while."); + } + + if stmt.is_while() { + if !last_params.empty() { + diff.add_forward("(" + diff_params.fwd + ")"); + } + // TODO: Assumption is here that nothing is in the condition + diff += "while (stmt.get_do_while_condition().to_string())$ "; + if stmt.has_next() { + // TODO: Assumption is here that nothing is in the next expression + diff += "next (stmt.get_next_expression().to_string())$ "; + } + + pre_traverse(stmt.get_do_while_body()); + } + else if stmt.is_do() { + if !last_params.empty() { + diff.add_forward("(" + diff_params.fwd + ")"); + } + + // TODO: Assumption is here that nothing is in the condition + diff += "do "; + pre_traverse(stmt.get_do_while_body()); + + if stmt.has_next() { + // TODO: Assumption is here that nothing is in the next expression + diff += "next (stmt.get_next_expression().to_string())$ "; + } + diff += "while (stmt.get_do_while_condition().to_string())$;"; + } + else { + assert(stmt.is_for()); + // No zip view available in cpp 20 do a piggy back for range + + // TODO: Assumption that this is just an id expression. + range := stmt.get_for_range().to_string(); + + param := stmt.get_for_parameter(); + param_style := to_string_view(param.get_passing_style()); + param_decl := param.get_declaration(); + + rws : std::string = "("; + rws_restore: std::string = ""; + diff.add_forward("("); // Open statment parameter scope. If the loop has parameters, they are alrady handled and the brace is left open. + diff.add_reverse_primal("{\n"); + if !last_params.empty() { + for last_params do (cur) { + if cur.get_declaration().has_initializer() { + // TODO: Handle no type and no initializer. Handle passing style. + diff.add_reverse_primal("(cur.get_declaration().name())$: (cur.get_declaration().type())$ = (cur.get_declaration().get_initializer().to_string())$;\n"); + rws_restore += "cpp2::ad_stack::push<(cur.get_declaration().type())$>((cur.get_declaration().name())$);\n"; + rws += "(to_string_view(cur.get_passing_style()))$ (cur.get_declaration().name())$: (cur.get_declaration().type())$ = cpp2::ad_stack::pop<(cur.get_declaration().type())$>(), "; + } + } + diff.add_forward(diff_params.fwd); + } + diff.add_forward("copy (param_decl.name())$(ctx*.fwd_suffix)$_iter := (range)$(ctx*.fwd_suffix)$.begin())\n"); + diff.add_forward("for (range)$ next ("); + + rws += "copy (param_decl.name())$(ctx*.rws_suffix)$_iter := (range)$(ctx*.rws_suffix)$.rbegin())\n"; + rws += "for std::ranges::reverse_view((range)$) next ("; + diff.add_reverse_primal("for (range)$ next ("); + if stmt.has_next() { + // TODO: Assumption is here that nothing is in the next expression + diff.add_forward("(stmt.get_next_expression().to_string())$, "); + diff.add_reverse_primal("(stmt.get_next_expression().to_string())$, "); + rws += "(reverse_next(stmt.get_next_expression().to_string()))$, "; + } + diff.add_forward("(param_decl.name())$(ctx*.fwd_suffix)$_iter++"); + diff.add_forward(") do ((param_style)$ (param_decl.name())$: (param_decl.type())$) {\n"); + rws += "(param_decl.name())$(ctx*.rws_suffix)$_iter++"; + rws += ") do ((param_style)$ (param_decl.name())$: (param_decl.type())$) {\n"; + rws += "(inout (param_decl.name())$(ctx*.rws_suffix)$ := (param_decl.name())$(ctx*.rws_suffix)$_iter*)\n"; + + diff.add_reverse_primal(") do ((param_style)$ (param_decl.name())$: (param_decl.type())$)"); + diff.add_forward("((param_style)$ (param_decl.name())$(ctx*.fwd_suffix)$: (param_decl.type())$ = (param_decl.name())$(ctx*.fwd_suffix)$_iter*)"); + + ctx*.add_variable_declaration("(param_decl.name())$", "(param_decl.type())$", true); // TODO: Handle loop/compound context variable declarations. + diff.add_reverse_backprop("}\n"); + + pre_traverse(stmt.get_for_body()); + diff.add_forward("}\n"); + + if stmt.has_next() { + diff.add_reverse_primal("(reverse_next(stmt.get_next_expression().to_string()))$;\n"); + } + diff.add_reverse_primal(rws_restore); + diff.add_reverse_primal("}\n"); + diff.add_reverse_backprop(rws); + } + } + + + traverse: (override inout this, stmt: meta::selection_statement) = { + // TODO: Currently assuming that nothing bad happens in the condition + diff += "if (stmt.get_expression().to_string())$"; + pre_traverse(stmt.get_true_branch()); + + if stmt.has_false_branch() { + diff += "else "; + pre_traverse(stmt.get_false_branch()); + } + } + + traverse : (override inout this, expr: meta::expression) = { + base::traverse(expr); } - // Else we're at an actual postfix expression with ops - else { - sample_print("postfix expression", indent); + traverse: (override inout this, binexpr: meta::assignment_expression) = { + ada: autodiff_activity_check = (ctx); + ada.pre_traverse(binexpr.get_lhs_postfix_expression()); + if "_" == binexpr.get_lhs_postfix_expression().to_string() { + ada.pre_traverse(binexpr.get_terms()[1].get_term()); + } - sample_print("expression", indent+1); - sample_traverser(postfix.get_primary_expression(), indent+2); + if ada.active { + h_lhs: autodiff_expression_handler = (ctx); + h_lhs.pre_traverse(binexpr.get_lhs_postfix_expression()); - for terms do (term) { - sample_print("op: (term.get_op())$", indent+1); - if term.is_id_expression() { - sample_traverser(term.get_id_expression(), indent+1); + // Cpp2 doesn't allow chained assignment, so rhs must be a single logical_or_expression + assignment_terms := binexpr.get_terms(); + + h: autodiff_expression_handler = (ctx); + h.pre_traverse(assignment_terms[1].get_term()); + + is_overwrite := h.primal_expr.contains(h_lhs.primal_expr); + if overwrite_push_pop && is_overwrite { + r := ctx*.lookup_variable_declaration(h_lhs.primal_expr); + diff.add_reverse_primal("cpp2::ad_stack::push<(r.decl)$>((h_lhs.primal_expr)$);"); } - else if term.is_expression_list() { - sample_traverser(term.get_expression_list(), indent+1); + + if is_overwrite && ctx*.is_reverse() { + t_b := ctx*.gen_temporary() + ctx*.rws_suffix; + h.gen_assignment(h_lhs.primal_expr, h_lhs.fwd_expr, t_b); + append(h); + diff.add_reverse_backprop("(h_lhs.rws_expr)$ = 0.0;\n"); + diff.add_reverse_backprop("(t_b)$ := (h_lhs.rws_expr)$;\n"); } - else if term.is_expression() { - sample_traverser(term.get_expression(), indent+1); + else { + h.gen_assignment(h_lhs.primal_expr, h_lhs.fwd_expr, h_lhs.rws_expr); + append(h); + } + + if overwrite_push_pop && is_overwrite { + r := ctx*.lookup_variable_declaration(h_lhs.primal_expr); + diff.add_reverse_backprop("(h_lhs.primal_expr)$ = cpp2::ad_stack::pop<(r.decl)$>();"); + } + + // Simple overwrite check + if is_overwrite { + overwritten.push_back(h_lhs.primal_expr); } } + else { + diff.add_forward(binexpr.to_string() + ";\n"); + diff.add_reverse_primal(binexpr.to_string() + ";\n"); + } } -} - -sample_traverser: (uid: meta::unqualified_id, indent: i32) = -{ - if uid.is_identifier() { - sample_print(uid.get_identifier(), indent); + traverse: (override inout this, binexpr: meta::logical_or_expression) = { + binexpr.error( "AD: Logical or expressions are not yet handled as standalone statements." ); } - else { - sample_print(uid.to_string(), indent+1); + + traverse: (override inout this, binexpr: meta::logical_and_expression) = { + binexpr.error( "AD: Logical and expressions are not yet handled as standalone statements." ); } -} + traverse: (override inout this, binexpr: meta::bit_or_expression) = { + binexpr.error( "AD: Bit or expressions are not yet handled as standalone statements." ); + } -sample_traverser: (qid: meta::qualified_id, indent: i32) = -{ - (copy first := true) - for qid.get_terms() - do (term) - { - if !first { - sample_print("op: (term.get_op())$", indent+1); - } - first = false; - sample_print("unqualified:", indent+1); - sample_traverser(term.get_unqualified(), indent+2); + traverse: (override inout this, binexpr: meta::bit_xor_expression) = { + binexpr.error( "AD: Bit xor expressions are not yet handled as standalone statements." ); } -} + traverse: (override inout this, binexpr: meta::bit_and_expression) = { + binexpr.error( "AD: Bit and expressions are not yet handled as standalone statements." ); + } -sample_traverser: (tid: meta::type_id, indent: i32) = -{ - if tid.is_postfix_expression() { - sample_traverser(tid.as_postfix_expression(), indent); + traverse: (override inout this, binexpr: meta::equality_expression) = { + binexpr.error( "AD: Equality or expressions are not yet handled as standalone statements." ); } - else if tid.is_qualified_id() { - sample_traverser(tid.as_qualified_id(), indent); + + traverse: (override inout this, binexpr: meta::relational_expression) = { + binexpr.error( "AD: Relational expressions are not yet handled as standalone statements." ); } - else if tid.is_unqualified_id() { - sample_traverser(tid.as_unqualified_id(), indent); + + traverse: (override inout this, binexpr: meta::compare_expression) = { + binexpr.error( "AD: Compare or expressions are not yet handled as standalone statements." ); } - else { - sample_print(tid.to_string(), indent); + + traverse: (override inout this, binexpr: meta::shift_expression) = { + binexpr.error( "AD: Shift or expressions are not yet handled as standalone statements." ); } -} + traverse: (override inout this, binexpr: meta::additive_expression) = { + binexpr.error( "AD: Additive expressions are not yet handled as standalone statements." ); + } -sample_traverser: (primary: meta::primary_expression, indent: i32) = -{ - if primary.is_identifier() { - sample_print(primary.as_identifier(), indent+1); + traverse: (override inout this, binexpr: meta::multiplicative_expression) = { + binexpr.error( "AD: Multiplicative expressions are not yet handled as standalone statements." ); } - else if primary.is_expression_list() { - sample_traverser(primary.as_expression_list(), indent+1); + + traverse: (override inout this, isas: meta::is_as_expression) = { + isas.error( "AD: Is as expressions are not yet handled as standalone statements." ); } - else if primary.is_literal() { - sample_print(primary.as_literal(), indent+1); + + traverse: (override inout this, prefix: meta::prefix_expression) = + { + prefix.error( "AD: Prefix expressions are not yet handled as standalone statements." ); } - else if primary.is_declaration() { - sample_traverser(primary.as_declaration(), indent+1); + + traverse: (override inout this, postfix: meta::postfix_expression) = + { + terms := postfix.get_terms(); + + is_func := false; + + (copy i := 0) + for terms next i += 1 do (term) { + if term.get_op() == "." { + continue; + } + if term.get_op() == "(" && i + 1 == terms.ssize() { // Function operator has to be the last + is_func = true; + continue; + } else { + postfix.error("AD: Unknown operator for standalone postfix expression. op: (term.get_op())$ expr: (postfix)$"); + } + } + + // Check for function call, everything else is not handled. + if !(is_func) { + postfix.error( "AD: Postfix expressions are only handled for function calls, or member function calls. Do not know how to handle: (postfix.to_string())$" ); + return; + } + + ad: autodiff_expression_handler = (ctx); + ad.handle_function_call(postfix, false); + ad.diff += ad.fwd_expr + "\n"; + ad.diff += ad.primal_expr + "\n"; + append(ad); } - else { - sample_print(primary.to_string(), indent+1); + + traverse: (override inout this, primary: meta::primary_expression) = + { + primary.error( "AD: Primary expressions are not yet handled as standalone statements." ); } } +autodiff_declaration_handler: type = { + this: simple_traverser = (); + this: autodiff_handler_base; -sample_traverser: (idexpr: meta::id_expression, indent: i32) = -{ - if idexpr.is_identifier() { - sample_print(idexpr.as_identifier(), indent+1); - } - else if idexpr.is_qualified() { - sample_traverser(idexpr.as_qualified(), indent+1); - } - else if idexpr.is_unqualified() { - sample_traverser(idexpr.as_unqualified(), indent+1); + base: type == simple_traverser; + + decl: meta::type_or_namespace_declaration; + + is_type_context: bool = false; + diff_ad_type : std::string = ""; + + operator=: (out this, ctx_: *autodiff_context, decl_: meta::type_or_namespace_declaration) = { + autodiff_handler_base = (ctx_); + decl = decl_; } - else { - sample_print(idexpr.to_string(), indent+1); + + traverse: (override inout this, decl_: meta::declaration) = { + base::traverse(decl_); } -} -//----------------------------------------------------------------------- -// -// autodiff - stub -// + traverse: (override inout this, f: meta::function_declaration) = { + ctx*.enter_function(); -autodiff_impl: type = { + // TODO: Add activity for member functions - private temporary_count : int = 0; + diff.add_forward(" (f.name())$(ctx*.fwd_suffix)$: ("); + diff.add_reverse_primal(" (f.name())$(ctx*.rws_suffix)$: ("); - public diff : std::string = ""; + // 1. Generate the modified signature + // a) Parameters - gen_temporary : (inout this) -> std::string = { - temporary_count += 1; - return "temp_(temporary_count)$"; - } + for f.get_parameters() do (param) { + name: std::string = param.get_declaration().name(); - handle_expression_term :(inout this, inout _ /*mf*/, term) -> std::string = { - if term.is_identifier() { - return term.to_string(); - } - else { - t := gen_temporary(); - std::cout << "Handle generation for: (term.to_string())$" << std::endl; - //handle_expression_terms(mf, t, term..get_expression_list()); - return t; - } - } + fwd_pass_style := to_string_view(param.get_passing_style()); + rws_pass_style := to_string_view(ctx*.get_reverse_passing_style(param.get_passing_style())); - handle_expression_terms :(inout this, inout mf, lhs: std::string, terms) = { - // Handle binary || - logical_or_terms := terms; - if logical_or_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found as a grammatical - // identifier (this won't compile as Cpp1, but it will - // be visible via @print for development/debugging) - diff += "found_logical_or_with_____"; - count := 0; - for logical_or_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; - } - diff += term.get_term().to_string() + "___"; - } - diff += ";"; + if "this" == name { + fwd_ad_type := ctx*.get_fwd_ad_type(std::string(decl.name())); + rws_ad_type := ctx*.get_rws_ad_type(std::string(decl.name())); - return; - } + diff.add_forward("(fwd_pass_style)$ (name)$, "); + diff.add_forward("(fwd_pass_style)$ (name)$(ctx*.fwd_suffix)$: (fwd_ad_type)$, "); - // Handle binary && - if logical_or_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one logical or term here" ); - } - logical_and_terms := logical_or_terms.front().get_term().get_terms(); - if logical_and_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_logical_and_with_____"; - count := 0; - for logical_and_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; + diff.add_reverse_primal("(fwd_pass_style)$ (name)$, "); + if ctx*.is_taylor() { // Add forward type for higher order + diff.add_reverse_primal("(fwd_pass_style)$ (name)$(ctx*.fwd_suffix)$: (fwd_ad_type)$, "); } - diff += term.get_term().to_string() + "___"; + diff.add_reverse_primal("(rws_pass_style)$ (name)$(ctx*.rws_suffix)$: (rws_ad_type)$, "); } - diff += ";"; + else { + type := param.get_declaration().type(); - return; - } + ada: autodiff_activity_check = (ctx); + ada.pre_traverse(param); - // Handle binary | - if logical_and_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one logical and term here" ); - } - bit_or_terms := logical_and_terms.front().get_term().get_terms(); - if bit_or_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_bit_or_with_____"; - count := 0; - for bit_or_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; + if ada.active { + diff.add_forward("(fwd_pass_style)$ (name)$ : (type)$, "); + diff.add_forward("(fwd_pass_style)$ (name)$(ctx*.fwd_suffix)$ : (ctx*.get_fwd_ad_type(type))$, "); + + diff.add_reverse_primal("(fwd_pass_style)$ (name)$ : (type)$, "); + if ctx*.is_taylor() { + diff.add_reverse_primal("(fwd_pass_style)$ (name)$(ctx*.fwd_suffix)$ : (ctx*.get_fwd_ad_type(type))$, "); + } + diff.add_reverse_primal("(rws_pass_style)$ (name)$(ctx*.rws_suffix)$ : (ctx*.get_rws_ad_type(type))$, "); + } + else { + diff.add_forward("(fwd_pass_style)$ (name)$ : (type)$, "); + diff.add_reverse_primal("(fwd_pass_style)$ (name)$ : (type)$, "); } - diff += term.get_term().to_string() + "___"; - } - diff += ";"; - return; + ctx*.add_variable_declaration(name, type, ada.active); + } } - // Handle binary ^ - if bit_or_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one bit or term here" ); - } - bit_xor_terms := bit_or_terms.front().get_term().get_terms(); - if bit_xor_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_bit_xor_with_____"; - count := 0; - for bit_xor_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; - } - diff += term.get_term().to_string() + "___"; - } - diff += ";"; + // b) Add arguments for returns that become inputs - return; + if f.has_non_void_return_type() && f.get_returns().empty() { // TODO: has_non_void_return_type is true for return lists: (r: double) bug/feature? + // TODO: check if name "r" is available. (Also needs inspection of functions at call sides.) + if f.has_deduced_return_type() { + // TODO: Take care of initialization order error. + diff.add_reverse_primal("inout r(ctx*.rws_suffix)$, "); + } + else { + diff.add_reverse_primal("inout r(ctx*.rws_suffix)$: (ctx*.get_rws_ad_type(f.get_unnamed_return_type()))$, "); + } } + else { + for f.get_returns() do (param) { + name := param.get_declaration().name(); + type := param.get_declaration().type(); - // Handle binary & - if bit_xor_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one bit xor term here" ); - } - bit_and_terms := bit_xor_terms.front().get_term().get_terms(); - if bit_and_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_bit_and_with_____"; - count := 0; - for bit_and_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; - } - diff += term.get_term().to_string() + "___"; + rws_pass_style := to_string_view(ctx*.get_reverse_passing_style(param.get_passing_style())); + diff.add_reverse_primal("(rws_pass_style)$ (name)$(ctx*.rws_suffix)$ : (ctx*.get_rws_ad_type(type))$ , "); } - diff += ";"; - - return; } - // Handle binary == and != - if bit_and_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one bit and term here" ); - } - equality_terms := bit_and_terms.front().get_term().get_terms(); - if equality_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_equality_with_____"; - count := 0; - for equality_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; - } - diff += term.get_term().to_string() + "___"; - } - diff += ";"; + diff.add_forward(") -> ("); + diff.add_reverse_primal(") -> ("); - return; - } + // c) Returns - // Handle binary < > <= >= - if equality_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one equality term here" ); - } - relational_terms := equality_terms.front().get_term().get_terms(); - if relational_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_relational_with_____"; - count := 0; - for relational_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; + if f.has_non_void_return_type() && f.get_returns().empty() { // TODO: has_non_void_return_type is true for return lists: (r: double) bug/feature? + // TODO: check if name "r" is available. (Also needs inspection of functions at call sides.) + if f.has_deduced_return_type() { + // TODO: Take care of initialization order error. + diff.add_forward("r, r(ctx*.fwd_suffix)$, "); + diff.add_reverse_primal("r, "); + if ctx*.is_taylor() { + diff.add_reverse_primal("r(ctx*.fwd_suffix)$,"); } - diff += term.get_term().to_string() + "___"; } - diff += ";"; - - return; - } - - // Handle binary <=> - if relational_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one relational term here" ); - } - compare_terms := relational_terms.front().get_term().get_terms(); - if compare_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_compare_with_____"; - count := 0; - for compare_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; + else { + diff.add_forward("r: (f.get_unnamed_return_type())$ = (), r(ctx*.fwd_suffix)$: (ctx*.get_fwd_ad_type(f.get_unnamed_return_type()))$ = (), "); + diff.add_reverse_primal("r: (f.get_unnamed_return_type())$ = (), "); + if ctx*.is_taylor() { + diff.add_reverse_primal("r(ctx*.fwd_suffix)$: (ctx*.get_fwd_ad_type(f.get_unnamed_return_type()))$ = (), "); } - diff += term.get_term().to_string() + "___"; } - diff += ";"; - - return; } - - // Handle binary << and >> - if compare_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one compare term here" ); - } - shift_terms := compare_terms.front().get_term().get_terms(); - if shift_terms.ssize() > 1 - { - // TODO: Do whatever is appropriate here... - // For now, just list out what we found (visible via @print)... - diff += "found_shift_with_____"; - count := 0; - for shift_terms do (term) { - if count++ > 1 { - diff += term.get_op() + "___"; + else { + for f.get_returns() do (param) { + name := param.get_declaration().name(); + type := param.get_declaration().type(); + + fwd_pass_style := to_string_view(param.get_passing_style()); + //rws_pass_style := to_string_view(ctx*.get_reverse_passing_style(param.get_passing_style())); + diff.add_forward("(fwd_pass_style)$ (name)$ : (param.get_declaration().type())$ = 0.0, "); + diff.add_forward("(fwd_pass_style)$ (name)$(ctx*.fwd_suffix)$ : (ctx*.get_fwd_ad_type(type))$ = 0.0, "); + + diff.add_reverse_primal("(fwd_pass_style)$ (name)$ : (param.get_declaration().type())$ = 0.0, "); + if ctx*.is_taylor() { + diff.add_reverse_primal("(fwd_pass_style)$ (name)$(ctx*.fwd_suffix)$ : (ctx*.get_fwd_ad_type(type))$ = 0.0, "); } - diff += term.get_term().to_string() + "___"; + + ctx*.add_variable_declaration("(name)$", "(type)$", true); // TODO_a: Add acitivty check } - diff += ";"; + } + + diff.add_forward(") = {"); + diff.add_reverse_primal(") = {"); + + // Generate the body + if !f.has_compound_body() { + f.error( "temporary alpha limitation: a differentiable function must have a {}-enclosed body" ); return; } - // Handle binary + and - - if shift_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one shift term here" ); - } - additive_terms := shift_terms.front().get_term().get_terms(); - if additive_terms.ssize() > 1 - { - first := true; - fwd : std::string = "(lhs)$_d = "; - primal: std::string = "(lhs)$ = "; - for additive_terms do (term) { - if !first { - op := term.get_op().to_string(); - fwd += " (op)$ "; - primal += " (op)$ "; - } - var := handle_expression_term(mf, term.get_term()); - fwd += "(var)$_d"; - primal += "(var)$"; + ad_impl : autodiff_stmt_handler = (ctx*&, f); - first = false; - } - fwd += ";"; - primal += ";"; + for f.get_compound_body().get_statements() do (stmt) + { + ad_impl..pre_traverse(stmt); + } + diff.add_forward(ad_impl.diff.fwd); + diff.add_reverse_primal(ad_impl.diff.rws_primal); + diff.add_reverse_primal(ad_impl.diff.rws_backprop); - diff += fwd + primal; + diff.add_forward("}"); + diff.add_reverse_primal("}"); - return; - } + ctx*.leave_function(); - // Handle binary * / % - if additive_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one additive term here" ); + if ctx*.is_forward() { + decl.add_member( diff.fwd ); } - multiplicative_terms := additive_terms.front().get_term().get_terms(); - - // Temporary test loop - if multiplicative_terms.ssize() > 1 - { - std::cout << "debug: found (multiplicative_terms.ssize())$ is_as_expressions\n"; - for multiplicative_terms do (isas) { - std::cout << "debug: is_as term: \"(isas.get_term().to_string())$\"\n"; - if isas.get_term().is_identifier() { - std::cout << "debug: identifier: (isas.get_term().get_identifier())$\n"; - } - } + if ctx*.is_reverse() { + decl.add_member( diff.rws_primal ); } + diff.reset(); - if multiplicative_terms.ssize() > 1 - { - arg_a := handle_expression_term(mf, multiplicative_terms[0].get_term()); + ctx*.add_as_differentiated(f); + } - i : int = 1; - while i < multiplicative_terms.ssize() next i += 1 { - arg_b := handle_expression_term(mf, multiplicative_terms[i].get_term()); - op := multiplicative_terms[i].get_op().to_string(); + traverse: (override inout this, o: meta::object_declaration) = { + ad_name : std::string = "(o.name())$(ctx*.fwd_suffix)$"; + fwd_ad_type : std::string = ctx*.get_fwd_ad_type(o.type()); + ad_init : std::string = ""; - fwd : std::string = ""; - primal : std::string = ""; + if o.has_initializer() { + ad: autodiff_expression_handler = (ctx); + ad.pre_traverse(o.get_initializer()); - if "*" == op { - fwd = "(arg_a)$ * (arg_b)$_d + (arg_b)$ * (arg_a)$_d"; - primal = "(arg_a)$ * (arg_b)$"; - } - else if "/" == op { - fwd = "(arg_a)$_d / (arg_b)$ - (arg_a)$ * (arg_b)$_d / ((arg_b)$ * (arg_b)$)"; - primal = "(arg_a)$ / (arg_b)$"; - } - else { - mf.error( "unkown multiplicative operator '(op)$'"); - } + assert(ad.diff.empty()); + ad_init = " = " +ad.fwd_expr; + } + diff = "(ad_name)$ : (fwd_ad_type)$(ad_init)$;"; - if i + 1 == multiplicative_terms.ssize() { - // Last item - diff += "(lhs)$_d = (fwd)$;"; - diff += "(lhs)$ = (primal)$;"; - } - else { - // Temporary - t := gen_temporary(); - // TODO: Get type of expression, in order to define the type of t. - diff += "(t)$_d := (fwd)$;"; - diff += "(t)$ := (primal)$;"; + if is_type_context { - arg_a = t; - } - } + diff_ad_type += "public (diff.fwd)$\n"; } + else { + decl.add_member(diff.fwd); + } + diff = ""; + ctx*.add_variable_declaration("(o.name())$", "(o.type())$", true, true); // TODO_a: Add acitivty check } - handle_expression_statement : (inout this, inout mf, expr) = { - if expr.is_simple_assignment() - { - // If this is not an assignment to a parameter or return object, skip it - lhs_rhs := expr.get_lhs_rhs_if_simple_assignment(); - lhs := lhs_rhs.lhs.get_first_token_ignoring_this(); - if !mf.has_parameter_or_return_named(lhs) - { - return; - } - assignment := expr.as_assignment_expression(); + traverse: (override inout this, t: meta::type_declaration) = { + ctx*.push_stack(t); + ad: autodiff_declaration_handler = (ctx, t); + ad.is_type_context = true; - // Cpp2 doesn't allow chained assignment, so rhs must be a single logical_or_expression - assignment_terms := assignment.get_terms(); - if assignment_terms.ssize() != 2 { - mf.error( "an assignment must have exactly one right-hand side expression" ); - } + for t.get_members() + do (m) + { + ad.pre_traverse(m); + } - // Now we handle sequences of binary "expr1 @ expr2 @ ..." where each - // @ is one of a list of operators at the same grammar precedence + ctx*.pop_stack(); - handle_expression_terms(mf, lhs.to_string(), assignment_terms[1].get_term().get_terms()); + if !ad.diff_ad_type.empty() { + diff = "(t.name())$(ctx*.fwd_suffix)$ : type = {\n"; + diff += "(ad.diff_ad_type)$"; + diff += "}"; + + decl.add_member(diff.fwd); + diff = ""; } } -} -autodiff: (inout t: meta::type_declaration) = -{ - for t.get_members() - do (m) - if m.is_function() - { - mf := m.as_function(); - diff: std::string = " (mf.name())$_diff: ("; + traverse: (override inout this, t: meta::parameter_declaration) = { + t.error("AD: Do not know how to handle parameter_declaration: (t.to_string())$"); + } - // 1. Generate the modified signature - // a) Parameters - for mf.get_parameters() do (param) { - diff += "(param.get_declaration().name())$ : (param.get_declaration().type())$, "; - diff += "(param.get_declaration().name())$_d : (param.get_declaration().type())$, "; - } + traverse: (override inout this, stmt: meta::statement) = { + stmt.error("AD: Do not know how to handle statement in declaration context: (stmt.to_string())$"); + } +} - diff += ") -> ("; - // b) Returns +autodiff: (inout t: meta::type_declaration) = +{ - for mf.get_returns() do (param) { - diff += "(param.get_declaration().name())$ : (param.get_declaration().type())$ = 1, "; - diff += "(param.get_declaration().name())$_d : (param.get_declaration().type())$ = 1, "; - } + suffix_token : std::string_view == "suffix="; + rws_suffix_token : std::string_view == "rws_suffix="; + order_token : std::string_view == "order="; + reverse_token : std::string_view == "reverse"; - diff += ") = {"; + args := t.get_arguments(); - // Generate the body + suffix : std::string = "_d"; + rws_suffix: std::string = "_b"; + order : int = 1; + reverse : bool = false; + for args do (arg_str) { + if arg_str.starts_with("\"") && arg_str.ends_with("\"") { + arg := arg_str.substr(1, arg_str.ssize() - 2); - if !mf.has_compound_body() { - mf.error( "temporary alpha limitation: a differentiable function must have a {}-enclosed body" ); - return; + if arg.starts_with(suffix_token) { + suffix = arg.substr(suffix_token.size()); + continue; + } + else if arg.starts_with(rws_suffix_token) { + suffix = arg.substr(rws_suffix_token.size()); + continue; + } + else if arg.starts_with(order_token) { + if !string_util::string_to_int(arg.substr(order_token.size()), order) { + t.error("AD: Could not parse derivative order: (arg.substr(order_token.size()))$"); + return; + } + continue; + } + else if arg == reverse_token { + reverse = true; + continue; + } } - ad_impl : autodiff_impl = (); + t.error("AD: Unknown argument: (arg_str)$"); + return; + } + + ad_ctx: autodiff_context = (order, reverse); + ad_ctx.fwd_suffix = suffix; + ad_ctx.rws_suffix = rws_suffix; + if t.parent_is_nonglobal_namespace() { + p := t.get_parent().as_nonglobal_namespace(); + ad_ctx.create_namespace_stack(p); + ad: autodiff_declaration_handler = (ad_ctx&, p); + ad.pre_traverse(t); - for mf.get_compound_body().get_statements() do (stmt) + } + else if t.parent_is_type() { + p := t.get_parent().as_type(); + ad_ctx.create_namespace_stack(p); + ad: autodiff_declaration_handler = (ad_ctx&, p); + ad.pre_traverse(t); + } + else { + // TODO: Remove when global namespace is available. + // Traverse without parent context + ad_ctx.push_stack(t); + ad: autodiff_declaration_handler = (ad_ctx&, t); + + for t.get_members() + do (m) + if m.is_function() { - if stmt.is_expression_statement() - { - ad_impl.handle_expression_statement(mf, stmt.as_expression_statement().get_expression()); - } + ad.pre_traverse(m); } - diff += ad_impl.diff; - - diff += "}"; + ad_ctx.pop_stack(); + } - t.add_member( diff ); + if 1 != order { + t.add_runtime_support_include( "cpp2taylor.h" ); + } + if reverse { + t.add_runtime_support_include( "cpp2ad_stack.h" ); } + + ad_ctx.finish(); + + _ = ad_ctx; }