diff --git a/include/cpp2regex.h b/include/cpp2regex.h index e2a69946ca..1463724228 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 763c5638be..6fbc03f128 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 0000000000..e07cb31717 --- /dev/null +++ b/include/cpp2taylor.h @@ -0,0 +1,467 @@ + +#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 225 "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 { + private: std::array v {}; + + public: explicit taylor(); + public: taylor(R const& d1); +#line 10 "cpp2taylor.h2" + public: auto operator=(R const& d1) -> taylor& ; + +#line 13 "cpp2taylor.h2" + public: taylor(taylor const& that); +#line 13 "cpp2taylor.h2" + public: auto operator=(taylor const& that) -> taylor& ; +#line 13 "cpp2taylor.h2" + public: taylor(taylor&& that) noexcept; +#line 13 "cpp2taylor.h2" + public: auto operator=(taylor&& that) noexcept -> taylor& ; + + public: taylor(std::initializer_list const& l); +#line 15 "cpp2taylor.h2" + public: auto operator=(std::initializer_list const& l) -> taylor& ; + +#line 22 "cpp2taylor.h2" + // C++ interface + + public: [[nodiscard]] auto operator[](cpp2::impl::in k) const& -> R; + +#line 34 "cpp2taylor.h2" + public: auto set(cpp2::impl::in k, cpp2::impl::in value) & -> void; + +#line 44 "cpp2taylor.h2" + // C++2 interface / AD interface + + public: [[nodiscard]] auto get(cpp2::impl::in i, cpp2::impl::in v0) const& -> R; + +#line 56 "cpp2taylor.h2" + // Overload for simple handling of connected adds. + public: [[nodiscard]] auto operator+(cpp2::impl::in o) const& -> taylor; + +#line 61 "cpp2taylor.h2" + // Overload for simple handling of connected minuses. + public: [[nodiscard]] auto operator-(cpp2::impl::in o) const& -> taylor; + +#line 66 "cpp2taylor.h2" + public: [[nodiscard]] auto add(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 77 "cpp2taylor.h2" + public: [[nodiscard]] auto sub(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 88 "cpp2taylor.h2" + public: [[nodiscard]] auto mul(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 101 "cpp2taylor.h2" + public: [[nodiscard]] auto div(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor; + +#line 119 "cpp2taylor.h2" + public: [[nodiscard]] auto sqrt(cpp2::impl::in v0) const& -> taylor; + +#line 138 "cpp2taylor.h2" + public: [[nodiscard]] auto log(cpp2::impl::in v0) const& -> taylor; + +#line 157 "cpp2taylor.h2" + public: [[nodiscard]] auto exp(cpp2::impl::in v0) const& -> taylor; + +#line 176 "cpp2taylor.h2" + public: static auto comp_sin_cos(taylor& s, taylor& c, cpp2::impl::in u, cpp2::impl::in u0) -> void; + +#line 193 "cpp2taylor.h2" + public: [[nodiscard]] auto sin(cpp2::impl::in v0) const& -> taylor; + +#line 203 "cpp2taylor.h2" + public: [[nodiscard]] auto cos(cpp2::impl::in v0) const& -> taylor; + +#line 212 "cpp2taylor.h2" +}; + +template [[nodiscard]] auto to_string(taylor const& o) -> std::string; + +#line 225 "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{ d1 }{ + +#line 12 "cpp2taylor.h2" + } +#line 10 "cpp2taylor.h2" + template auto taylor::operator=(R const& d1) -> taylor& { + v = d1; + return *this; + +#line 12 "cpp2taylor.h2" + } +#line 13 "cpp2taylor.h2" + template taylor::taylor(taylor const& that) + : v{ that.v }{} +#line 13 "cpp2taylor.h2" + template auto taylor::operator=(taylor const& that) -> taylor& { + v = that.v; + return *this; } +#line 13 "cpp2taylor.h2" + template taylor::taylor(taylor&& that) noexcept + : v{ std::move(that).v }{} +#line 13 "cpp2taylor.h2" + template auto taylor::operator=(taylor&& that) noexcept -> taylor& { + v = std::move(that).v; + return *this; } + +#line 15 "cpp2taylor.h2" + template taylor::taylor(std::initializer_list const& l){ +{ +auto i{1}; + +#line 17 "cpp2taylor.h2" + for ( auto const& cur : l ) { + set(i, cur); + } +} +#line 20 "cpp2taylor.h2" + } +#line 15 "cpp2taylor.h2" + template auto taylor::operator=(std::initializer_list const& l) -> taylor& { + v = {}; +{ +auto i{1}; + +#line 17 "cpp2taylor.h2" + for ( auto const& cur : l ) { + set(i, cur); + } +} + return *this; +#line 20 "cpp2taylor.h2" + } + +#line 24 "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 28 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(i,k); i += 1 ) { + r *= i; + } +} +#line 31 "cpp2taylor.h2" + return r; + } + +#line 34 "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 39 "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 42 "cpp2taylor.h2" + } + +#line 46 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::get(cpp2::impl::in i, cpp2::impl::in v0) const& -> R{ + if (cpp2::cpp2_default.is_active() && !([_0 = 0, _1 = i, _2 = dim]{ return cpp2::impl::cmp_less_eq(_0,_1) && cpp2::impl::cmp_less_eq(_1,_2); }()) ) { cpp2::cpp2_default.report_violation(""); } + + if (i == 0) { + return v0; + } + + return CPP2_ASSERT_IN_BOUNDS(v, i - 1); + } + +#line 57 "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 62 "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 66 "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 70 "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 74 "cpp2taylor.h2" + return r; + } + +#line 77 "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 81 "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 85 "cpp2taylor.h2" + return r; + } + +#line 88 "cpp2taylor.h2" + template [[nodiscard]] auto taylor::mul(cpp2::impl::in o, cpp2::impl::in v0, cpp2::impl::in o0) const& -> taylor{ + taylor r {}; +{ +auto k{1}; + +#line 92 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { +{ +auto j{0}; + +#line 94 "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 97 "cpp2taylor.h2" + } +} +#line 98 "cpp2taylor.h2" + return r; + } + +#line 101 "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 108 "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 111 "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 114 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) *= factor; + } +} +#line 116 "cpp2taylor.h2" + return r; + } + +#line 119 "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 126 "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 129 "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 132 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) *= factor; + } +} + +#line 135 "cpp2taylor.h2" + return r; + } + +#line 138 "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 145 "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 148 "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 151 "cpp2taylor.h2" + CPP2_ASSERT_IN_BOUNDS(r.v, k - 1) *= factor / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(factor),k); + } +} + +#line 154 "cpp2taylor.h2" + return r; + } + +#line 157 "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 164 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { +{ +auto j{1}; + +#line 166 "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 169 "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 172 "cpp2taylor.h2" + return r; + } + +#line 176 "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 181 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(k,dim); k += 1 ) { +{ +auto j{1}; + +#line 183 "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) * CPP2_UFCS(get)(c, k - j, c0); + CPP2_ASSERT_IN_BOUNDS(c.v, k - 1) -= j * u.get(j, u0) * CPP2_UFCS(get)(s, k - j, s0); + } +} +#line 187 "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 190 "cpp2taylor.h2" + } + +#line 193 "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 203 "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 214 "cpp2taylor.h2" +template [[nodiscard]] auto to_string(taylor const& o) -> std::string{ + std::string r {"("}; +{ +auto i{1}; + +#line 217 "cpp2taylor.h2" + for( ; cpp2::impl::cmp_less_eq(i,order); i += 1 ) { + r += " " + cpp2::to_string(CPP2_ASSERT_IN_BOUNDS(o, i)) + ""; + } +} +#line 220 "cpp2taylor.h2" + r += " )"; + + return r; +} + +} + +#endif diff --git a/include/cpp2taylor.h2 b/include/cpp2taylor.h2 new file mode 100644 index 0000000000..845af5d0f5 --- /dev/null +++ b/include/cpp2taylor.h2 @@ -0,0 +1,244 @@ +#ifndef CPP2_CPP2TAYLOR_H +#define CPP2_CPP2TAYLOR_H + +cpp2: namespace = { + +taylor: type = { + v : std::array = (); + + operator=:(out this) = {} + operator=:(out this, d1: R) = { + 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 = { + assert(0 <= i <= dim); + + if i == 0 { + return v0; + } + + return v[i - 1]; + } + + // 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, o: taylor, v0: R, o0: R) -> taylor = { + r: taylor = (); + + (copy k:= 1) + while k <= dim 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 0000000000..d7d4ff43c7 --- /dev/null +++ b/regression-tests/mixed-autodiff-taylor.cpp2 @@ -0,0 +1,85 @@ +#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) = { + 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 0000000000..cfa25c6bc4 --- /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 0000000000..3dd253dde1 --- /dev/null +++ b/regression-tests/pure2-autodiff.cpp2 @@ -0,0 +1,245 @@ +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 = (); // 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); + } +} +} + +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; +} + +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)); + + 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 0000000000..75ad0ade51 --- /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/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 0000000000..0a486b06f7 --- /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 0000000000..84a5f58deb --- /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 0000000000..b199249903 --- /dev/null +++ b/regression-tests/test-results/gcc-13-c++2b/pure2-autodiff.cpp.execution @@ -0,0 +1,31 @@ +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) +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 0000000000..cd61d4f563 --- /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/mixed-autodiff-taylor.cpp b/regression-tests/test-results/mixed-autodiff-taylor.cpp new file mode 100644 index 0000000000..56a0606d4a --- /dev/null +++ b/regression-tests/test-results/mixed-autodiff-taylor.cpp @@ -0,0 +1,213 @@ +#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 71 "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{ + std::cout << "" + cpp2::to_string(func) + " = " + cpp2::to_string(ret.y0) + "" << std::endl; +{ +auto i{1}; + +#line 66 "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 69 "mixed-autodiff-taylor.cpp2" +} + +#line 71 "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 0000000000..20bd4dd086 --- /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/pure2-autodiff-higher-order.cpp b/regression-tests/test-results/pure2-autodiff-higher-order.cpp new file mode 100644 index 0000000000..91b5ca7930 --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff-higher-order.cpp @@ -0,0 +1,1087 @@ + +#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 = CPP2_UFCS(mul)(x_d, 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 {CPP2_UFCS(mul)(x_d, y_d, x, y)}; + + auto temp_1 {x * y}; + r_d = CPP2_UFCS(mul)(cpp2::move(temp_1_d), 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 {CPP2_UFCS(mul)(x_d, 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 = CPP2_UFCS(mul)(x_d, 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 {CPP2_UFCS(mul)(x_d, 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 {temp_1.ret_d}; + + double temp_2 {cpp2::move(temp_1).ret}; + r_d = CPP2_UFCS(mul)(x_d, 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 {temp_1.ret_d}; + + double temp_2 {cpp2::move(temp_1).ret}; + r_d = CPP2_UFCS(mul)(x_d, 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_d {}; + + int i {}; + r_d = x_d + y_d; + r = x + y; + i_d = { }; + i = 2; + static_cast(cpp2::move(i_d)); + 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_d {}; + + 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_d {}; + + 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)(cpp2::move(t), cpp2::move(t_d), y, y_d)}; + r_d = temp_1.r_d; + r = cpp2::move(temp_1).r; + 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 0000000000..90bf689bd2 --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff-higher-order.cpp2.output @@ -0,0 +1,898 @@ +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 = temp_1.ret; + 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 = temp_1.ret; + 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_d: int = (); + i: int = (); + r_d = x_d + y_d; + r = x + y; + i_d = (); + i = 2; + _ = i_d; + _ = 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_d: int = (); + 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_d: int = (); + 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 = temp_1.r; + 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 0000000000..a1f7ddf4b0 --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff.cpp @@ -0,0 +1,1138 @@ + +#define CPP2_IMPORT_STD Yes + +//=== 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 193 "pure2-autodiff.cpp2" +} + +class ad_test_twice; + + +//=== 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 154 "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 165 "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 179 "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 186 "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 192 "pure2-autodiff.cpp2" +}; +} + +class ad_test_twice { +using mul_1_ret = double; + +#line 196 "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 199 "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 205 "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 {}; // 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 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" + 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 154 "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 155 "pure2-autodiff.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 165 "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 166 "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 179 "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 180 "pure2-autodiff.cpp2" + type_outer t {}; + t.a = x; + + r.construct(cpp2::move(t).a + y); + return std::move(r.value()); } + +#line 186 "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 187 "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 = x * y_d + y * x_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 {x * y_d + y * x_d}; + + auto temp_1 {x * y}; + r_d = temp_1 * x_d + x * cpp2::move(temp_1_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 {x * y_d + y * x_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 = x * cpp2::move(temp_1_d) + temp_1 * x_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 {x * y_d + y * x_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 {temp_1.ret_d}; + + double temp_2 {cpp2::move(temp_1).ret}; + r_d = x * cpp2::move(temp_2_d) + temp_2 * x_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 {temp_1.ret_d}; + + double temp_2 {cpp2::move(temp_1).ret}; + r_d = x * cpp2::move(temp_2_d) + temp_2 * x_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_d {}; + + int i {}; + r_d = x_d + y_d; + r = x + y; + i_d = { }; + i = 2; + static_cast(cpp2::move(i_d)); + 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}; +int i_d {}; + + 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}; + double r_d {0.0}; +int i_d {}; + + 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}; + 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)(cpp2::move(t), cpp2::move(t_d), y, y_d)}; + r_d = temp_1.r_d; + r = cpp2::move(temp_1).r; + return { std::move(r), std::move(r_d) }; + } + +#line 193 "pure2-autodiff.cpp2" +} + +#line 196 "pure2-autodiff.cpp2" + [[nodiscard]] auto ad_test_twice::mul_1(cpp2::impl::in x) -> mul_1_ret{ + cpp2::impl::deferred_init r; +#line 197 "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 * x_d_d2 + x_d * x_d2}; + + double temp_1 {x * x_d}; + + double temp_2_d2 {x * x_d_d2 + x_d * x_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 201 "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 205 "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, cpp2::move(y), cpp2::move(y_d))); + + 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 0000000000..7b43c59f6d --- /dev/null +++ b/regression-tests/test-results/pure2-autodiff.cpp2.output @@ -0,0 +1,957 @@ +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, ) = + { + 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: 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 = x * y_d + y * x_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: _ = x * y_d + y * x_d; + temp_1: _ = x * y; + r_d = temp_1 * x_d + x * temp_1_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: _ = x * y_d + y * x_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 = x * temp_1_d + temp_1 * x_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 = x * y_d + y * x_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 = temp_1.ret; + r_d = x * temp_2_d + temp_2 * x_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 = temp_1.ret; + r_d = x * temp_2_d + temp_2 * x_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_d: int = (); + i: int = (); + r_d = x_d + y_d; + r = x + y; + i_d = (); + i = 2; + _ = i_d; + _ = 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, + ) = + { + i_d: int = (); + 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: double, + in y: double, + in y_d: double, + ) -> ( + out r: double = 0.0, + out r_d: double = 0.0, + ) = + { + i_d: int = (); + 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: 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 = temp_1.r; + 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 * x_d_d2 + x_d * x_d2; + temp_1: double = x * x_d; + temp_2_d2: double = x * x_d_d2 + x_d * x_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; + } +} + 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 1f549a3467..674d9ada9a 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 0000000000..4bb5f42590 --- /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/reflect.h b/source/reflect.h index 98d2ec7924..60588cb3c7 100644 --- a/source/reflect.h +++ b/source/reflect.h @@ -24,161 +24,188 @@ class compiler_services; #line 189 "reflect.h2" template class reflection_base; -#line 222 "reflect.h2" +#line 225 "reflect.h2" class declaration; -#line 307 "reflect.h2" +#line 310 "reflect.h2" class function_declaration; -#line 412 "reflect.h2" +#line 415 "reflect.h2" class object_declaration; -#line 448 "reflect.h2" +#line 451 "reflect.h2" class type_or_namespace_declaration; -#line 558 "reflect.h2" +#line 562 "reflect.h2" class type_declaration; -#line 601 "reflect.h2" +#line 605 "reflect.h2" class namespace_declaration; -#line 620 "reflect.h2" +#line 624 "reflect.h2" class alias_declaration; -#line 639 "reflect.h2" +#line 643 "reflect.h2" class parameter_declaration; -#line 685 "reflect.h2" +#line 689 "reflect.h2" template class binary_expression; -#line 812 "reflect.h2" +#line 816 "reflect.h2" class expression_list; -#line 845 "reflect.h2" +#line 849 "reflect.h2" class prefix_expression; -#line 887 "reflect.h2" +#line 891 "reflect.h2" class postfix_expression; -#line 958 "reflect.h2" +#line 962 "reflect.h2" class template_arg; -#line 984 "reflect.h2" +#line 988 "reflect.h2" class unqualified_id; -#line 1016 "reflect.h2" +#line 1020 "reflect.h2" class qualified_id; -#line 1060 "reflect.h2" +#line 1064 "reflect.h2" class type_id; -#line 1103 "reflect.h2" +#line 1107 "reflect.h2" class primary_expression; -#line 1142 "reflect.h2" +#line 1146 "reflect.h2" class id_expression; -#line 1178 "reflect.h2" +#line 1182 "reflect.h2" class expression; -#line 1229 "reflect.h2" +#line 1233 "reflect.h2" class is_as_expression; -#line 1290 "reflect.h2" +#line 1294 "reflect.h2" class statement; -#line 1332 "reflect.h2" +#line 1336 "reflect.h2" class expression_statement; -#line 1354 "reflect.h2" +#line 1358 "reflect.h2" class compound_statement; -#line 1393 "reflect.h2" +#line 1397 "reflect.h2" class selection_statement; -#line 1419 "reflect.h2" +#line 1423 "reflect.h2" class return_statement; -#line 1441 "reflect.h2" +#line 1445 "reflect.h2" class iteration_statement; -#line 1938 "reflect.h2" +#line 1942 "reflect.h2" class value_member_info; -#line 3249 "reflect.h2" -class autodiff_impl; +#line 2476 "reflect.h2" +class simple_traverser; + +#line 3960 "reflect.h2" +class autodiff_special_func; + +#line 3996 "reflect.h2" +class autodiff_declared_variable; + +#line 4012 "reflect.h2" +class autodiff_declaration_stack_item; + +#line 4051 "reflect.h2" +class autodiff_context; + + +#line 4326 "reflect.h2" +class autodiff_handler_base; + + +#line 4340 "reflect.h2" +class autodiff_expression_handler; + + +#line 4847 "reflect.h2" +class autodiff_stmt_handler; -#line 3665 "reflect.h2" +#line 5108 "reflect.h2" +class autodiff_declaration_handler; + +#line 5364 "reflect.h2" class expression_flags; -#line 3681 "reflect.h2" +#line 5380 "reflect.h2" class regex_token; -#line 3708 "reflect.h2" +#line 5407 "reflect.h2" class regex_token_check; -#line 3729 "reflect.h2" +#line 5428 "reflect.h2" class regex_token_code; -#line 3750 "reflect.h2" +#line 5449 "reflect.h2" class regex_token_empty; -#line 3768 "reflect.h2" +#line 5467 "reflect.h2" class regex_token_list; -#line 3820 "reflect.h2" +#line 5519 "reflect.h2" class parse_context_group_state; -#line 3881 "reflect.h2" +#line 5580 "reflect.h2" class parse_context_branch_reset_state; -#line 3924 "reflect.h2" +#line 5623 "reflect.h2" class parse_context; -#line 4325 "reflect.h2" +#line 6024 "reflect.h2" class generation_function_context; -#line 4343 "reflect.h2" +#line 6042 "reflect.h2" class generation_context; -#line 4542 "reflect.h2" +#line 6241 "reflect.h2" class alternative_token; -#line 4557 "reflect.h2" +#line 6256 "reflect.h2" class alternative_token_gen; -#line 4622 "reflect.h2" +#line 6321 "reflect.h2" class any_token; -#line 4639 "reflect.h2" +#line 6338 "reflect.h2" class atomic_group_token; -#line 4669 "reflect.h2" +#line 6368 "reflect.h2" class char_token; -#line 4784 "reflect.h2" +#line 6483 "reflect.h2" class class_token; -#line 5008 "reflect.h2" +#line 6707 "reflect.h2" class group_ref_token; -#line 5145 "reflect.h2" +#line 6844 "reflect.h2" class group_token; -#line 5492 "reflect.h2" +#line 7191 "reflect.h2" class lookahead_lookbehind_token; -#line 5587 "reflect.h2" +#line 7286 "reflect.h2" class range_token; -#line 5744 "reflect.h2" +#line 7443 "reflect.h2" class special_range_token; -#line 5830 "reflect.h2" +#line 7529 "reflect.h2" template class regex_generator; -#line 6087 "reflect.h2" +#line 7786 "reflect.h2" } } @@ -295,25 +322,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(reflection_base const& o) const& -> bool; public: virtual ~reflection_base() noexcept; public: reflection_base(reflection_base const& that); public: reflection_base(reflection_base&& that) noexcept; -#line 209 "reflect.h2" +#line 212 "reflect.h2" }; -#line 222 "reflect.h2" +#line 225 "reflect.h2" class declaration : public reflection_base { -#line 226 "reflect.h2" +#line 229 "reflect.h2" public: declaration( declaration_node* n_, cpp2::impl::in s ); -#line 235 "reflect.h2" +#line 238 "reflect.h2" public: [[nodiscard]] auto is_public() const& -> bool; public: [[nodiscard]] auto is_protected() const& -> bool; public: [[nodiscard]] auto is_private() const& -> bool; @@ -332,7 +362,7 @@ class declaration public: [[nodiscard]] auto name() const& -> std::string_view; -#line 256 "reflect.h2" +#line 259 "reflect.h2" public: [[nodiscard]] auto has_initializer() const& -> bool; public: [[nodiscard]] auto get_initializer() const& -> statement; @@ -378,21 +408,21 @@ public: declaration(declaration const& that); public: declaration(declaration&& that) noexcept; -#line 301 "reflect.h2" +#line 304 "reflect.h2" }; -#line 307 "reflect.h2" +#line 310 "reflect.h2" class function_declaration : public declaration { -#line 311 "reflect.h2" +#line 314 "reflect.h2" public: function_declaration( declaration_node* n_, cpp2::impl::in s ); -#line 321 "reflect.h2" +#line 324 "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; @@ -442,10 +472,10 @@ class function_declaration public: [[nodiscard]] auto get_parameters() const& -> std::vector; -#line 378 "reflect.h2" +#line 381 "reflect.h2" public: [[nodiscard]] auto get_returns() const& -> std::vector; -#line 390 "reflect.h2" +#line 393 "reflect.h2" public: [[nodiscard]] auto default_to_virtual() & -> decltype(auto); public: [[nodiscard]] auto make_virtual() & -> bool; @@ -455,88 +485,88 @@ class function_declaration public: function_declaration(function_declaration&& that) noexcept; -#line 406 "reflect.h2" +#line 409 "reflect.h2" }; -#line 412 "reflect.h2" +#line 415 "reflect.h2" class object_declaration : public declaration { -#line 416 "reflect.h2" +#line 419 "reflect.h2" public: object_declaration( declaration_node* n_, cpp2::impl::in s ); -#line 426 "reflect.h2" +#line 429 "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 436 "reflect.h2" +#line 439 "reflect.h2" public: [[nodiscard]] auto initializer() const& -> std::string; public: object_declaration(object_declaration const& that); public: object_declaration(object_declaration&& that) noexcept; -#line 442 "reflect.h2" +#line 445 "reflect.h2" }; -#line 448 "reflect.h2" +#line 451 "reflect.h2" class type_or_namespace_declaration : public declaration { -#line 452 "reflect.h2" +#line 455 "reflect.h2" public: type_or_namespace_declaration( declaration_node* n_, cpp2::impl::in s ); -#line 462 "reflect.h2" +#line 465 "reflect.h2" public: auto reserve_names(cpp2::impl::in name, auto&& ...etc) const& -> void; -#line 476 "reflect.h2" +#line 479 "reflect.h2" public: [[nodiscard]] auto get_member_functions() const& -> std::vector; -#line 487 "reflect.h2" +#line 490 "reflect.h2" public: [[nodiscard]] auto get_member_functions_needing_initializer() const& -> std::vector; -#line 502 "reflect.h2" +#line 505 "reflect.h2" public: [[nodiscard]] auto get_member_objects() const& -> std::vector; -#line 512 "reflect.h2" +#line 515 "reflect.h2" public: [[nodiscard]] auto get_member_types() const& -> std::vector; -#line 522 "reflect.h2" +#line 525 "reflect.h2" public: [[nodiscard]] auto get_member_aliases() const& -> std::vector; -#line 532 "reflect.h2" +#line 535 "reflect.h2" public: [[nodiscard]] auto get_members() const& -> std::vector; -#line 542 "reflect.h2" +#line 545 "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 555 "reflect.h2" +#line 559 "reflect.h2" }; -#line 558 "reflect.h2" +#line 562 "reflect.h2" class type_declaration : public type_or_namespace_declaration { -#line 562 "reflect.h2" +#line 566 "reflect.h2" public: type_declaration( declaration_node* n_, cpp2::impl::in s ); -#line 573 "reflect.h2" +#line 577 "reflect.h2" public: [[nodiscard]] auto is_polymorphic() const& -> bool; public: [[nodiscard]] auto is_final() const& -> bool; public: [[nodiscard]] auto make_final() & -> bool; @@ -544,26 +574,26 @@ struct query_declared_value_set_functions_ret { bool out_this_in_that; bool out_ -#line 577 "reflect.h2" +#line 581 "reflect.h2" public: [[nodiscard]] auto query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret; -#line 593 "reflect.h2" +#line 597 "reflect.h2" public: [[nodiscard]] auto disable_member_function_generation() & -> decltype(auto); -#line 596 "reflect.h2" +#line 600 "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 598 "reflect.h2" +#line 602 "reflect.h2" }; -#line 601 "reflect.h2" +#line 605 "reflect.h2" class namespace_declaration : public type_or_namespace_declaration { -#line 605 "reflect.h2" +#line 609 "reflect.h2" public: namespace_declaration( declaration_node* n_, @@ -573,14 +603,14 @@ class namespace_declaration public: namespace_declaration(namespace_declaration&& that) noexcept; -#line 614 "reflect.h2" +#line 618 "reflect.h2" }; -#line 620 "reflect.h2" +#line 624 "reflect.h2" class alias_declaration : public declaration { -#line 624 "reflect.h2" +#line 628 "reflect.h2" public: alias_declaration( declaration_node* n_, @@ -590,21 +620,21 @@ class alias_declaration public: alias_declaration(alias_declaration&& that) noexcept; -#line 633 "reflect.h2" +#line 637 "reflect.h2" }; -#line 639 "reflect.h2" +#line 643 "reflect.h2" class parameter_declaration : public reflection_base { -#line 643 "reflect.h2" +#line 647 "reflect.h2" public: parameter_declaration( parameter_declaration_node* n_, cpp2::impl::in s ); -#line 652 "reflect.h2" +#line 656 "reflect.h2" public: [[nodiscard]] auto get_declaration() const& -> object_declaration; public: [[nodiscard]] auto get_passing_style() const& -> passing_style; @@ -615,10 +645,10 @@ class parameter_declaration public: parameter_declaration(parameter_declaration const& that); public: parameter_declaration(parameter_declaration&& that) noexcept; -#line 659 "reflect.h2" +#line 663 "reflect.h2" }; -#line 672 "reflect.h2" +#line 676 "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>; @@ -635,14 +665,14 @@ using assignment_expression = binary_expression<"assignment",logical_or_expressi template class binary_expression : public reflection_base> { -#line 689 "reflect.h2" +#line 693 "reflect.h2" public: binary_expression( binary_expression_node* n_, cpp2::impl::in s ); -#line 698 "reflect.h2" +#line 702 "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; @@ -667,16 +697,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 716 "reflect.h2" +#line 720 "reflect.h2" }; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 793 "reflect.h2" +#line 797 "reflect.h2" public: [[nodiscard]] auto as_expression_list() const& -> expression_list; public: [[nodiscard]] auto as_literal() const& -> std::string; -#line 797 "reflect.h2" +#line 801 "reflect.h2" public: [[nodiscard]] auto get_if_only_a_postfix_expression() const& -> postfix_expression; public: [[nodiscard]] auto get_lhs_postfix_expression() const& -> postfix_expression; @@ -689,49 +719,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 806 "reflect.h2" +#line 810 "reflect.h2" }; -#line 812 "reflect.h2" +#line 816 "reflect.h2" class expression_list : public reflection_base { -#line 816 "reflect.h2" +#line 820 "reflect.h2" public: expression_list( expression_list_node* n_, cpp2::impl::in s ); -#line 825 "reflect.h2" +#line 829 "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 838 "reflect.h2" +#line 842 "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 839 "reflect.h2" +#line 843 "reflect.h2" }; -#line 845 "reflect.h2" +#line 849 "reflect.h2" class prefix_expression : public reflection_base { -#line 849 "reflect.h2" +#line 853 "reflect.h2" public: prefix_expression( prefix_expression_node* n_, cpp2::impl::in s ); -#line 858 "reflect.h2" +#line 862 "reflect.h2" public: [[nodiscard]] auto get_ops() const& -> std::vector; -#line 866 "reflect.h2" +#line 870 "reflect.h2" public: [[nodiscard]] auto get_postfix_expression() const& -> postfix_expression; public: [[nodiscard]] auto is_fold_expression() const& -> bool; @@ -751,21 +781,21 @@ class prefix_expression public: prefix_expression(prefix_expression const& that); public: prefix_expression(prefix_expression&& that) noexcept; -#line 881 "reflect.h2" +#line 885 "reflect.h2" }; -#line 887 "reflect.h2" +#line 891 "reflect.h2" class postfix_expression : public reflection_base { -#line 891 "reflect.h2" +#line 895 "reflect.h2" public: postfix_expression( postfix_expression_node* n_, cpp2::impl::in s ); -#line 900 "reflect.h2" +#line 904 "reflect.h2" public: [[nodiscard]] auto get_primary_expression() const& -> primary_expression; public: class term_t { @@ -776,7 +806,7 @@ class postfix_expression public: [[nodiscard]] auto get_op() const& -> std::string_view; -#line 916 "reflect.h2" +#line 920 "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; @@ -787,12 +817,12 @@ class postfix_expression public: term_t(term_t const& that); public: term_t(term_t&& that) noexcept; -#line 923 "reflect.h2" +#line 927 "reflect.h2" }; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 931 "reflect.h2" +#line 935 "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; @@ -806,7 +836,7 @@ public: term_t(term_t&& that) noexcept; public: [[nodiscard]] auto get_first_token_ignoring_this() const& -> std::string_view; -#line 948 "reflect.h2" +#line 952 "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; @@ -814,21 +844,21 @@ public: term_t(term_t&& that) noexcept; public: postfix_expression(postfix_expression const& that); public: postfix_expression(postfix_expression&& that) noexcept; -#line 952 "reflect.h2" +#line 956 "reflect.h2" }; -#line 958 "reflect.h2" +#line 962 "reflect.h2" class template_arg : public reflection_base { -#line 962 "reflect.h2" +#line 966 "reflect.h2" public: template_arg( template_argument* n_, cpp2::impl::in s ); -#line 971 "reflect.h2" +#line 975 "reflect.h2" public: [[nodiscard]] auto is_expression() const& -> bool; public: [[nodiscard]] auto is_type_id() const& -> bool; @@ -839,47 +869,47 @@ class template_arg public: template_arg(template_arg const& that); public: template_arg(template_arg&& that) noexcept; -#line 978 "reflect.h2" +#line 982 "reflect.h2" }; -#line 984 "reflect.h2" +#line 988 "reflect.h2" class unqualified_id : public reflection_base { -#line 988 "reflect.h2" +#line 992 "reflect.h2" public: unqualified_id( unqualified_id_node* n_, cpp2::impl::in s ); -#line 997 "reflect.h2" +#line 1001 "reflect.h2" public: [[nodiscard]] auto is_identifier() const& -> bool; public: [[nodiscard]] auto get_identifier() const& -> std::string; -#line 1007 "reflect.h2" +#line 1011 "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 1010 "reflect.h2" +#line 1014 "reflect.h2" }; -#line 1016 "reflect.h2" +#line 1020 "reflect.h2" class qualified_id : public reflection_base { -#line 1020 "reflect.h2" +#line 1024 "reflect.h2" public: qualified_id( qualified_id_node* n_, cpp2::impl::in s ); -#line 1029 "reflect.h2" +#line 1033 "reflect.h2" public: class term_t { private: std::string op; private: unqualified_id unqualified; @@ -891,33 +921,33 @@ class qualified_id public: term_t(term_t const& that); public: term_t(term_t&& that) noexcept; -#line 1037 "reflect.h2" +#line 1041 "reflect.h2" }; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 1051 "reflect.h2" +#line 1055 "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 1054 "reflect.h2" +#line 1058 "reflect.h2" }; -#line 1060 "reflect.h2" +#line 1064 "reflect.h2" class type_id : public reflection_base { -#line 1064 "reflect.h2" +#line 1068 "reflect.h2" public: type_id( type_id_node* n_, cpp2::impl::in s ); -#line 1079 "reflect.h2" +#line 1083 "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; @@ -931,7 +961,7 @@ class type_id public: [[nodiscard]] auto as_qualified_id() const& -> qualified_id; public: [[nodiscard]] auto as_unqualified_id() const& -> unqualified_id; -#line 1093 "reflect.h2" +#line 1097 "reflect.h2" public: [[nodiscard]] auto as_keyword() const& -> std::string; public: [[nodiscard]] auto as_token() const& -> std::string; @@ -939,21 +969,21 @@ class type_id public: type_id(type_id const& that); public: type_id(type_id&& that) noexcept; -#line 1097 "reflect.h2" +#line 1101 "reflect.h2" }; -#line 1103 "reflect.h2" +#line 1107 "reflect.h2" class primary_expression : public reflection_base { -#line 1107 "reflect.h2" +#line 1111 "reflect.h2" public: primary_expression( primary_expression_node* n_, cpp2::impl::in s ); -#line 1122 "reflect.h2" +#line 1126 "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; @@ -971,21 +1001,21 @@ class primary_expression public: primary_expression(primary_expression const& that); public: primary_expression(primary_expression&& that) noexcept; -#line 1136 "reflect.h2" +#line 1140 "reflect.h2" }; -#line 1142 "reflect.h2" +#line 1146 "reflect.h2" class id_expression : public reflection_base { -#line 1146 "reflect.h2" +#line 1150 "reflect.h2" public: id_expression( id_expression_node* n_, cpp2::impl::in s ); -#line 1161 "reflect.h2" +#line 1165 "reflect.h2" public: [[nodiscard]] auto is_fold_expression() const& -> bool; public: [[nodiscard]] auto is_empty() const& -> bool; public: [[nodiscard]] auto is_identifier() const& -> bool; @@ -1001,21 +1031,21 @@ class id_expression public: id_expression(id_expression const& that); public: id_expression(id_expression&& that) noexcept; -#line 1172 "reflect.h2" +#line 1176 "reflect.h2" }; -#line 1178 "reflect.h2" +#line 1182 "reflect.h2" class expression : public reflection_base { -#line 1182 "reflect.h2" +#line 1186 "reflect.h2" public: expression( expression_node* n_, cpp2::impl::in s ); -#line 1191 "reflect.h2" +#line 1195 "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; @@ -1032,10 +1062,10 @@ struct get_lhs_rhs_if_simple_assignment_ret { postfix_expression lhs; logical_or -#line 1207 "reflect.h2" +#line 1211 "reflect.h2" public: [[nodiscard]] auto get_lhs_rhs_if_simple_assignment() const& -> get_lhs_rhs_if_simple_assignment_ret; -#line 1218 "reflect.h2" +#line 1222 "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; @@ -1045,21 +1075,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 1223 "reflect.h2" +#line 1227 "reflect.h2" }; -#line 1229 "reflect.h2" +#line 1233 "reflect.h2" class is_as_expression : public reflection_base { -#line 1233 "reflect.h2" +#line 1237 "reflect.h2" public: is_as_expression( is_as_expression_node* n_, cpp2::impl::in s ); -#line 1242 "reflect.h2" +#line 1246 "reflect.h2" public: class term_t { private: std::string op; private: expression expr; @@ -1071,14 +1101,14 @@ class is_as_expression public: term_t(term_t const& that); public: term_t(term_t&& that) noexcept; -#line 1250 "reflect.h2" +#line 1254 "reflect.h2" }; public: [[nodiscard]] auto get_expression() const& -> prefix_expression; public: [[nodiscard]] auto get_terms() const& -> auto; -#line 1260 "reflect.h2" +#line 1264 "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; @@ -1091,27 +1121,27 @@ public: term_t(term_t&& that) noexcept; public: [[nodiscard]] auto get_identifier() const& -> std::string_view; -#line 1276 "reflect.h2" +#line 1280 "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 1277 "reflect.h2" +#line 1281 "reflect.h2" }; -#line 1290 "reflect.h2" +#line 1294 "reflect.h2" class statement : public reflection_base { -#line 1294 "reflect.h2" +#line 1298 "reflect.h2" public: statement( statement_node* n_, cpp2::impl::in s ); -#line 1303 "reflect.h2" +#line 1307 "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; @@ -1130,71 +1160,71 @@ class statement public: [[nodiscard]] auto as_return_statement() const& -> return_statement; public: [[nodiscard]] auto as_iteration_statement() const& -> iteration_statement; -#line 1325 "reflect.h2" +#line 1329 "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 1326 "reflect.h2" +#line 1330 "reflect.h2" }; -#line 1332 "reflect.h2" +#line 1336 "reflect.h2" class expression_statement : public reflection_base { -#line 1336 "reflect.h2" +#line 1340 "reflect.h2" public: expression_statement( expression_statement_node* n_, cpp2::impl::in s ); -#line 1345 "reflect.h2" +#line 1349 "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 1348 "reflect.h2" +#line 1352 "reflect.h2" }; -#line 1354 "reflect.h2" +#line 1358 "reflect.h2" class compound_statement : public reflection_base { -#line 1358 "reflect.h2" +#line 1362 "reflect.h2" public: compound_statement( compound_statement_node* n_, cpp2::impl::in s ); -#line 1367 "reflect.h2" +#line 1371 "reflect.h2" public: [[nodiscard]] auto get_statements() const& -> std::vector; -#line 1377 "reflect.h2" +#line 1381 "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 1387 "reflect.h2" +#line 1391 "reflect.h2" }; -#line 1393 "reflect.h2" +#line 1397 "reflect.h2" class selection_statement : public reflection_base { -#line 1397 "reflect.h2" +#line 1401 "reflect.h2" public: selection_statement( selection_statement_node* n_, cpp2::impl::in s ); -#line 1406 "reflect.h2" +#line 1410 "reflect.h2" public: [[nodiscard]] auto has_false_branch_in_source_code() const& -> bool; public: [[nodiscard]] auto has_false_branch() const& -> bool; @@ -1205,42 +1235,42 @@ class selection_statement public: selection_statement(selection_statement const& that); public: selection_statement(selection_statement&& that) noexcept; -#line 1413 "reflect.h2" +#line 1417 "reflect.h2" }; -#line 1419 "reflect.h2" +#line 1423 "reflect.h2" class return_statement : public reflection_base { -#line 1423 "reflect.h2" +#line 1427 "reflect.h2" public: return_statement( return_statement_node* n_, cpp2::impl::in s ); -#line 1432 "reflect.h2" +#line 1436 "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 1435 "reflect.h2" +#line 1439 "reflect.h2" }; -#line 1441 "reflect.h2" +#line 1445 "reflect.h2" class iteration_statement : public reflection_base { -#line 1445 "reflect.h2" +#line 1449 "reflect.h2" public: iteration_statement( iteration_statement_node* n_, cpp2::impl::in s ); -#line 1454 "reflect.h2" +#line 1458 "reflect.h2" public: [[nodiscard]] auto is_do() const& -> bool; public: [[nodiscard]] auto is_while() const& -> bool; public: [[nodiscard]] auto is_for() const& -> bool; @@ -1256,68 +1286,68 @@ class iteration_statement public: iteration_statement(iteration_statement const& that); public: iteration_statement(iteration_statement&& that) noexcept; -#line 1466 "reflect.h2" +#line 1470 "reflect.h2" }; -#line 1481 "reflect.h2" +#line 1485 "reflect.h2" auto add_virtual_destructor(meta::type_declaration& t) -> void; -#line 1501 "reflect.h2" +#line 1505 "reflect.h2" auto interface(meta::type_declaration& t) -> void; -#line 1549 "reflect.h2" +#line 1553 "reflect.h2" auto polymorphic_base(meta::type_declaration& t) -> void; -#line 1594 "reflect.h2" +#line 1598 "reflect.h2" auto ordered_impl( meta::type_declaration& t, cpp2::impl::in ordering ) -> void; -#line 1623 "reflect.h2" +#line 1627 "reflect.h2" auto ordered(meta::type_declaration& t) -> void; -#line 1631 "reflect.h2" +#line 1635 "reflect.h2" auto weakly_ordered(meta::type_declaration& t) -> void; -#line 1639 "reflect.h2" +#line 1643 "reflect.h2" auto partially_ordered(meta::type_declaration& t) -> void; -#line 1661 "reflect.h2" +#line 1665 "reflect.h2" auto copyable(meta::type_declaration& t) -> void; -#line 1693 "reflect.h2" +#line 1697 "reflect.h2" auto copy_constructible(meta::type_declaration& t) -> void; -#line 1725 "reflect.h2" +#line 1729 "reflect.h2" auto hashable(meta::type_declaration& t) -> void; -#line 1758 "reflect.h2" +#line 1762 "reflect.h2" auto basic_value(meta::type_declaration& t) -> void; -#line 1786 "reflect.h2" +#line 1790 "reflect.h2" auto value(meta::type_declaration& t) -> void; -#line 1792 "reflect.h2" +#line 1796 "reflect.h2" auto weakly_ordered_value(meta::type_declaration& t) -> void; -#line 1798 "reflect.h2" +#line 1802 "reflect.h2" auto partially_ordered_value(meta::type_declaration& t) -> void; -#line 1827 "reflect.h2" +#line 1831 "reflect.h2" auto cpp1_rule_of_zero(meta::type_declaration& t) -> void; -#line 1869 "reflect.h2" +#line 1873 "reflect.h2" auto cpp2_struct(meta::type_declaration& t) -> void; -#line 1938 "reflect.h2" +#line 1942 "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 1942 "reflect.h2" +#line 1946 "reflect.h2" }; auto basic_enum( @@ -1326,159 +1356,767 @@ auto basic_enum( cpp2::impl::in bitwise ) -> void; -#line 2208 "reflect.h2" +#line 2212 "reflect.h2" auto cpp2_enum(meta::type_declaration& t) -> void; -#line 2235 "reflect.h2" +#line 2239 "reflect.h2" auto flag_enum(meta::type_declaration& t) -> void; -#line 2281 "reflect.h2" +#line 2285 "reflect.h2" auto cpp2_union(meta::type_declaration& t) -> void; -#line 2432 "reflect.h2" +#line 2436 "reflect.h2" auto print(cpp2::impl::in t) -> void; -#line 2443 "reflect.h2" +#line 2447 "reflect.h2" auto noisy(cpp2::impl::in t) -> void; -#line 2464 "reflect.h2" +#line 2468 "reflect.h2" auto sample_print(cpp2::impl::in s, cpp2::impl::in indent) -> void; -#line 2483 "reflect.h2" +#line 2476 "reflect.h2" +class simple_traverser { + + public: virtual auto pre_traverse(cpp2::impl::in decl) -> void; + +#line 2482 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in decl) -> void; + +#line 2502 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in f) -> void; + +#line 2506 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in f) -> void; + +#line 2527 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in o) -> void; + +#line 2531 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in o) -> void; + +#line 2539 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in t) -> void; + +#line 2543 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in t) -> void; + +#line 2551 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in t) -> void; + +#line 2555 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in t) -> void; + +#line 2560 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2564 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2599 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2603 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2613 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2617 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2625 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2629 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2648 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in stmt) -> void; + +#line 2652 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in stmt) -> void; + +#line 2663 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in expr) -> void; + +#line 2669 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in expr) -> void; + +#line 2683 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2700 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2711 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2728 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2740 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2757 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2768 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2785 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2796 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2813 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2825 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2842 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2854 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2871 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2882 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2899 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2910 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2927 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in binexpr) -> void; + +#line 2938 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in binexpr) -> void; + +#line 2955 "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 isas) -> void; + +#line 3039 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in isas) -> void; + +#line 3050 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in exprs) -> void; + +#line 3057 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in prefix) -> void; + +#line 3073 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in prefix) -> void; + +#line 3078 "reflect.h2" + public: virtual auto pre_traverse(cpp2::impl::in postfix) -> void; + +#line 3094 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in postfix) -> void; + +#line 3113 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in uid) -> void; + +#line 3119 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in qid) -> void; + +#line 3129 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in tid) -> void; + +#line 3146 "reflect.h2" + public: virtual auto traverse(cpp2::impl::in primary) -> void; + +#line 3166 "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 3181 "reflect.h2" +}; + +#line 3194 "reflect.h2" auto sample_traverser(cpp2::impl::in decl, cpp2::impl::in indent) -> void; -#line 2505 "reflect.h2" +#line 3216 "reflect.h2" auto sample_traverser(cpp2::impl::in f, cpp2::impl::in indent = 0) -> void; -#line 2535 "reflect.h2" +#line 3246 "reflect.h2" auto sample_traverser(cpp2::impl::in o, cpp2::impl::in indent) -> void; -#line 2545 "reflect.h2" +#line 3256 "reflect.h2" auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent = 0) -> void; -#line 2566 "reflect.h2" +#line 3277 "reflect.h2" auto sample_traverser(cpp2::impl::in t, cpp2::impl::in indent = 0) -> void; -#line 2585 "reflect.h2" +#line 3296 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2632 "reflect.h2" +#line 3343 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2649 "reflect.h2" +#line 3360 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2659 "reflect.h2" +#line 3370 "reflect.h2" auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void; -#line 2691 "reflect.h2" +#line 3402 "reflect.h2" auto sample_traverser(cpp2::impl::in expr, cpp2::impl::in indent) -> void; -#line 2705 "reflect.h2" +#line 3416 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2735 "reflect.h2" +#line 3446 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2765 "reflect.h2" +#line 3476 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2795 "reflect.h2" +#line 3506 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2825 "reflect.h2" +#line 3536 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2855 "reflect.h2" +#line 3566 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2885 "reflect.h2" +#line 3596 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2915 "reflect.h2" +#line 3626 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2945 "reflect.h2" +#line 3656 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 2975 "reflect.h2" +#line 3686 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3005 "reflect.h2" +#line 3716 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3035 "reflect.h2" +#line 3746 "reflect.h2" auto sample_traverser(cpp2::impl::in binexpr, cpp2::impl::in indent) -> void; -#line 3065 "reflect.h2" +#line 3776 "reflect.h2" auto sample_traverser(cpp2::impl::in isas, cpp2::impl::in indent) -> void; -#line 3091 "reflect.h2" +#line 3802 "reflect.h2" auto sample_traverser(cpp2::impl::in exprs, cpp2::impl::in indent) -> void; -#line 3106 "reflect.h2" +#line 3817 "reflect.h2" auto sample_traverser(cpp2::impl::in prefix, cpp2::impl::in indent) -> void; -#line 3130 "reflect.h2" +#line 3841 "reflect.h2" auto sample_traverser(cpp2::impl::in postfix, cpp2::impl::in indent) -> void; -#line 3163 "reflect.h2" +#line 3874 "reflect.h2" auto sample_traverser(cpp2::impl::in uid, cpp2::impl::in indent) -> void; -#line 3174 "reflect.h2" +#line 3885 "reflect.h2" auto sample_traverser(cpp2::impl::in qid, cpp2::impl::in indent) -> void; -#line 3190 "reflect.h2" +#line 3901 "reflect.h2" auto sample_traverser(cpp2::impl::in tid, cpp2::impl::in indent) -> void; -#line 3207 "reflect.h2" +#line 3918 "reflect.h2" auto sample_traverser(cpp2::impl::in primary, cpp2::impl::in indent) -> void; -#line 3227 "reflect.h2" +#line 3938 "reflect.h2" auto sample_traverser(cpp2::impl::in idexpr, cpp2::impl::in indent) -> void; -#line 3249 "reflect.h2" -class autodiff_impl { +#line 3960 "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_primal_higher_order; + public: std::string code_fwd_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_primal_higher_order_ = "", cpp2::impl::in code_fwd_higher_order_ = ""); + +#line 3989 "reflect.h2" + public: autodiff_special_func(autodiff_special_func const& that); +#line 3989 "reflect.h2" + public: auto operator=(autodiff_special_func const& that) -> autodiff_special_func& ; +#line 3989 "reflect.h2" + public: autodiff_special_func(autodiff_special_func&& that) noexcept; +#line 3989 "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 3994 "reflect.h2" +}; - private: int temporary_count {0}; +class autodiff_declared_variable { + public: std::string name {""}; + public: std::string decl {""}; + 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_member_); + +#line 4009 "reflect.h2" + public: autodiff_declared_variable(autodiff_declared_variable const& that); +#line 4009 "reflect.h2" + public: auto operator=(autodiff_declared_variable const& that) -> autodiff_declared_variable& ; +#line 4009 "reflect.h2" + public: autodiff_declared_variable(autodiff_declared_variable&& that) noexcept; +#line 4009 "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 4026 "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 3260 "reflect.h2" - public: [[nodiscard]] auto handle_expression_term([[maybe_unused]] auto& unnamed_param_2, auto const& term) & -> std::string; -#line 3272 "reflect.h2" - public: auto handle_expression_terms(auto& mf, cpp2::impl::in lhs, auto const& terms) & -> void; -#line 3565 "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 4036 "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 3590 "reflect.h2" +#line 4049 "reflect.h2" }; -auto autodiff(meta::type_declaration& t) -> void; +class autodiff_context { + private: int temporary_count {0}; -#line 3661 "reflect.h2" -using error_func = std::function x)>; +#line 4061 "reflect.h2" + public: std::vector special_funcs { + autodiff_special_func("sin", 1, false, + "sin(_a1_)", + "cos(_a1_) * _ad1_", + "sin(_a1_)", + "_ad1_.sin(_a1_)" + + ), + autodiff_special_func("cos", 1, false, + "cos(_a1_)", + "-sin(_a1_) * _ad1_", + "cos(_a1_)", + "_ad1_.cos(_a1_)" + ), + autodiff_special_func("exp", 1, false, + "exp(_a1_)", + "exp(_a1_) * _ad1_", + "exp(_a1_)", + "_ad1_.exp(_a1_)" + ), + autodiff_special_func("push_back", 1, true, + "_o_.push_back(_a1_);", + "_od_.push_back(_ad1_);")}; + +#line 4086 "reflect.h2" + public: std::string suffix {"_d"}; + private: int order {1}; + +#line 4090 "reflect.h2" + public: std::string ad_type {"double"}; + + public: std::map> declaration_map {}; + public: std::vector declaration_stack {}; + + public: auto add_variable_declaration(cpp2::impl::in name, cpp2::impl::in type, cpp2::impl::in is_member = false) & -> void; -#line 3665 "reflect.h2" -class expression_flags - { -private: cpp2::u8 _value; private: constexpr expression_flags(cpp2::impl::in _val); +#line 4099 "reflect.h2" + public: auto create_namespace_stack(cpp2::impl::in t) & -> void; -private: constexpr auto operator=(cpp2::impl::in _val) -> expression_flags& ; -public: constexpr auto operator|=(expression_flags const& that) & -> decltype(auto); -public: constexpr auto operator&=(expression_flags const& that) & -> decltype(auto); -public: constexpr auto operator^=(expression_flags const& that) & -> decltype(auto); -public: [[nodiscard]] constexpr auto operator|(expression_flags const& that) const& -> expression_flags; -public: [[nodiscard]] constexpr auto operator&(expression_flags const& that) const& -> expression_flags; -public: [[nodiscard]] constexpr auto operator^(expression_flags const& that) const& -> expression_flags; +#line 4116 "reflect.h2" + public: auto set_order(cpp2::impl::in new_order) & -> void; + +#line 4127 "reflect.h2" + public: [[nodiscard]] auto is_taylor() const& -> decltype(auto); + + public: [[nodiscard]] auto gen_temporary() & -> std::string; + +#line 4134 "reflect.h2" + public: [[nodiscard]] auto get_ad_type(cpp2::impl::in type) & -> std::string; +using lookup_declaration_ret = std::vector; + + +#line 4152 "reflect.h2" + public: [[nodiscard]] auto lookup_declaration(cpp2::impl::in decl_name) & -> lookup_declaration_ret; + +#line 4175 "reflect.h2" + public: [[nodiscard]] auto lookup_variable_declaration(cpp2::impl::in name) & -> autodiff_declared_variable; +using lookup_function_declaration_ret = std::vector; + + +#line 4192 "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 4202 "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 4212 "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; }; + + + +#line 4222 "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 4244 "reflect.h2" + public: auto add_as_differentiated(cpp2::impl::in t) & -> void; + +#line 4252 "reflect.h2" + public: auto add_for_differentiation(cpp2::impl::in t) & -> void; + +#line 4272 "reflect.h2" + public: [[nodiscard]] static auto is_in_list(cpp2::impl::in v, cpp2::impl::in> list) -> bool; + +#line 4282 "reflect.h2" + public: auto enter_function() & -> void; + +#line 4287 "reflect.h2" + public: auto leave_function() & -> void; + +#line 4291 "reflect.h2" + public: auto push_stack(cpp2::impl::in decl) & -> void; + +#line 4304 "reflect.h2" + public: auto pop_stack() & -> void; + +#line 4319 "reflect.h2" + public: auto finish() & -> void; + public: autodiff_context() = default; + public: autodiff_context(autodiff_context const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(autodiff_context const&) -> void = delete; + + +#line 4324 "reflect.h2" +}; + +class autodiff_handler_base { + public: autodiff_context* ctx; + + public: std::string diff {""}; + + public: autodiff_handler_base(autodiff_context* ctx_); +#line 4331 "reflect.h2" + public: auto operator=(autodiff_context* ctx_) -> autodiff_handler_base& ; + +#line 4335 "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 4338 "reflect.h2" +}; + +class autodiff_expression_handler: public simple_traverser, public autodiff_handler_base { + +#line 4344 "reflect.h2" + public: using base = simple_traverser; + + public: std::string primal_expr {""}; + public: std::string fwd_expr {""}; + + public: autodiff_expression_handler(autodiff_context* ctx_); + +#line 4353 "reflect.h2" + public: [[nodiscard]] auto add_suffix_if_not_wildcard(cpp2::impl::in lhs) const& -> std::string; + +#line 4362 "reflect.h2" + public: auto gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in rhs, cpp2::impl::in rhs_d) & -> void; + +#line 4366 "reflect.h2" + public: [[nodiscard]] auto gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d) & -> decltype(auto); + + public: [[nodiscard]] auto gen_assignment(cpp2::impl::in lhs) & -> decltype(auto); + +#line 4372 "reflect.h2" + public: auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in type, cpp2::impl::in type_d) & -> void; + +#line 4376 "reflect.h2" + public: [[nodiscard]] auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in type) & -> decltype(auto); + + public: [[nodiscard]] auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in type) & -> decltype(auto); + + public: [[nodiscard]] auto gen_declaration(cpp2::impl::in lhs, cpp2::impl::in type) & -> decltype(auto); + +#line 4385 "reflect.h2" + public: class primal_fwd_name { + public: std::string primal {""}; + public: std::string fwd {""}; + public: primal_fwd_name(auto&& primal_, auto&& fwd_) +CPP2_REQUIRES_ (std::is_convertible_v&> && std::is_convertible_v&>) ; +public: primal_fwd_name(); + +#line 4388 "reflect.h2" + }; + + public: [[nodiscard]] auto handle_expression_list(cpp2::impl::in list) & -> std::vector; + +#line 4399 "reflect.h2" + public: [[nodiscard]] auto handle_expression_term(auto const& term) & -> primal_fwd_name; + +#line 4450 "reflect.h2" + public: auto handle_function_call(cpp2::impl::in postfix, cpp2::impl::in has_return) & -> void; + +#line 4594 "reflect.h2" + public: [[nodiscard]] auto handle_special_function(cpp2::impl::in object, cpp2::impl::in object_d, cpp2::impl::in function_name, cpp2::impl::in> args) & -> bool; + +#line 4629 "reflect.h2" + public: auto traverse(cpp2::impl::in expr) -> void override; + +#line 4633 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4637 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4641 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4645 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4649 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4653 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4657 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4661 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4665 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4669 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4673 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4697 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 4754 "reflect.h2" + public: auto traverse(cpp2::impl::in isas) -> void override; + +#line 4758 "reflect.h2" + public: auto traverse(cpp2::impl::in prefix) -> void override; + +#line 4774 "reflect.h2" + public: auto traverse(cpp2::impl::in postfix) -> void override; + +#line 4814 "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 4845 "reflect.h2" +}; + +class autodiff_stmt_handler: public simple_traverser, public autodiff_handler_base { + +#line 4851 "reflect.h2" + public: using base = simple_traverser; + + private: meta::function_declaration mf; + + public: autodiff_stmt_handler(autodiff_context* ctx_, cpp2::impl::in mf_); + +#line 4860 "reflect.h2" + public: auto traverse(cpp2::impl::in decl) -> void override; + +#line 4865 "reflect.h2" + public: auto traverse(cpp2::impl::in f) -> void override; + +#line 4870 "reflect.h2" + public: auto traverse(cpp2::impl::in o) -> void override; + +#line 4899 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 4904 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 4909 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 4914 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 4922 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 4939 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 4989 "reflect.h2" + public: auto traverse(cpp2::impl::in stmt) -> void override; + +#line 5000 "reflect.h2" + public: auto traverse(cpp2::impl::in expr) -> void override; + +#line 5004 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5017 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5021 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5025 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5029 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5033 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5037 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5041 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5045 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5049 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5053 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5057 "reflect.h2" + public: auto traverse(cpp2::impl::in binexpr) -> void override; + +#line 5061 "reflect.h2" + public: auto traverse(cpp2::impl::in isas) -> void override; + +#line 5065 "reflect.h2" + public: auto traverse(cpp2::impl::in prefix) -> void override; + +#line 5070 "reflect.h2" + public: auto traverse(cpp2::impl::in postfix) -> void override; + +#line 5102 "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 5106 "reflect.h2" +}; + +class autodiff_declaration_handler: public simple_traverser, public autodiff_handler_base { + +#line 5112 "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(autodiff_context* ctx_, cpp2::impl::in decl_); + +#line 5124 "reflect.h2" + public: auto traverse(cpp2::impl::in decl) -> void override; + +#line 5129 "reflect.h2" + public: auto traverse(cpp2::impl::in f) -> void override; + +#line 5209 "reflect.h2" + public: auto traverse(cpp2::impl::in o) -> void override; + +#line 5237 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 5261 "reflect.h2" + public: auto traverse(cpp2::impl::in t) -> void override; + +#line 5266 "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 5269 "reflect.h2" +}; + +#line 5272 "reflect.h2" +auto autodiff(meta::type_declaration& t) -> void; + +#line 5360 "reflect.h2" +using error_func = std::function x)>; + +#line 5364 "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); +public: constexpr auto operator&=(expression_flags const& that) & -> decltype(auto); +public: constexpr auto operator^=(expression_flags const& that) & -> decltype(auto); +public: [[nodiscard]] constexpr auto operator|(expression_flags const& that) const& -> expression_flags; +public: [[nodiscard]] constexpr auto operator&(expression_flags const& that) const& -> expression_flags; +public: [[nodiscard]] constexpr auto operator^(expression_flags const& that) const& -> expression_flags; public: [[nodiscard]] constexpr auto has(expression_flags const& that) const& -> bool; public: constexpr auto set(expression_flags const& that) & -> void; public: constexpr auto clear(expression_flags const& that) & -> void; @@ -1502,20 +2140,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 3673 "reflect.h2" +#line 5372 "reflect.h2" }; -#line 3681 "reflect.h2" +#line 5380 "reflect.h2" class regex_token { public: std::string string_rep; public: regex_token(cpp2::impl::in str); -#line 3689 "reflect.h2" +#line 5388 "reflect.h2" public: explicit regex_token(); -#line 3694 "reflect.h2" +#line 5393 "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; @@ -1527,103 +2165,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 3700 "reflect.h2" +#line 5399 "reflect.h2" }; using token_ptr = std::shared_ptr; using token_vec = std::vector; -#line 3706 "reflect.h2" +#line 5405 "reflect.h2" // Adds a check in code generation. // class regex_token_check : public regex_token { -#line 3712 "reflect.h2" +#line 5411 "reflect.h2" private: std::string check; public: regex_token_check(cpp2::impl::in str, cpp2::impl::in check_); -#line 3719 "reflect.h2" +#line 5418 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 3723 "reflect.h2" +#line 5422 "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 3724 "reflect.h2" +#line 5423 "reflect.h2" }; -#line 3727 "reflect.h2" +#line 5426 "reflect.h2" // Adds code in code generation. // class regex_token_code : public regex_token { -#line 3733 "reflect.h2" +#line 5432 "reflect.h2" private: std::string code; public: regex_token_code(cpp2::impl::in str, cpp2::impl::in code_); -#line 3740 "reflect.h2" +#line 5439 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 3744 "reflect.h2" +#line 5443 "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 3745 "reflect.h2" +#line 5444 "reflect.h2" }; -#line 3748 "reflect.h2" +#line 5447 "reflect.h2" // Token that does not influence the matching. E.g. comment. // class regex_token_empty : public regex_token { -#line 3754 "reflect.h2" +#line 5453 "reflect.h2" public: regex_token_empty(cpp2::impl::in str); -#line 3758 "reflect.h2" +#line 5457 "reflect.h2" public: auto generate_code([[maybe_unused]] generation_context& unnamed_param_2) const -> void override; -#line 3762 "reflect.h2" +#line 5461 "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 3763 "reflect.h2" +#line 5462 "reflect.h2" }; -#line 3766 "reflect.h2" +#line 5465 "reflect.h2" // Represents a list of regex tokens as one token. // class regex_token_list : public regex_token { -#line 3772 "reflect.h2" +#line 5471 "reflect.h2" public: token_vec tokens; public: regex_token_list(cpp2::impl::in t); -#line 3779 "reflect.h2" +#line 5478 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 3785 "reflect.h2" +#line 5484 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; -#line 3791 "reflect.h2" +#line 5490 "reflect.h2" public: [[nodiscard]] static auto gen_string(cpp2::impl::in vec) -> std::string; -#line 3799 "reflect.h2" +#line 5498 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; public: virtual ~regex_token_list() noexcept; @@ -1631,10 +2269,10 @@ class regex_token_list public: auto operator=(regex_token_list const&) -> void = delete; -#line 3811 "reflect.h2" +#line 5510 "reflect.h2" }; -#line 3814 "reflect.h2" +#line 5513 "reflect.h2" // // Parse and generation context. // @@ -1650,33 +2288,33 @@ class parse_context_group_state // Start a new alternative. public: auto next_alternative() & -> void; -#line 3834 "reflect.h2" +#line 5533 "reflect.h2" // Swap this state with the other one. NOLINTNEXTLINE(performance-noexcept-swap) public: auto swap(parse_context_group_state& t) & -> void; -#line 3841 "reflect.h2" +#line 5540 "reflect.h2" // Convert this state into a regex token. public: [[nodiscard]] auto get_as_token() & -> token_ptr; -#line 3853 "reflect.h2" +#line 5552 "reflect.h2" // Add a token to the current matcher list. public: auto add(cpp2::impl::in token) & -> void; -#line 3858 "reflect.h2" +#line 5557 "reflect.h2" // True if current matcher list is empty. public: [[nodiscard]] auto empty() const& -> bool; -#line 3862 "reflect.h2" +#line 5561 "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 3876 "reflect.h2" +#line 5575 "reflect.h2" }; -#line 3879 "reflect.h2" +#line 5578 "reflect.h2" // State for the branch reset. Takes care of the group numbering. See '(|)'. // class parse_context_branch_reset_state @@ -1689,25 +2327,25 @@ class parse_context_branch_reset_state // Next group identifier. public: [[nodiscard]] auto next() & -> int; -#line 3897 "reflect.h2" +#line 5596 "reflect.h2" // Set next group identifier. public: auto set_next(cpp2::impl::in g) & -> void; -#line 3903 "reflect.h2" +#line 5602 "reflect.h2" // Start a new alternative branch. public: auto next_alternative() & -> void; -#line 3910 "reflect.h2" +#line 5609 "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 3917 "reflect.h2" +#line 5616 "reflect.h2" }; -#line 3920 "reflect.h2" +#line 5619 "reflect.h2" // Context during parsing of the regular expressions. // // Keeps track of the distributed group identifiers, current parsed group and branch resets. @@ -1723,7 +2361,7 @@ class parse_context private: parse_context_group_state cur_group_state {}; private: parse_context_branch_reset_state cur_branch_reset_state {}; -#line 3936 "reflect.h2" +#line 5635 "reflect.h2" public: std::map named_groups {}; private: error_func error_out; // TODO: Declaring std::function fails for cpp2. @@ -1731,64 +2369,64 @@ class parse_context public: parse_context(cpp2::impl::in r, auto const& e); -#line 3947 "reflect.h2" +#line 5646 "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 3960 "reflect.h2" +#line 5659 "reflect.h2" // `old_state` argument needs to be from start group. public: [[nodiscard]] auto end_group(cpp2::impl::in old_state) & -> token_ptr; -#line 3968 "reflect.h2" +#line 5667 "reflect.h2" public: [[nodiscard]] auto get_modifiers() const& -> expression_flags; -#line 3972 "reflect.h2" +#line 5671 "reflect.h2" public: auto set_modifiers(cpp2::impl::in mod) & -> void; -#line 3976 "reflect.h2" +#line 5675 "reflect.h2" // Branch reset management functions // public: [[nodiscard]] auto branch_reset_new_state() & -> parse_context_branch_reset_state; -#line 3988 "reflect.h2" +#line 5687 "reflect.h2" public: auto branch_reset_restore_state(cpp2::impl::in old_state) & -> void; -#line 3995 "reflect.h2" +#line 5694 "reflect.h2" public: auto next_alternative() & -> void; -#line 4001 "reflect.h2" +#line 5700 "reflect.h2" // Regex token management // public: auto add_token(cpp2::impl::in token) & -> void; -#line 4007 "reflect.h2" +#line 5706 "reflect.h2" public: [[nodiscard]] auto has_token() const& -> bool; -#line 4011 "reflect.h2" +#line 5710 "reflect.h2" public: [[nodiscard]] auto pop_token() & -> token_ptr; -#line 4022 "reflect.h2" +#line 5721 "reflect.h2" public: [[nodiscard]] auto get_as_token() & -> token_ptr; -#line 4026 "reflect.h2" +#line 5725 "reflect.h2" // Group management // public: [[nodiscard]] auto get_cur_group() const& -> int; -#line 4032 "reflect.h2" +#line 5731 "reflect.h2" public: [[nodiscard]] auto next_group() & -> int; -#line 4036 "reflect.h2" +#line 5735 "reflect.h2" public: auto set_named_group(cpp2::impl::in name, cpp2::impl::in id) & -> void; -#line 4043 "reflect.h2" +#line 5742 "reflect.h2" public: [[nodiscard]] auto get_named_group(cpp2::impl::in name) const& -> int; -#line 4054 "reflect.h2" +#line 5753 "reflect.h2" // Position management functions // public: [[nodiscard]] auto current() const& -> char; @@ -1796,51 +2434,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 4098 "reflect.h2" +#line 5797 "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 4110 "reflect.h2" +#line 5809 "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 4123 "reflect.h2" +#line 5822 "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 4146 "reflect.h2" +#line 5845 "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 4163 "reflect.h2" +#line 5862 "reflect.h2" public: [[nodiscard]] auto grab_number() & -> std::string; -#line 4184 "reflect.h2" +#line 5883 "reflect.h2" private: [[nodiscard]] auto peek_impl(cpp2::impl::in in_class) const& -> char; -#line 4194 "reflect.h2" +#line 5893 "reflect.h2" public: [[nodiscard]] auto peek() const& -> decltype(auto); public: [[nodiscard]] auto peek_in_class() const& -> decltype(auto); -#line 4198 "reflect.h2" +#line 5897 "reflect.h2" // Parsing functions // public: [[nodiscard]] auto parser_group_modifiers(cpp2::impl::in change_str, expression_flags& parser_modifiers) & -> bool; -#line 4254 "reflect.h2" +#line 5953 "reflect.h2" public: [[nodiscard]] auto parse_until(cpp2::impl::in term) & -> bool; -#line 4293 "reflect.h2" +#line 5992 "reflect.h2" public: [[nodiscard]] auto parse(cpp2::impl::in modifiers) & -> bool; -#line 4308 "reflect.h2" +#line 6007 "reflect.h2" // Misc functions public: [[nodiscard]] auto get_pos() const& -> decltype(auto); @@ -1852,10 +2490,10 @@ class parse_context public: auto operator=(parse_context const&) -> void = delete; -#line 4319 "reflect.h2" +#line 6018 "reflect.h2" }; -#line 4322 "reflect.h2" +#line 6021 "reflect.h2" // Context for one function generation. Generation of functions can be interleaved, // therefore we buffer the code for one function here. // @@ -1865,16 +2503,16 @@ class generation_function_context { public: auto add_tabs(cpp2::impl::in c) & -> void; -#line 4336 "reflect.h2" +#line 6035 "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 4339 "reflect.h2" +#line 6038 "reflect.h2" }; -#line 4342 "reflect.h2" +#line 6041 "reflect.h2" // Context for generating the state machine. class generation_context { @@ -1894,68 +2532,68 @@ class generation_context // Add code line. public: auto add(cpp2::impl::in s) & -> void; -#line 4364 "reflect.h2" +#line 6063 "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 4370 "reflect.h2" +#line 6069 "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 4379 "reflect.h2" +#line 6078 "reflect.h2" protected: auto start_func_named(cpp2::impl::in name) & -> void; -#line 4390 "reflect.h2" +#line 6089 "reflect.h2" protected: [[nodiscard]] auto start_func() & -> std::string; -#line 4397 "reflect.h2" +#line 6096 "reflect.h2" protected: auto end_func_statefull(cpp2::impl::in s) & -> void; -#line 4417 "reflect.h2" +#line 6116 "reflect.h2" // Generate the function for a token. public: [[nodiscard]] auto generate_func(cpp2::impl::in token) & -> std::string; -#line 4427 "reflect.h2" +#line 6126 "reflect.h2" // Generate the reset for a list of group identifiers. public: [[nodiscard]] auto generate_reset(cpp2::impl::in> groups) & -> std::string; -#line 4450 "reflect.h2" +#line 6149 "reflect.h2" // Name generation // protected: [[nodiscard]] auto gen_func_name() & -> std::string; -#line 4458 "reflect.h2" +#line 6157 "reflect.h2" public: [[nodiscard]] auto next_func_name() & -> std::string; -#line 4462 "reflect.h2" +#line 6161 "reflect.h2" protected: [[nodiscard]] auto gen_reset_func_name() & -> std::string; -#line 4468 "reflect.h2" +#line 6167 "reflect.h2" public: [[nodiscard]] auto gen_temp() & -> std::string; -#line 4474 "reflect.h2" +#line 6173 "reflect.h2" // Context management // public: [[nodiscard]] auto new_context() & -> generation_function_context*; -#line 4484 "reflect.h2" +#line 6183 "reflect.h2" public: auto finish_context() & -> void; -#line 4492 "reflect.h2" +#line 6191 "reflect.h2" // Misc functions // private: [[nodiscard]] auto get_current() & -> generation_function_context*; -#line 4498 "reflect.h2" +#line 6197 "reflect.h2" private: [[nodiscard]] auto get_base() & -> generation_function_context*; -#line 4502 "reflect.h2" +#line 6201 "reflect.h2" public: [[nodiscard]] auto get_entry_func() const& -> std::string; -#line 4506 "reflect.h2" +#line 6205 "reflect.h2" public: [[nodiscard]] auto create_named_group_lookup(cpp2::impl::in> named_groups) const& -> std::string; -#line 4530 "reflect.h2" +#line 6229 "reflect.h2" // Run the generation for the token. public: [[nodiscard]] auto run(cpp2::impl::in token) & -> std::string; public: generation_context() = default; @@ -1963,7 +2601,7 @@ class generation_context public: auto operator=(generation_context const&) -> void = delete; -#line 4536 "reflect.h2" +#line 6235 "reflect.h2" }; // Regex syntax: | Example: ab|ba @@ -1983,27 +2621,27 @@ class alternative_token public: auto operator=(alternative_token const&) -> void = delete; -#line 4555 "reflect.h2" +#line 6254 "reflect.h2" }; class alternative_token_gen : public regex_token { -#line 4561 "reflect.h2" +#line 6260 "reflect.h2" private: token_vec alternatives; public: alternative_token_gen(cpp2::impl::in a); -#line 4568 "reflect.h2" +#line 6267 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 4585 "reflect.h2" +#line 6284 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; -#line 4592 "reflect.h2" +#line 6291 "reflect.h2" public: [[nodiscard]] static auto gen_string(cpp2::impl::in a) -> std::string; -#line 4605 "reflect.h2" +#line 6304 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; public: virtual ~alternative_token_gen() noexcept; @@ -2011,19 +2649,19 @@ class alternative_token_gen public: auto operator=(alternative_token_gen const&) -> void = delete; -#line 4617 "reflect.h2" +#line 6316 "reflect.h2" }; -#line 4620 "reflect.h2" +#line 6319 "reflect.h2" // Regex syntax: . // class any_token : public regex_token_check { -#line 4626 "reflect.h2" +#line 6325 "reflect.h2" public: any_token(cpp2::impl::in single_line); -#line 4630 "reflect.h2" +#line 6329 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; public: virtual ~any_token() noexcept; @@ -2031,7 +2669,7 @@ class any_token public: auto operator=(any_token const&) -> void = delete; -#line 4635 "reflect.h2" +#line 6334 "reflect.h2" }; // Regex syntax: (?>) Example: a(?>bc|c)c @@ -2039,17 +2677,17 @@ class any_token class atomic_group_token : public regex_token { -#line 4643 "reflect.h2" +#line 6342 "reflect.h2" public: token_ptr inner_token {nullptr}; public: explicit atomic_group_token(); public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 4654 "reflect.h2" +#line 6353 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 4662 "reflect.h2" +#line 6361 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~atomic_group_token() noexcept; @@ -2057,7 +2695,7 @@ class atomic_group_token public: auto operator=(atomic_group_token const&) -> void = delete; -#line 4665 "reflect.h2" +#line 6364 "reflect.h2" }; // Regex syntax: a @@ -2065,34 +2703,34 @@ class atomic_group_token class char_token : public regex_token { -#line 4673 "reflect.h2" +#line 6372 "reflect.h2" private: std::string token; private: bool ignore_case; public: char_token(cpp2::impl::in t, cpp2::impl::in ignore_case_); -#line 4682 "reflect.h2" +#line 6381 "reflect.h2" public: char_token(cpp2::impl::in t, cpp2::impl::in ignore_case_); -#line 4688 "reflect.h2" +#line 6387 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 4692 "reflect.h2" +#line 6391 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 4715 "reflect.h2" +#line 6414 "reflect.h2" public: auto gen_case_insensitive(cpp2::impl::in lower, cpp2::impl::in upper, generation_context& ctx) const& -> void; -#line 4736 "reflect.h2" +#line 6435 "reflect.h2" public: auto gen_case_sensitive(generation_context& ctx) const& -> void; -#line 4754 "reflect.h2" +#line 6453 "reflect.h2" public: [[nodiscard]] auto add_escapes(std::string str) const& -> std::string; -#line 4769 "reflect.h2" +#line 6468 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 4775 "reflect.h2" +#line 6474 "reflect.h2" public: auto append(char_token const& that) & -> void; public: virtual ~char_token() noexcept; @@ -2100,33 +2738,33 @@ class char_token public: auto operator=(char_token const&) -> void = delete; -#line 4779 "reflect.h2" +#line 6478 "reflect.h2" }; -#line 4782 "reflect.h2" +#line 6481 "reflect.h2" // Regex syntax: [] Example: [abcx-y[:digits:]] // class class_token : public regex_token { -#line 4788 "reflect.h2" +#line 6487 "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 4800 "reflect.h2" +#line 6499 "reflect.h2" // TODO: Rework class generation: Generate check functions for classes. public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 4926 "reflect.h2" +#line 6625 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 4935 "reflect.h2" +#line 6634 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 4940 "reflect.h2" +#line 6639 "reflect.h2" private: [[nodiscard]] static auto create_matcher(cpp2::impl::in name, cpp2::impl::in template_arguments) -> std::string; public: virtual ~class_token() noexcept; @@ -2134,20 +2772,20 @@ class class_token public: auto operator=(class_token const&) -> void = delete; -#line 4947 "reflect.h2" +#line 6646 "reflect.h2" }; -#line 4950 "reflect.h2" +#line 6649 "reflect.h2" // Regex syntax: \a or \n or \[ // [[nodiscard]] auto escape_token_parse(parse_context& ctx) -> token_ptr; -#line 4991 "reflect.h2" +#line 6690 "reflect.h2" // Regex syntax: \K Example: ab\Kcd // [[nodiscard]] auto global_group_reset_token_parse(parse_context& ctx) -> token_ptr; -#line 5002 "reflect.h2" +#line 6701 "reflect.h2" // Regex syntax: \ Example: \1 // \g{name_or_number} // \k{name_or_number} @@ -2157,20 +2795,20 @@ class class_token class group_ref_token : public regex_token { -#line 5012 "reflect.h2" +#line 6711 "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 5024 "reflect.h2" +#line 6723 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 5125 "reflect.h2" +#line 6824 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5129 "reflect.h2" +#line 6828 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; public: virtual ~group_ref_token() noexcept; @@ -2178,10 +2816,10 @@ class group_ref_token public: auto operator=(group_ref_token const&) -> void = delete; -#line 5132 "reflect.h2" +#line 6831 "reflect.h2" }; -#line 5135 "reflect.h2" +#line 6834 "reflect.h2" // Regex syntax: () Example: (abc) // (?:) (?i:abc) @@ -2195,29 +2833,29 @@ class group_ref_token class group_token : public regex_token { -#line 5149 "reflect.h2" +#line 6848 "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 5171 "reflect.h2" +#line 6870 "reflect.h2" public: [[nodiscard]] static auto parse_atomic_pattern(parse_context& ctx, cpp2::impl::in syntax) -> token_ptr; -#line 5185 "reflect.h2" +#line 6884 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 5344 "reflect.h2" +#line 7043 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5352 "reflect.h2" +#line 7051 "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 5370 "reflect.h2" +#line 7069 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 5401 "reflect.h2" +#line 7100 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~group_token() noexcept; @@ -2226,25 +2864,25 @@ class group_token public: auto operator=(group_token const&) -> void = delete; -#line 5408 "reflect.h2" +#line 7107 "reflect.h2" }; -#line 5411 "reflect.h2" +#line 7110 "reflect.h2" // Regex syntax: \x or \x{} Example: \x{62} // [[nodiscard]] auto hexadecimal_token_parse(parse_context& ctx) -> token_ptr; -#line 5452 "reflect.h2" +#line 7151 "reflect.h2" // Regex syntax: $ Example: aa$ // [[nodiscard]] auto line_end_token_parse(parse_context& ctx) -> token_ptr; -#line 5472 "reflect.h2" +#line 7171 "reflect.h2" // Regex syntax: ^ Example: ^aa // [[nodiscard]] auto line_start_token_parse(parse_context& ctx) -> token_ptr; -#line 5488 "reflect.h2" +#line 7187 "reflect.h2" // Regex syntax: (?=) or (?!) or (*pla), etc. Example: (?=AA) // // Parsed in group_token. @@ -2252,20 +2890,20 @@ class group_token class lookahead_lookbehind_token : public regex_token { -#line 5496 "reflect.h2" +#line 7195 "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 5505 "reflect.h2" +#line 7204 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 5516 "reflect.h2" +#line 7215 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5523 "reflect.h2" +#line 7222 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~lookahead_lookbehind_token() noexcept; @@ -2273,26 +2911,26 @@ class lookahead_lookbehind_token public: auto operator=(lookahead_lookbehind_token const&) -> void = delete; -#line 5526 "reflect.h2" +#line 7225 "reflect.h2" }; -#line 5529 "reflect.h2" +#line 7228 "reflect.h2" // Named character classes // [[nodiscard]] auto named_class_token_parse(parse_context& ctx) -> token_ptr; -#line 5557 "reflect.h2" +#line 7256 "reflect.h2" // Regex syntax: \o{} Example: \o{142} // [[nodiscard]] auto octal_token_parse(parse_context& ctx) -> token_ptr; -#line 5585 "reflect.h2" +#line 7284 "reflect.h2" // Regex syntax: {min, max} Example: a{2,4} // class range_token : public regex_token { -#line 5591 "reflect.h2" +#line 7290 "reflect.h2" protected: int min_count {-1}; protected: int max_count {-1}; protected: int kind {range_flags::greedy}; @@ -2302,22 +2940,22 @@ class range_token public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; -#line 5671 "reflect.h2" +#line 7370 "reflect.h2" public: auto parse_modifier(parse_context& ctx) & -> void; -#line 5683 "reflect.h2" +#line 7382 "reflect.h2" public: [[nodiscard]] auto gen_mod_string() const& -> std::string; -#line 5696 "reflect.h2" +#line 7395 "reflect.h2" public: [[nodiscard]] auto gen_range_string() const& -> std::string; -#line 5715 "reflect.h2" +#line 7414 "reflect.h2" public: [[nodiscard]] auto reverse() const -> token_ptr override; -#line 5725 "reflect.h2" +#line 7424 "reflect.h2" public: auto generate_code(generation_context& ctx) const -> void override; -#line 5736 "reflect.h2" +#line 7435 "reflect.h2" public: auto add_groups(std::set& groups) const -> void override; public: virtual ~range_token() noexcept; @@ -2325,16 +2963,16 @@ class range_token public: auto operator=(range_token const&) -> void = delete; -#line 5739 "reflect.h2" +#line 7438 "reflect.h2" }; -#line 5742 "reflect.h2" +#line 7441 "reflect.h2" // Regex syntax: *, +, or ? Example: aa* // class special_range_token : public range_token { -#line 5748 "reflect.h2" +#line 7447 "reflect.h2" public: [[nodiscard]] static auto parse(parse_context& ctx) -> token_ptr; public: virtual ~special_range_token() noexcept; @@ -2343,7 +2981,7 @@ class special_range_token public: auto operator=(special_range_token const&) -> void = delete; -#line 5778 "reflect.h2" +#line 7477 "reflect.h2" }; // Regex syntax: \G Example: \Gaa @@ -2352,14 +2990,14 @@ class special_range_token // [[nodiscard]] auto start_match_parse(parse_context& ctx) -> token_ptr; -#line 5800 "reflect.h2" +#line 7499 "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 5822 "reflect.h2" +#line 7521 "reflect.h2" //----------------------------------------------------------------------- // // Parser for regular expression. @@ -2380,24 +3018,24 @@ template class regex_generator public: regex_generator(cpp2::impl::in r, Error_out const& e); -#line 5845 "reflect.h2" +#line 7544 "reflect.h2" public: [[nodiscard]] auto parse() & -> std::string; -#line 5880 "reflect.h2" +#line 7579 "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 5894 "reflect.h2" +#line 7593 "reflect.h2" }; template [[nodiscard]] auto generate_regex(cpp2::impl::in regex, Err const& err) -> std::string; -#line 5906 "reflect.h2" +#line 7605 "reflect.h2" auto regex_gen(meta::type_declaration& t) -> void; -#line 5961 "reflect.h2" +#line 7660 "reflect.h2" //----------------------------------------------------------------------- // // apply_metafunctions @@ -2408,7 +3046,7 @@ auto regex_gen(meta::type_declaration& t) -> void; auto const& error ) -> bool; -#line 6087 "reflect.h2" +#line 7786 "reflect.h2" } } @@ -2646,15 +3284,20 @@ compiler_services::compiler_services(compiler_services&& that) noexcept #line 208 "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 210 "reflect.h2" + template [[nodiscard]] auto reflection_base::is_same(cpp2::impl::in o) const& -> bool { return n == o.n; }// Test pointers +#line 211 "reflect.h2" + template template [[nodiscard]] auto reflection_base::is_same(reflection_base const& o) 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 212 "reflect.h2" +#line 215 "reflect.h2" //----------------------------------------------------------------------- // // Declarations @@ -2666,126 +3309,126 @@ template reflection_base::reflection_base(reflection_base&& that // All declarations // -#line 226 "reflect.h2" +#line 229 "reflect.h2" declaration::declaration( declaration_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 231 "reflect.h2" +#line 234 "reflect.h2" { } -#line 235 "reflect.h2" +#line 238 "reflect.h2" [[nodiscard]] auto declaration::is_public() const& -> bool { return CPP2_UFCS(is_public)((*cpp2::impl::assert_not_null(n))); } -#line 236 "reflect.h2" +#line 239 "reflect.h2" [[nodiscard]] auto declaration::is_protected() const& -> bool { return CPP2_UFCS(is_protected)((*cpp2::impl::assert_not_null(n))); } -#line 237 "reflect.h2" +#line 240 "reflect.h2" [[nodiscard]] auto declaration::is_private() const& -> bool { return CPP2_UFCS(is_private)((*cpp2::impl::assert_not_null(n))); } -#line 238 "reflect.h2" +#line 241 "reflect.h2" [[nodiscard]] auto declaration::is_default_access() const& -> bool { return CPP2_UFCS(is_default_access)((*cpp2::impl::assert_not_null(n))); } -#line 240 "reflect.h2" +#line 243 "reflect.h2" [[nodiscard]] auto declaration::default_to_public() & -> decltype(auto) { return static_cast(CPP2_UFCS(make_public)((*cpp2::impl::assert_not_null(n)))); } -#line 241 "reflect.h2" +#line 244 "reflect.h2" [[nodiscard]] auto declaration::default_to_protected() & -> decltype(auto) { return static_cast(CPP2_UFCS(make_protected)((*cpp2::impl::assert_not_null(n)))); } -#line 242 "reflect.h2" +#line 245 "reflect.h2" [[nodiscard]] auto declaration::default_to_private() & -> decltype(auto) { return static_cast(CPP2_UFCS(make_private)((*cpp2::impl::assert_not_null(n)))); } -#line 244 "reflect.h2" +#line 247 "reflect.h2" [[nodiscard]] auto declaration::make_public() & -> bool { return CPP2_UFCS(make_public)((*cpp2::impl::assert_not_null(n))); } -#line 245 "reflect.h2" +#line 248 "reflect.h2" [[nodiscard]] auto declaration::make_protected() & -> bool { return CPP2_UFCS(make_protected)((*cpp2::impl::assert_not_null(n))); } -#line 246 "reflect.h2" +#line 249 "reflect.h2" [[nodiscard]] auto declaration::make_private() & -> bool { return CPP2_UFCS(make_private)((*cpp2::impl::assert_not_null(n))); } -#line 248 "reflect.h2" +#line 251 "reflect.h2" [[nodiscard]] auto declaration::has_name() const& -> bool { return CPP2_UFCS(has_name)((*cpp2::impl::assert_not_null(n))); } -#line 249 "reflect.h2" +#line 252 "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 251 "reflect.h2" +#line 254 "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 256 "reflect.h2" +#line 259 "reflect.h2" [[nodiscard]] auto declaration::has_initializer() const& -> bool { return CPP2_UFCS(has_initializer)((*cpp2::impl::assert_not_null(n))); } -#line 258 "reflect.h2" +#line 261 "reflect.h2" [[nodiscard]] auto declaration::get_initializer() const& -> statement { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(n)).initializer), (*this) }; } -#line 260 "reflect.h2" +#line 263 "reflect.h2" [[nodiscard]] auto declaration::is_global() const& -> bool { return CPP2_UFCS(is_global)((*cpp2::impl::assert_not_null(n))); } -#line 261 "reflect.h2" +#line 264 "reflect.h2" [[nodiscard]] auto declaration::is_function() const& -> bool { return CPP2_UFCS(is_function)((*cpp2::impl::assert_not_null(n))); } -#line 262 "reflect.h2" +#line 265 "reflect.h2" [[nodiscard]] auto declaration::is_object() const& -> bool { return CPP2_UFCS(is_object)((*cpp2::impl::assert_not_null(n))); } -#line 263 "reflect.h2" +#line 266 "reflect.h2" [[nodiscard]] auto declaration::is_base_object() const& -> bool { return CPP2_UFCS(is_base_object)((*cpp2::impl::assert_not_null(n))); } -#line 264 "reflect.h2" +#line 267 "reflect.h2" [[nodiscard]] auto declaration::is_member_object() const& -> bool { return CPP2_UFCS(is_member_object)((*cpp2::impl::assert_not_null(n))); } -#line 265 "reflect.h2" +#line 268 "reflect.h2" [[nodiscard]] auto declaration::is_type() const& -> bool { return CPP2_UFCS(is_type)((*cpp2::impl::assert_not_null(n))); } -#line 266 "reflect.h2" +#line 269 "reflect.h2" [[nodiscard]] auto declaration::is_namespace() const& -> bool { return CPP2_UFCS(is_namespace)((*cpp2::impl::assert_not_null(n))); } -#line 267 "reflect.h2" +#line 270 "reflect.h2" [[nodiscard]] auto declaration::is_alias() const& -> bool { return CPP2_UFCS(is_alias)((*cpp2::impl::assert_not_null(n))); } -#line 269 "reflect.h2" +#line 272 "reflect.h2" [[nodiscard]] auto declaration::is_type_alias() const& -> bool { return CPP2_UFCS(is_type_alias)((*cpp2::impl::assert_not_null(n))); } -#line 270 "reflect.h2" +#line 273 "reflect.h2" [[nodiscard]] auto declaration::is_namespace_alias() const& -> bool { return CPP2_UFCS(is_namespace_alias)((*cpp2::impl::assert_not_null(n))); } -#line 271 "reflect.h2" +#line 274 "reflect.h2" [[nodiscard]] auto declaration::is_object_alias() const& -> bool { return CPP2_UFCS(is_object_alias)((*cpp2::impl::assert_not_null(n))); } -#line 273 "reflect.h2" +#line 276 "reflect.h2" [[nodiscard]] auto declaration::is_function_expression() const& -> bool { return CPP2_UFCS(is_function_expression)((*cpp2::impl::assert_not_null(n))); } -#line 275 "reflect.h2" +#line 278 "reflect.h2" [[nodiscard]] auto declaration::as_function() const& -> function_declaration { return { n, (*this) }; } -#line 276 "reflect.h2" +#line 279 "reflect.h2" [[nodiscard]] auto declaration::as_object() const& -> object_declaration { return { n, (*this) }; } -#line 277 "reflect.h2" +#line 280 "reflect.h2" [[nodiscard]] auto declaration::as_type() const& -> type_declaration { return { n, (*this) }; } -#line 278 "reflect.h2" +#line 281 "reflect.h2" [[nodiscard]] auto declaration::as_nonglobal_namespace() const& -> namespace_declaration { return { n, (*this) }; } -#line 279 "reflect.h2" +#line 282 "reflect.h2" [[nodiscard]] auto declaration::as_alias() const& -> alias_declaration { return { n, (*this) }; } -#line 281 "reflect.h2" +#line 284 "reflect.h2" [[nodiscard]] auto declaration::get_parent() const& -> declaration { return declaration((*cpp2::impl::assert_not_null(n)).parent_declaration, (*this)); } -#line 283 "reflect.h2" +#line 286 "reflect.h2" [[nodiscard]] auto declaration::parent_is_function() const& -> bool { return CPP2_UFCS(parent_is_function)((*cpp2::impl::assert_not_null(n))); } -#line 284 "reflect.h2" +#line 287 "reflect.h2" [[nodiscard]] auto declaration::parent_is_object() const& -> bool { return CPP2_UFCS(parent_is_object)((*cpp2::impl::assert_not_null(n))); } -#line 285 "reflect.h2" +#line 288 "reflect.h2" [[nodiscard]] auto declaration::parent_is_type() const& -> bool { return CPP2_UFCS(parent_is_type)((*cpp2::impl::assert_not_null(n))); } -#line 286 "reflect.h2" +#line 289 "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 287 "reflect.h2" +#line 290 "reflect.h2" [[nodiscard]] auto declaration::parent_is_alias() const& -> bool { return CPP2_UFCS(parent_is_alias)((*cpp2::impl::assert_not_null(n))); } -#line 289 "reflect.h2" +#line 292 "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 290 "reflect.h2" +#line 293 "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 291 "reflect.h2" +#line 294 "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 293 "reflect.h2" +#line 296 "reflect.h2" [[nodiscard]] auto declaration::parent_is_polymorphic() const& -> bool { return CPP2_UFCS(parent_is_polymorphic)((*cpp2::impl::assert_not_null(n))); } -#line 295 "reflect.h2" +#line 298 "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 298 "reflect.h2" +#line 301 "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 } @@ -2796,111 +3439,111 @@ declaration::declaration(declaration const& that) declaration::declaration(declaration&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 304 "reflect.h2" +#line 307 "reflect.h2" //----------------------------------------------------------------------- // Function declarations // -#line 311 "reflect.h2" +#line 314 "reflect.h2" function_declaration::function_declaration( declaration_node* n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 316 "reflect.h2" +#line 319 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_function)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } } -#line 321 "reflect.h2" +#line 324 "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 322 "reflect.h2" +#line 325 "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 323 "reflect.h2" +#line 326 "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 324 "reflect.h2" +#line 327 "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 325 "reflect.h2" +#line 328 "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 326 "reflect.h2" +#line 329 "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 327 "reflect.h2" +#line 330 "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 328 "reflect.h2" +#line 331 "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 329 "reflect.h2" +#line 332 "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 330 "reflect.h2" +#line 333 "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 331 "reflect.h2" +#line 334 "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 332 "reflect.h2" +#line 335 "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 334 "reflect.h2" +#line 337 "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 336 "reflect.h2" +#line 339 "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 337 "reflect.h2" +#line 340 "reflect.h2" [[nodiscard]] auto function_declaration::is_virtual() const& -> bool { return CPP2_UFCS(is_virtual_function)((*cpp2::impl::assert_not_null(n))); } -#line 338 "reflect.h2" +#line 341 "reflect.h2" [[nodiscard]] auto function_declaration::is_defaultable() const& -> bool { return CPP2_UFCS(is_defaultable_function)((*cpp2::impl::assert_not_null(n))); } -#line 339 "reflect.h2" +#line 342 "reflect.h2" [[nodiscard]] auto function_declaration::is_constructor() const& -> bool { return CPP2_UFCS(is_constructor)((*cpp2::impl::assert_not_null(n))); } -#line 340 "reflect.h2" +#line 343 "reflect.h2" [[nodiscard]] auto function_declaration::is_default_constructor() const& -> bool { return CPP2_UFCS(is_default_constructor)((*cpp2::impl::assert_not_null(n))); } -#line 341 "reflect.h2" +#line 344 "reflect.h2" [[nodiscard]] auto function_declaration::is_move() const& -> bool { return CPP2_UFCS(is_move)((*cpp2::impl::assert_not_null(n))); } -#line 342 "reflect.h2" +#line 345 "reflect.h2" [[nodiscard]] auto function_declaration::is_swap() const& -> bool { return CPP2_UFCS(is_swap)((*cpp2::impl::assert_not_null(n))); } -#line 343 "reflect.h2" +#line 346 "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 344 "reflect.h2" +#line 347 "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 345 "reflect.h2" +#line 348 "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 346 "reflect.h2" +#line 349 "reflect.h2" [[nodiscard]] auto function_declaration::is_assignment() const& -> bool { return CPP2_UFCS(is_assignment)((*cpp2::impl::assert_not_null(n))); } -#line 347 "reflect.h2" +#line 350 "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 348 "reflect.h2" +#line 351 "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 349 "reflect.h2" +#line 352 "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 350 "reflect.h2" +#line 353 "reflect.h2" [[nodiscard]] auto function_declaration::is_destructor() const& -> bool { return CPP2_UFCS(is_destructor)((*cpp2::impl::assert_not_null(n))); } -#line 352 "reflect.h2" +#line 355 "reflect.h2" [[nodiscard]] auto function_declaration::is_copy_or_move() const& -> bool { return is_constructor_with_that() || is_assignment_with_that(); } -#line 354 "reflect.h2" +#line 357 "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 355 "reflect.h2" +#line 358 "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 356 "reflect.h2" +#line 359 "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 357 "reflect.h2" +#line 360 "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 359 "reflect.h2" +#line 362 "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 361 "reflect.h2" +#line 364 "reflect.h2" [[nodiscard]] auto function_declaration::get_body() const& -> statement { return { CPP2_UFCS(get_function_body)((*cpp2::impl::assert_not_null(n))), (*this) }; } -#line 362 "reflect.h2" +#line 365 "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 363 "reflect.h2" +#line 366 "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 364 "reflect.h2" +#line 367 "reflect.h2" [[nodiscard]] auto function_declaration::get_signature() const& -> std::string { return CPP2_UFCS(signature_to_string)((*cpp2::impl::assert_not_null(n))); } -#line 366 "reflect.h2" +#line 369 "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 368 "reflect.h2" +#line 371 "reflect.h2" [[nodiscard]] auto function_declaration::get_parameters() const& -> std::vector { @@ -2911,7 +3554,7 @@ declaration::declaration(declaration&& that) noexcept return ret; } -#line 378 "reflect.h2" +#line 381 "reflect.h2" [[nodiscard]] auto function_declaration::get_returns() const& -> std::vector { @@ -2924,20 +3567,20 @@ declaration::declaration(declaration&& that) noexcept // Modifying operations // -#line 390 "reflect.h2" +#line 393 "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 392 "reflect.h2" +#line 395 "reflect.h2" [[nodiscard]] auto function_declaration::make_virtual() & -> bool { return CPP2_UFCS(make_function_virtual)((*cpp2::impl::assert_not_null(n))); } -#line 394 "reflect.h2" +#line 397 "reflect.h2" auto function_declaration::add_initializer(cpp2::impl::in source) & -> void -#line 397 "reflect.h2" +#line 400 "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 398 "reflect.h2" +#line 401 "reflect.h2" auto stmt {parse_statement(source)}; if (!((cpp2::impl::as_(stmt)))) { error("cannot add an initializer that is not a valid statement"); @@ -2952,30 +3595,30 @@ declaration::declaration(declaration&& that) noexcept function_declaration::function_declaration(function_declaration&& that) noexcept : declaration{ static_cast(that) }{} -#line 409 "reflect.h2" +#line 412 "reflect.h2" //----------------------------------------------------------------------- // Object declarations // -#line 416 "reflect.h2" +#line 419 "reflect.h2" object_declaration::object_declaration( declaration_node* n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 421 "reflect.h2" +#line 424 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_object)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } } -#line 426 "reflect.h2" +#line 429 "reflect.h2" [[nodiscard]] auto object_declaration::is_const() const& -> bool { return CPP2_UFCS(is_const)((*cpp2::impl::assert_not_null(n))); } -#line 427 "reflect.h2" +#line 430 "reflect.h2" [[nodiscard]] auto object_declaration::has_wildcard_type() const& -> bool { return CPP2_UFCS(has_wildcard_type)((*cpp2::impl::assert_not_null(n))); } -#line 429 "reflect.h2" +#line 432 "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*)")), @@ -2983,7 +3626,7 @@ function_declaration::function_declaration(function_declaration&& that) noexcept return ret; } -#line 436 "reflect.h2" +#line 439 "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*)")), @@ -2996,25 +3639,25 @@ function_declaration::function_declaration(function_declaration&& that) noexcept object_declaration::object_declaration(object_declaration&& that) noexcept : declaration{ static_cast(that) }{} -#line 445 "reflect.h2" +#line 448 "reflect.h2" //----------------------------------------------------------------------- // Type and namespace declarations // -#line 452 "reflect.h2" +#line 455 "reflect.h2" type_or_namespace_declaration::type_or_namespace_declaration( declaration_node* n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 457 "reflect.h2" +#line 460 "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 462 "reflect.h2" +#line 465 "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 ( @@ -3029,7 +3672,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept } } -#line 476 "reflect.h2" +#line 479 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_functions() const& -> std::vector { @@ -3041,7 +3684,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 487 "reflect.h2" +#line 490 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_functions_needing_initializer() const& -> std::vector { @@ -3057,7 +3700,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 502 "reflect.h2" +#line 505 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_objects() const& -> std::vector { @@ -3068,7 +3711,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 512 "reflect.h2" +#line 515 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_types() const& -> std::vector { @@ -3079,7 +3722,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 522 "reflect.h2" +#line 525 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_member_aliases() const& -> std::vector { @@ -3090,7 +3733,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 532 "reflect.h2" +#line 535 "reflect.h2" [[nodiscard]] auto type_or_namespace_declaration::get_members() const& -> std::vector { @@ -3101,7 +3744,7 @@ object_declaration::object_declaration(object_declaration&& that) noexcept return ret; } -#line 542 "reflect.h2" +#line 545 "reflect.h2" auto type_or_namespace_declaration::add_member(cpp2::impl::in source) & -> void { auto decl {parse_statement(source)}; @@ -3112,6 +3755,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); } @@ -3121,36 +3765,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 562 "reflect.h2" +#line 566 "reflect.h2" type_declaration::type_declaration( declaration_node* n_, cpp2::impl::in s ) : type_or_namespace_declaration{ n_, s } -#line 567 "reflect.h2" +#line 571 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_type)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } } -#line 573 "reflect.h2" +#line 577 "reflect.h2" [[nodiscard]] auto type_declaration::is_polymorphic() const& -> bool { return CPP2_UFCS(is_polymorphic)((*cpp2::impl::assert_not_null(n))); } -#line 574 "reflect.h2" +#line 578 "reflect.h2" [[nodiscard]] auto type_declaration::is_final() const& -> bool { return CPP2_UFCS(is_type_final)((*cpp2::impl::assert_not_null(n))); } -#line 575 "reflect.h2" +#line 579 "reflect.h2" [[nodiscard]] auto type_declaration::make_final() & -> bool { return CPP2_UFCS(make_type_final)((*cpp2::impl::assert_not_null(n))); } -#line 577 "reflect.h2" +#line 581 "reflect.h2" [[nodiscard]] auto type_declaration::query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret -#line 584 "reflect.h2" +#line 588 "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 585 "reflect.h2" +#line 589 "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); @@ -3159,13 +3803,13 @@ 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 593 "reflect.h2" +#line 597 "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))); } // At some point we may want to allow this also for namespaces, but for now only types -#line 596 "reflect.h2" +#line 600 "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 597 "reflect.h2" +#line 601 "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) @@ -3173,14 +3817,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 605 "reflect.h2" +#line 609 "reflect.h2" namespace_declaration::namespace_declaration( declaration_node* n_, cpp2::impl::in s ) : type_or_namespace_declaration{ n_, s } -#line 610 "reflect.h2" +#line 614 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_namespace)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } @@ -3191,19 +3835,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 617 "reflect.h2" +#line 621 "reflect.h2" //----------------------------------------------------------------------- // Alias declarations // -#line 624 "reflect.h2" +#line 628 "reflect.h2" alias_declaration::alias_declaration( declaration_node* n_, cpp2::impl::in s ) : declaration{ n_, s } -#line 629 "reflect.h2" +#line 633 "reflect.h2" { if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(is_alias)((*cpp2::impl::assert_not_null(n)))) ) { cpp2::cpp2_default.report_violation(""); } @@ -3214,35 +3858,35 @@ namespace_declaration::namespace_declaration(namespace_declaration&& that) noexc alias_declaration::alias_declaration(alias_declaration&& that) noexcept : declaration{ static_cast(that) }{} -#line 636 "reflect.h2" +#line 640 "reflect.h2" //----------------------------------------------------------------------- // Parameter declarations // -#line 643 "reflect.h2" +#line 647 "reflect.h2" parameter_declaration::parameter_declaration( parameter_declaration_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 648 "reflect.h2" +#line 652 "reflect.h2" { } -#line 652 "reflect.h2" +#line 656 "reflect.h2" [[nodiscard]] auto parameter_declaration::get_declaration() const& -> object_declaration { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(n)).declaration), (*this) }; } -#line 653 "reflect.h2" +#line 657 "reflect.h2" [[nodiscard]] auto parameter_declaration::get_passing_style() const& -> passing_style { return (*cpp2::impl::assert_not_null(n)).pass; } -#line 655 "reflect.h2" +#line 659 "reflect.h2" [[nodiscard]] auto parameter_declaration::is_implicit() const& -> bool { return (*cpp2::impl::assert_not_null(n)).mod == parameter_declaration_node::modifier::implicit; } -#line 656 "reflect.h2" +#line 660 "reflect.h2" [[nodiscard]] auto parameter_declaration::is_virtual() const& -> bool { return (*cpp2::impl::assert_not_null(n)).mod == parameter_declaration_node::modifier::virtual_; } -#line 657 "reflect.h2" +#line 661 "reflect.h2" [[nodiscard]] auto parameter_declaration::is_override() const& -> bool { return (*cpp2::impl::assert_not_null(n)).mod == parameter_declaration_node::modifier::override_; } -#line 658 "reflect.h2" +#line 662 "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) @@ -3250,7 +3894,7 @@ alias_declaration::alias_declaration(alias_declaration&& that) noexcept parameter_declaration::parameter_declaration(parameter_declaration&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 662 "reflect.h2" +#line 666 "reflect.h2" //----------------------------------------------------------------------- // // Expressions @@ -3262,45 +3906,45 @@ parameter_declaration::parameter_declaration(parameter_declaration&& that) noexc // Binary expressions // -#line 689 "reflect.h2" +#line 693 "reflect.h2" template binary_expression::binary_expression( binary_expression_node* n_, cpp2::impl::in s ) : reflection_base>{ n_, s } -#line 694 "reflect.h2" +#line 698 "reflect.h2" { } -#line 698 "reflect.h2" +#line 702 "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 699 "reflect.h2" +#line 703 "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 700 "reflect.h2" +#line 704 "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 701 "reflect.h2" +#line 705 "reflect.h2" template [[nodiscard]] auto binary_expression::terms_size() const& -> int { return CPP2_UFCS(terms_size)((*cpp2::impl::assert_not_null((*this).n))); } -#line 702 "reflect.h2" +#line 706 "reflect.h2" template [[nodiscard]] auto binary_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null((*this).n))); } -#line 703 "reflect.h2" +#line 707 "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 704 "reflect.h2" +#line 708 "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 705 "reflect.h2" +#line 709 "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 706 "reflect.h2" +#line 710 "reflect.h2" template [[nodiscard]] auto binary_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null((*this).n))); } -#line 712 "reflect.h2" +#line 716 "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 714 "reflect.h2" +#line 718 "reflect.h2" template template [[nodiscard]] auto binary_expression::term_t::get_op() const& -> std::string { return op; } -#line 715 "reflect.h2" +#line 719 "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) @@ -3318,7 +3962,7 @@ template template auto binary_expressi op = std::move(that).op; term = std::move(that).term; return *this;} -#line 718 "reflect.h2" +#line 722 "reflect.h2" template [[nodiscard]] auto binary_expression::get_terms() const& -> auto{ if constexpr (std::is_same_v) { std::vector> ret {}; @@ -3394,25 +4038,25 @@ template template auto binary_expressi } } -#line 793 "reflect.h2" +#line 797 "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 794 "reflect.h2" +#line 798 "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 797 "reflect.h2" +#line 801 "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 799 "reflect.h2" +#line 803 "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 801 "reflect.h2" +#line 805 "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 803 "reflect.h2" +#line 807 "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 805 "reflect.h2" +#line 809 "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) @@ -3420,29 +4064,29 @@ template template auto binary_expressi template binary_expression::binary_expression(binary_expression&& that) noexcept : reflection_base>{ static_cast>&&>(that) }{} -#line 809 "reflect.h2" +#line 813 "reflect.h2" //----------------------------------------------------------------------- // Expression list // -#line 816 "reflect.h2" +#line 820 "reflect.h2" expression_list::expression_list( expression_list_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 821 "reflect.h2" +#line 825 "reflect.h2" { } -#line 825 "reflect.h2" +#line 829 "reflect.h2" [[nodiscard]] auto expression_list::is_empty() const& -> bool { return CPP2_UFCS(is_empty)((*cpp2::impl::assert_not_null(n))); } -#line 826 "reflect.h2" +#line 830 "reflect.h2" [[nodiscard]] auto expression_list::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 828 "reflect.h2" +#line 832 "reflect.h2" [[nodiscard]] auto expression_list::get_expressions() const& -> std::vector { @@ -3453,7 +4097,7 @@ template binary_expression::binary_expre return ret; } -#line 838 "reflect.h2" +#line 842 "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) @@ -3461,24 +4105,24 @@ template binary_expression::binary_expre expression_list::expression_list(expression_list&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 842 "reflect.h2" +#line 846 "reflect.h2" //----------------------------------------------------------------------- // Prefix expressions // -#line 849 "reflect.h2" +#line 853 "reflect.h2" prefix_expression::prefix_expression( prefix_expression_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 854 "reflect.h2" +#line 858 "reflect.h2" { } -#line 858 "reflect.h2" +#line 862 "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 ) { @@ -3487,32 +4131,32 @@ expression_list::expression_list(expression_list&& that) noexcept return ret; } -#line 866 "reflect.h2" +#line 870 "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 868 "reflect.h2" +#line 872 "reflect.h2" [[nodiscard]] auto prefix_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 869 "reflect.h2" +#line 873 "reflect.h2" [[nodiscard]] auto prefix_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 870 "reflect.h2" +#line 874 "reflect.h2" [[nodiscard]] auto prefix_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 871 "reflect.h2" +#line 875 "reflect.h2" [[nodiscard]] auto prefix_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 872 "reflect.h2" +#line 876 "reflect.h2" [[nodiscard]] auto prefix_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 873 "reflect.h2" +#line 877 "reflect.h2" [[nodiscard]] auto prefix_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 874 "reflect.h2" +#line 878 "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 876 "reflect.h2" +#line 880 "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 877 "reflect.h2" +#line 881 "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 878 "reflect.h2" +#line 882 "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 880 "reflect.h2" +#line 884 "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{} @@ -3521,32 +4165,32 @@ prefix_expression::prefix_expression(prefix_expression const& that) prefix_expression::prefix_expression(prefix_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 884 "reflect.h2" +#line 888 "reflect.h2" //----------------------------------------------------------------------- // Postfix expressions // -#line 891 "reflect.h2" +#line 895 "reflect.h2" postfix_expression::postfix_expression( postfix_expression_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 896 "reflect.h2" +#line 900 "reflect.h2" { } -#line 900 "reflect.h2" +#line 904 "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 906 "reflect.h2" +#line 910 "reflect.h2" postfix_expression::term_t::term_t(auto&& term, auto&& cs) : term_{ CPP2_FORWARD(term) } , cs_{ CPP2_FORWARD(cs) }{} -#line 908 "reflect.h2" +#line 912 "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 @@ -3555,18 +4199,18 @@ prefix_expression::prefix_expression(prefix_expression&& that) noexcept // [ ( expression_list subscript or function call // ... expression fold expression -#line 916 "reflect.h2" +#line 920 "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 917 "reflect.h2" +#line 921 "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 918 "reflect.h2" +#line 922 "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 920 "reflect.h2" +#line 924 "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 921 "reflect.h2" +#line 925 "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 922 "reflect.h2" +#line 926 "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) @@ -3576,46 +4220,46 @@ postfix_expression::term_t::term_t(term_t&& that) noexcept : term_{ std::move(that).term_ } , cs_{ std::move(that).cs_ }{} -#line 925 "reflect.h2" +#line 929 "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 931 "reflect.h2" +#line 935 "reflect.h2" [[nodiscard]] auto postfix_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 932 "reflect.h2" +#line 936 "reflect.h2" [[nodiscard]] auto postfix_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 933 "reflect.h2" +#line 937 "reflect.h2" [[nodiscard]] auto postfix_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 934 "reflect.h2" +#line 938 "reflect.h2" [[nodiscard]] auto postfix_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 935 "reflect.h2" +#line 939 "reflect.h2" [[nodiscard]] auto postfix_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 936 "reflect.h2" +#line 940 "reflect.h2" [[nodiscard]] auto postfix_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 938 "reflect.h2" +#line 942 "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 939 "reflect.h2" +#line 943 "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 940 "reflect.h2" +#line 944 "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 942 "reflect.h2" +#line 946 "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 948 "reflect.h2" +#line 952 "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 949 "reflect.h2" +#line 953 "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 951 "reflect.h2" +#line 955 "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) @@ -3623,34 +4267,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 955 "reflect.h2" +#line 959 "reflect.h2" //----------------------------------------------------------------------- // Template arguments // -#line 962 "reflect.h2" +#line 966 "reflect.h2" template_arg::template_arg( template_argument* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 967 "reflect.h2" +#line 971 "reflect.h2" { } -#line 971 "reflect.h2" +#line 975 "reflect.h2" [[nodiscard]] auto template_arg::is_expression() const& -> bool { return CPP2_UFCS(is_expression)((*cpp2::impl::assert_not_null(n))); } -#line 972 "reflect.h2" +#line 976 "reflect.h2" [[nodiscard]] auto template_arg::is_type_id() const& -> bool { return CPP2_UFCS(is_type_id)((*cpp2::impl::assert_not_null(n))); } -#line 974 "reflect.h2" +#line 978 "reflect.h2" [[nodiscard]] auto template_arg::as_expression() const& -> expression { return { CPP2_UFCS(get_expression)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 975 "reflect.h2" +#line 979 "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 977 "reflect.h2" +#line 981 "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) @@ -3658,27 +4302,27 @@ postfix_expression::postfix_expression(postfix_expression&& that) noexcept template_arg::template_arg(template_arg&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 981 "reflect.h2" +#line 985 "reflect.h2" //----------------------------------------------------------------------- // Unqualified IDs // -#line 988 "reflect.h2" +#line 992 "reflect.h2" unqualified_id::unqualified_id( unqualified_id_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 993 "reflect.h2" +#line 997 "reflect.h2" { } -#line 997 "reflect.h2" +#line 1001 "reflect.h2" [[nodiscard]] auto unqualified_id::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 999 "reflect.h2" +#line 1003 "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 = { @@ -3687,10 +4331,10 @@ template_arg::template_arg(template_arg&& that) noexcept // return ret; //} -#line 1007 "reflect.h2" +#line 1011 "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 1009 "reflect.h2" +#line 1013 "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) @@ -3698,31 +4342,31 @@ template_arg::template_arg(template_arg&& that) noexcept unqualified_id::unqualified_id(unqualified_id&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1013 "reflect.h2" +#line 1017 "reflect.h2" //----------------------------------------------------------------------- // Qualified IDs // -#line 1020 "reflect.h2" +#line 1024 "reflect.h2" qualified_id::qualified_id( qualified_id_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1025 "reflect.h2" +#line 1029 "reflect.h2" { } -#line 1033 "reflect.h2" +#line 1037 "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 1035 "reflect.h2" +#line 1039 "reflect.h2" [[nodiscard]] auto qualified_id::term_t::get_op() const& -> std::string { return op; } -#line 1036 "reflect.h2" +#line 1040 "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) @@ -3732,7 +4376,7 @@ qualified_id::term_t::term_t(term_t&& that) noexcept : op{ std::move(that).op } , unqualified{ std::move(that).unqualified }{} -#line 1039 "reflect.h2" +#line 1043 "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))); } @@ -3745,10 +4389,10 @@ qualified_id::term_t::term_t(term_t&& that) noexcept // return ret; //} -#line 1051 "reflect.h2" +#line 1055 "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 1053 "reflect.h2" +#line 1057 "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) @@ -3756,19 +4400,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 1057 "reflect.h2" +#line 1061 "reflect.h2" //----------------------------------------------------------------------- // Type IDs // -#line 1064 "reflect.h2" +#line 1068 "reflect.h2" type_id::type_id( type_id_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1069 "reflect.h2" +#line 1073 "reflect.h2" { } @@ -3779,37 +4423,37 @@ qualified_id::qualified_id(qualified_id&& that) noexcept // return ret; //} -#line 1079 "reflect.h2" +#line 1083 "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 1080 "reflect.h2" +#line 1084 "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 1081 "reflect.h2" +#line 1085 "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 1082 "reflect.h2" +#line 1086 "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 1083 "reflect.h2" +#line 1087 "reflect.h2" [[nodiscard]] auto type_id::is_keyword() const& -> bool { return CPP2_UFCS(is_keyword)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1084 "reflect.h2" +#line 1088 "reflect.h2" [[nodiscard]] auto type_id::is_wildcard() const& -> bool { return CPP2_UFCS(is_wildcard)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1085 "reflect.h2" +#line 1089 "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 1086 "reflect.h2" +#line 1090 "reflect.h2" [[nodiscard]] auto type_id::is_concept() const& -> bool { return CPP2_UFCS(is_concept)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1088 "reflect.h2" +#line 1092 "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 1089 "reflect.h2" +#line 1093 "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 1090 "reflect.h2" +#line 1094 "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 1093 "reflect.h2" +#line 1097 "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 1094 "reflect.h2" +#line 1098 "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 1096 "reflect.h2" +#line 1100 "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) @@ -3817,19 +4461,19 @@ qualified_id::qualified_id(qualified_id&& that) noexcept type_id::type_id(type_id&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1100 "reflect.h2" +#line 1104 "reflect.h2" //----------------------------------------------------------------------- // Primary expressions // -#line 1107 "reflect.h2" +#line 1111 "reflect.h2" primary_expression::primary_expression( primary_expression_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1112 "reflect.h2" +#line 1116 "reflect.h2" { } @@ -3840,31 +4484,31 @@ type_id::type_id(type_id&& that) noexcept // return ret; //} -#line 1122 "reflect.h2" +#line 1126 "reflect.h2" [[nodiscard]] auto primary_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1123 "reflect.h2" +#line 1127 "reflect.h2" [[nodiscard]] auto primary_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 1124 "reflect.h2" +#line 1128 "reflect.h2" [[nodiscard]] auto primary_expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1125 "reflect.h2" +#line 1129 "reflect.h2" [[nodiscard]] auto primary_expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 1126 "reflect.h2" +#line 1130 "reflect.h2" [[nodiscard]] auto primary_expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 1127 "reflect.h2" +#line 1131 "reflect.h2" [[nodiscard]] auto primary_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 1128 "reflect.h2" +#line 1132 "reflect.h2" [[nodiscard]] auto primary_expression::is_declaration() const& -> bool { return CPP2_UFCS(is_declaration)((*cpp2::impl::assert_not_null(n))); } -#line 1130 "reflect.h2" +#line 1134 "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 1131 "reflect.h2" +#line 1135 "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 1132 "reflect.h2" +#line 1136 "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 1133 "reflect.h2" +#line 1137 "reflect.h2" [[nodiscard]] auto primary_expression::as_declaration() const& -> declaration { return { CPP2_UFCS(get_declaration)((*cpp2::impl::assert_not_null((*this).n))), (*this) }; } -#line 1135 "reflect.h2" +#line 1139 "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) @@ -3872,19 +4516,19 @@ type_id::type_id(type_id&& that) noexcept primary_expression::primary_expression(primary_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1139 "reflect.h2" +#line 1143 "reflect.h2" //----------------------------------------------------------------------- // ID expression // -#line 1146 "reflect.h2" +#line 1150 "reflect.h2" id_expression::id_expression( id_expression_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1151 "reflect.h2" +#line 1155 "reflect.h2" { } @@ -3895,25 +4539,25 @@ primary_expression::primary_expression(primary_expression&& that) noexcept // return ret; //} -#line 1161 "reflect.h2" +#line 1165 "reflect.h2" [[nodiscard]] auto id_expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1162 "reflect.h2" +#line 1166 "reflect.h2" [[nodiscard]] auto id_expression::is_empty() const& -> bool { return CPP2_UFCS(is_empty)((*cpp2::impl::assert_not_null(n))); } -#line 1163 "reflect.h2" +#line 1167 "reflect.h2" [[nodiscard]] auto id_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 1164 "reflect.h2" +#line 1168 "reflect.h2" [[nodiscard]] auto id_expression::is_qualified() const& -> bool { return CPP2_UFCS(is_qualified)((*cpp2::impl::assert_not_null(n))); } -#line 1165 "reflect.h2" +#line 1169 "reflect.h2" [[nodiscard]] auto id_expression::is_unqualified() const& -> bool { return CPP2_UFCS(is_unqualified)((*cpp2::impl::assert_not_null(n))); } -#line 1167 "reflect.h2" +#line 1171 "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 1168 "reflect.h2" +#line 1172 "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 1169 "reflect.h2" +#line 1173 "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 1171 "reflect.h2" +#line 1175 "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{} @@ -3922,71 +4566,71 @@ id_expression::id_expression(id_expression const& that) id_expression::id_expression(id_expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1175 "reflect.h2" +#line 1179 "reflect.h2" //----------------------------------------------------------------------- // General expression // -#line 1182 "reflect.h2" +#line 1186 "reflect.h2" expression::expression( expression_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1187 "reflect.h2" +#line 1191 "reflect.h2" { } -#line 1191 "reflect.h2" +#line 1195 "reflect.h2" [[nodiscard]] auto expression::is_fold_expression() const& -> bool { return CPP2_UFCS(is_fold_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1192 "reflect.h2" +#line 1196 "reflect.h2" [[nodiscard]] auto expression::is_standalone_expression() const& -> bool { return CPP2_UFCS(is_standalone_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1193 "reflect.h2" +#line 1197 "reflect.h2" [[nodiscard]] auto expression::subexpression_count() const& -> int { return CPP2_UFCS(subexpression_count)((*cpp2::impl::assert_not_null(n))); } -#line 1194 "reflect.h2" +#line 1198 "reflect.h2" [[nodiscard]] auto expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null(n))); } -#line 1195 "reflect.h2" +#line 1199 "reflect.h2" [[nodiscard]] auto expression::is_id_expression() const& -> bool { return CPP2_UFCS(is_id_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1196 "reflect.h2" +#line 1200 "reflect.h2" [[nodiscard]] auto expression::is_unqualified_id() const& -> bool { return CPP2_UFCS(is_unqualified_id)((*cpp2::impl::assert_not_null(n))); } -#line 1197 "reflect.h2" +#line 1201 "reflect.h2" [[nodiscard]] auto expression::is_expression_list() const& -> bool { return CPP2_UFCS(is_expression_list)((*cpp2::impl::assert_not_null(n))); } -#line 1198 "reflect.h2" +#line 1202 "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 1199 "reflect.h2" +#line 1203 "reflect.h2" [[nodiscard]] auto expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null(n))); } -#line 1200 "reflect.h2" +#line 1204 "reflect.h2" [[nodiscard]] auto expression::is_assignment_expression() const& -> bool { return CPP2_UFCS(is_assignment_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1202 "reflect.h2" +#line 1206 "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 1207 "reflect.h2" +#line 1211 "reflect.h2" [[nodiscard]] auto expression::get_lhs_rhs_if_simple_assignment() const& -> get_lhs_rhs_if_simple_assignment_ret -#line 1212 "reflect.h2" +#line 1216 "reflect.h2" { cpp2::impl::deferred_init lhs; cpp2::impl::deferred_init rhs; -#line 1213 "reflect.h2" +#line 1217 "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 1218 "reflect.h2" +#line 1222 "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 1219 "reflect.h2" +#line 1223 "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 1220 "reflect.h2" +#line 1224 "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 1222 "reflect.h2" +#line 1226 "reflect.h2" [[nodiscard]] auto expression::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } expression::~expression() noexcept{} @@ -3995,31 +4639,31 @@ expression::expression(expression const& that) expression::expression(expression&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1226 "reflect.h2" +#line 1230 "reflect.h2" //----------------------------------------------------------------------- // is_as_expression // -#line 1233 "reflect.h2" +#line 1237 "reflect.h2" is_as_expression::is_as_expression( is_as_expression_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1238 "reflect.h2" +#line 1242 "reflect.h2" { } -#line 1246 "reflect.h2" +#line 1250 "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 1248 "reflect.h2" +#line 1252 "reflect.h2" [[nodiscard]] auto is_as_expression::term_t::get_op() const& -> std::string { return op; } -#line 1249 "reflect.h2" +#line 1253 "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) @@ -4029,42 +4673,42 @@ is_as_expression::term_t::term_t(term_t&& that) noexcept : op{ std::move(that).op } , expr{ std::move(that).expr }{} -#line 1252 "reflect.h2" +#line 1256 "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 1254 "reflect.h2" +#line 1258 "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 1260 "reflect.h2" +#line 1264 "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 1261 "reflect.h2" +#line 1265 "reflect.h2" [[nodiscard]] auto is_as_expression::is_identifier() const& -> bool { return CPP2_UFCS(is_identifier)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1262 "reflect.h2" +#line 1266 "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 1263 "reflect.h2" +#line 1267 "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 1264 "reflect.h2" +#line 1268 "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 1265 "reflect.h2" +#line 1269 "reflect.h2" [[nodiscard]] auto is_as_expression::is_literal() const& -> bool { return CPP2_UFCS(is_literal)((*cpp2::impl::assert_not_null((*this).n))); } -#line 1267 "reflect.h2" +#line 1271 "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 1268 "reflect.h2" +#line 1272 "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 1270 "reflect.h2" +#line 1274 "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 1276 "reflect.h2" +#line 1280 "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{} @@ -4073,7 +4717,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 1280 "reflect.h2" +#line 1284 "reflect.h2" //----------------------------------------------------------------------- // // Statements @@ -4085,57 +4729,57 @@ is_as_expression::is_as_expression(is_as_expression&& that) noexcept // General statement // -#line 1294 "reflect.h2" +#line 1298 "reflect.h2" statement::statement( statement_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1299 "reflect.h2" +#line 1303 "reflect.h2" { } -#line 1303 "reflect.h2" +#line 1307 "reflect.h2" [[nodiscard]] auto statement::is_expression_statement() const& -> bool { return CPP2_UFCS(is_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1304 "reflect.h2" +#line 1308 "reflect.h2" [[nodiscard]] auto statement::is_compound_statement() const& -> bool { return CPP2_UFCS(is_compound)((*cpp2::impl::assert_not_null(n))); } -#line 1305 "reflect.h2" +#line 1309 "reflect.h2" [[nodiscard]] auto statement::is_selection_statement() const& -> bool { return CPP2_UFCS(is_selection)((*cpp2::impl::assert_not_null(n))); } -#line 1306 "reflect.h2" +#line 1310 "reflect.h2" [[nodiscard]] auto statement::is_declaration() const& -> bool { return CPP2_UFCS(is_declaration)((*cpp2::impl::assert_not_null(n))); } -#line 1307 "reflect.h2" +#line 1311 "reflect.h2" [[nodiscard]] auto statement::is_return_statement() const& -> bool { return CPP2_UFCS(is_return)((*cpp2::impl::assert_not_null(n))); } -#line 1308 "reflect.h2" +#line 1312 "reflect.h2" [[nodiscard]] auto statement::is_iteration_statement() const& -> bool { return CPP2_UFCS(is_iteration)((*cpp2::impl::assert_not_null(n))); } -#line 1309 "reflect.h2" +#line 1313 "reflect.h2" [[nodiscard]] auto statement::is_using_statement() const& -> bool { return CPP2_UFCS(is_using)((*cpp2::impl::assert_not_null(n))); } -#line 1310 "reflect.h2" +#line 1314 "reflect.h2" [[nodiscard]] auto statement::is_contract() const& -> bool { return CPP2_UFCS(is_contract)((*cpp2::impl::assert_not_null(n))); } -#line 1311 "reflect.h2" +#line 1315 "reflect.h2" [[nodiscard]] auto statement::is_inspect_expression() const& -> bool { return CPP2_UFCS(is_inspect)((*cpp2::impl::assert_not_null(n))); } -#line 1312 "reflect.h2" +#line 1316 "reflect.h2" [[nodiscard]] auto statement::is_jump_statement() const& -> bool { return CPP2_UFCS(is_jump)((*cpp2::impl::assert_not_null(n))); } -#line 1314 "reflect.h2" +#line 1318 "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 1315 "reflect.h2" +#line 1319 "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 1316 "reflect.h2" +#line 1320 "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 1317 "reflect.h2" +#line 1321 "reflect.h2" [[nodiscard]] auto statement::as_declaration() const& -> declaration { return declaration(CPP2_UFCS_TEMPLATE(get_if)((*cpp2::impl::assert_not_null(n))), (*this)); } -#line 1318 "reflect.h2" +#line 1322 "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 1319 "reflect.h2" +#line 1323 "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 1325 "reflect.h2" +#line 1329 "reflect.h2" [[nodiscard]] auto statement::to_string() const& -> std::string { return CPP2_UFCS(to_string)((*cpp2::impl::assert_not_null(n))); } statement::~statement() noexcept{} @@ -4144,27 +4788,27 @@ statement::statement(statement const& that) statement::statement(statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1329 "reflect.h2" +#line 1333 "reflect.h2" //----------------------------------------------------------------------- // Expression statements // -#line 1336 "reflect.h2" +#line 1340 "reflect.h2" expression_statement::expression_statement( expression_statement_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1341 "reflect.h2" +#line 1345 "reflect.h2" { } -#line 1345 "reflect.h2" +#line 1349 "reflect.h2" [[nodiscard]] auto expression_statement::get_expression() const& -> expression { return { CPP2_UFCS(get)((*cpp2::impl::assert_not_null(n)).expr), (*this) }; } -#line 1347 "reflect.h2" +#line 1351 "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) @@ -4172,24 +4816,24 @@ statement::statement(statement&& that) noexcept expression_statement::expression_statement(expression_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1351 "reflect.h2" +#line 1355 "reflect.h2" //----------------------------------------------------------------------- // Compound statements // -#line 1358 "reflect.h2" +#line 1362 "reflect.h2" compound_statement::compound_statement( compound_statement_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1363 "reflect.h2" +#line 1367 "reflect.h2" { } -#line 1367 "reflect.h2" +#line 1371 "reflect.h2" [[nodiscard]] auto compound_statement::get_statements() const& -> std::vector { @@ -4200,7 +4844,7 @@ expression_statement::expression_statement(expression_statement&& that) noexcept return ret; } -#line 1377 "reflect.h2" +#line 1381 "reflect.h2" auto compound_statement::add_statement(cpp2::impl::in source, cpp2::impl::in before_position) & -> void { auto stmt {parse_statement(source)}; @@ -4217,35 +4861,35 @@ expression_statement::expression_statement(expression_statement&& that) noexcept compound_statement::compound_statement(compound_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1390 "reflect.h2" +#line 1394 "reflect.h2" //----------------------------------------------------------------------- // Selection statements // -#line 1397 "reflect.h2" +#line 1401 "reflect.h2" selection_statement::selection_statement( selection_statement_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1402 "reflect.h2" +#line 1406 "reflect.h2" { } -#line 1406 "reflect.h2" +#line 1410 "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 1407 "reflect.h2" +#line 1411 "reflect.h2" [[nodiscard]] auto selection_statement::has_false_branch() const& -> bool { return CPP2_UFCS(has_false_branch)((*cpp2::impl::assert_not_null(n))); } -#line 1409 "reflect.h2" +#line 1413 "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 1410 "reflect.h2" +#line 1414 "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 1411 "reflect.h2" +#line 1415 "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 1412 "reflect.h2" +#line 1416 "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) @@ -4253,27 +4897,27 @@ compound_statement::compound_statement(compound_statement&& that) noexcept selection_statement::selection_statement(selection_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1416 "reflect.h2" +#line 1420 "reflect.h2" //----------------------------------------------------------------------- // Return statements // -#line 1423 "reflect.h2" +#line 1427 "reflect.h2" return_statement::return_statement( return_statement_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1428 "reflect.h2" +#line 1432 "reflect.h2" { } -#line 1432 "reflect.h2" +#line 1436 "reflect.h2" [[nodiscard]] auto return_statement::has_expression() const& -> bool { return CPP2_UFCS(has_expression)((*cpp2::impl::assert_not_null(n))); } -#line 1434 "reflect.h2" +#line 1438 "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) @@ -4281,45 +4925,45 @@ selection_statement::selection_statement(selection_statement&& that) noexcept return_statement::return_statement(return_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1438 "reflect.h2" +#line 1442 "reflect.h2" //----------------------------------------------------------------------- // Iteration statements - for, do, while // -#line 1445 "reflect.h2" +#line 1449 "reflect.h2" iteration_statement::iteration_statement( iteration_statement_node* n_, cpp2::impl::in s ) : reflection_base{ n_, s } -#line 1450 "reflect.h2" +#line 1454 "reflect.h2" { } -#line 1454 "reflect.h2" +#line 1458 "reflect.h2" [[nodiscard]] auto iteration_statement::is_do() const& -> bool { return CPP2_UFCS(is_do)((*cpp2::impl::assert_not_null(n))); } -#line 1455 "reflect.h2" +#line 1459 "reflect.h2" [[nodiscard]] auto iteration_statement::is_while() const& -> bool { return CPP2_UFCS(is_while)((*cpp2::impl::assert_not_null(n))); } -#line 1456 "reflect.h2" +#line 1460 "reflect.h2" [[nodiscard]] auto iteration_statement::is_for() const& -> bool { return CPP2_UFCS(is_for)((*cpp2::impl::assert_not_null(n))); } -#line 1457 "reflect.h2" +#line 1461 "reflect.h2" [[nodiscard]] auto iteration_statement::has_next() const& -> bool { return CPP2_UFCS(has_next)((*cpp2::impl::assert_not_null(n))); } -#line 1459 "reflect.h2" +#line 1463 "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 1460 "reflect.h2" +#line 1464 "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 1461 "reflect.h2" +#line 1465 "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 1462 "reflect.h2" +#line 1466 "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 1463 "reflect.h2" +#line 1467 "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 1464 "reflect.h2" +#line 1468 "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 1465 "reflect.h2" +#line 1469 "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) @@ -4327,7 +4971,7 @@ return_statement::return_statement(return_statement&& that) noexcept iteration_statement::iteration_statement(iteration_statement&& that) noexcept : reflection_base{ static_cast&&>(that) }{} -#line 1469 "reflect.h2" +#line 1473 "reflect.h2" //----------------------------------------------------------------------- // // Metafunctions - these are hardwired for now until we get to the @@ -4340,13 +4984,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 1481 "reflect.h2" +#line 1485 "reflect.h2" auto add_virtual_destructor(meta::type_declaration& t) -> void { CPP2_UFCS(add_member)(t, "operator=: (virtual move this) = { }"); } -#line 1487 "reflect.h2" +#line 1491 "reflect.h2" //----------------------------------------------------------------------- // // "... an abstract base class defines an interface ..." @@ -4361,7 +5005,7 @@ auto add_virtual_destructor(meta::type_declaration& t) -> void // a public default constructor, a public virtual destructor, and // protected copy/move operations // -#line 1501 "reflect.h2" +#line 1505 "reflect.h2" auto interface(meta::type_declaration& t) -> void { auto has_dtor {false}; @@ -4393,7 +5037,7 @@ auto interface(meta::type_declaration& t) -> void } } -#line 1533 "reflect.h2" +#line 1537 "reflect.h2" //----------------------------------------------------------------------- // // "C.35: A base class destructor should be either public and @@ -4410,7 +5054,7 @@ auto interface(meta::type_declaration& t) -> void // // Unlike an interface, it can have nonpublic and nonvirtual functions. // -#line 1549 "reflect.h2" +#line 1553 "reflect.h2" auto polymorphic_base(meta::type_declaration& t) -> void { auto has_dtor {false}; @@ -4435,7 +5079,7 @@ auto polymorphic_base(meta::type_declaration& t) -> void } } -#line 1574 "reflect.h2" +#line 1578 "reflect.h2" //----------------------------------------------------------------------- // // "... A totally ordered type ... requires operator<=> that @@ -4456,7 +5100,7 @@ auto polymorphic_base(meta::type_declaration& t) -> void //----------------------------------------------------------------------- // -#line 1594 "reflect.h2" +#line 1598 "reflect.h2" auto ordered_impl( meta::type_declaration& t, cpp2::impl::in ordering// must be "strong_ordering" etc. @@ -4486,7 +5130,7 @@ auto ordered_impl( // // Note: the ordering that should be encouraged as default gets the nice name // -#line 1623 "reflect.h2" +#line 1627 "reflect.h2" auto ordered(meta::type_declaration& t) -> void { ordered_impl(t, "strong_ordering"); @@ -4495,7 +5139,7 @@ auto ordered(meta::type_declaration& t) -> void //----------------------------------------------------------------------- // weakly_ordered - a weakly ordered type // -#line 1631 "reflect.h2" +#line 1635 "reflect.h2" auto weakly_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "weak_ordering"); @@ -4504,13 +5148,13 @@ auto weakly_ordered(meta::type_declaration& t) -> void //----------------------------------------------------------------------- // partially_ordered - a partially ordered type // -#line 1639 "reflect.h2" +#line 1643 "reflect.h2" auto partially_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "partial_ordering"); } -#line 1645 "reflect.h2" +#line 1649 "reflect.h2" //----------------------------------------------------------------------- // // "A value is ... a regular type. It must have all public @@ -4527,7 +5171,7 @@ auto partially_ordered(meta::type_declaration& t) -> void // // A type with (copy and move) x (construction and assignment) // -#line 1661 "reflect.h2" +#line 1665 "reflect.h2" auto copyable(meta::type_declaration& t) -> void { // If the user explicitly wrote any of the copy/move functions, @@ -4555,12 +5199,12 @@ auto copyable(meta::type_declaration& t) -> void }} } -#line 1689 "reflect.h2" +#line 1693 "reflect.h2" // copy_constructible // // A type with (copy and move) construction // -#line 1693 "reflect.h2" +#line 1697 "reflect.h2" auto copy_constructible(meta::type_declaration& t) -> void { // If the user explicitly wrote any of the copy/move constructors, @@ -4586,14 +5230,14 @@ auto copy_constructible(meta::type_declaration& t) -> void }} } -#line 1719 "reflect.h2" +#line 1723 "reflect.h2" //----------------------------------------------------------------------- // // hashable // // A memberwise hashable type // -#line 1725 "reflect.h2" +#line 1729 "reflect.h2" auto hashable(meta::type_declaration& t) -> void { CPP2_UFCS(require)(t, !(CPP2_UFCS(empty)(CPP2_UFCS(get_member_objects)(t))), @@ -4619,7 +5263,7 @@ auto hashable(meta::type_declaration& t) -> void CPP2_UFCS(add_member)(t, cpp2::move(hash) + "\n return ret;\n }"); } -#line 1751 "reflect.h2" +#line 1755 "reflect.h2" //----------------------------------------------------------------------- // // basic_value @@ -4627,7 +5271,7 @@ auto hashable(meta::type_declaration& t) -> void // A regular type: copyable, plus has public default construction // and no protected or virtual functions // -#line 1758 "reflect.h2" +#line 1762 "reflect.h2" auto basic_value(meta::type_declaration& t) -> void { CPP2_UFCS(copyable)(t); @@ -4656,28 +5300,28 @@ auto basic_value(meta::type_declaration& t) -> void // // Note: the ordering that should be encouraged as default gets the nice name // -#line 1786 "reflect.h2" +#line 1790 "reflect.h2" auto value(meta::type_declaration& t) -> void { CPP2_UFCS(ordered)(t); CPP2_UFCS(basic_value)(t); } -#line 1792 "reflect.h2" +#line 1796 "reflect.h2" auto weakly_ordered_value(meta::type_declaration& t) -> void { CPP2_UFCS(weakly_ordered)(t); CPP2_UFCS(basic_value)(t); } -#line 1798 "reflect.h2" +#line 1802 "reflect.h2" auto partially_ordered_value(meta::type_declaration& t) -> void { CPP2_UFCS(partially_ordered)(t); CPP2_UFCS(basic_value)(t); } -#line 1805 "reflect.h2" +#line 1809 "reflect.h2" //----------------------------------------------------------------------- // // C.20: If you can avoid defining default operations, do @@ -4700,7 +5344,7 @@ auto partially_ordered_value(meta::type_declaration& t) -> void // // a type without declared copy/move/destructor functions // -#line 1827 "reflect.h2" +#line 1831 "reflect.h2" auto cpp1_rule_of_zero(meta::type_declaration& t) -> void { for ( auto& mf : CPP2_UFCS(get_member_functions)(t) ) @@ -4743,7 +5387,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 1869 "reflect.h2" +#line 1873 "reflect.h2" auto cpp2_struct(meta::type_declaration& t) -> void { std::string ctor_params {}; @@ -4800,7 +5444,7 @@ value_member_info::value_member_info(auto const& name_, auto const& type_, auto , type{ type_ } , value{ value_ }{} -#line 1921 "reflect.h2" +#line 1925 "reflect.h2" //----------------------------------------------------------------------- // // "C enumerations constitute a curiously half-baked concept. ... @@ -4819,7 +5463,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 1944 "reflect.h2" +#line 1948 "reflect.h2" auto basic_enum( meta::type_declaration& t, auto const& nextval, @@ -4844,7 +5488,7 @@ auto basic_enum( { std::string value{"-1"}; -#line 1967 "reflect.h2" +#line 1971 "reflect.h2" for ( auto const& m : CPP2_UFCS(get_members)(t) ) if ( CPP2_UFCS(is_member_object)(m)) @@ -4886,7 +5530,7 @@ std::string value{"-1"}; } } -#line 2007 "reflect.h2" +#line 2011 "reflect.h2" if ((CPP2_UFCS(empty)(enumerators))) { CPP2_UFCS(error)(t, "an enumeration must contain at least one enumerator value"); return ; @@ -4937,7 +5581,7 @@ std::string value{"-1"}; } } -#line 2058 "reflect.h2" +#line 2062 "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' @@ -4987,7 +5631,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 2105 "reflect.h2" +#line 2109 "reflect.h2" { if (bitwise) { to_string_impl += ", separator: std::string_view ) -> std::string = { \n" @@ -5028,7 +5672,7 @@ std::string to_string_impl{" to_string_impl: (this, prefix: std::string_view" } } -#line 2144 "reflect.h2" +#line 2148 "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)) + "::\", \" | \" );"); @@ -5042,7 +5686,7 @@ std::string from_string{" from_string: (s: std::string_view) -> " + cpp2::to_ // Provide a 'from_string' function to parse strings into enumerators -#line 2155 "reflect.h2" +#line 2159 "reflect.h2" { std::string_view prefix {""}; std::string_view combine_op {"return"}; @@ -5064,7 +5708,7 @@ std::string from_string{" from_string: (s: std::string_view) -> " + cpp2::to_ { std::string_view else_{""}; -#line 2175 "reflect.h2" +#line 2179 "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"; @@ -5072,7 +5716,7 @@ std::string_view else_{""}; } } -#line 2181 "reflect.h2" +#line 2185 "reflect.h2" if (bitwise) { from_string += " else { break outer; }\n" " }\n" @@ -5088,11 +5732,11 @@ std::string_view else_{""}; } } -#line 2195 "reflect.h2" +#line 2199 "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 2199 "reflect.h2" +#line 2203 "reflect.h2" //----------------------------------------------------------------------- // // "An enum[...] is a totally ordered value type that stores a @@ -5102,7 +5746,7 @@ std::string_view else_{""}; // // -- P0707R4, section 3 // -#line 2208 "reflect.h2" +#line 2212 "reflect.h2" auto cpp2_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with an incrementing value generator @@ -5119,7 +5763,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void ); } -#line 2225 "reflect.h2" +#line 2229 "reflect.h2" //----------------------------------------------------------------------- // // "flag_enum expresses an enumeration that stores values @@ -5130,7 +5774,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void // // -- P0707R4, section 3 // -#line 2235 "reflect.h2" +#line 2239 "reflect.h2" auto flag_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with a power-of-two value generator @@ -5152,7 +5796,7 @@ auto flag_enum(meta::type_declaration& t) -> void ); } -#line 2257 "reflect.h2" +#line 2261 "reflect.h2" //----------------------------------------------------------------------- // // "As with void*, programmers should know that unions [...] are @@ -5177,7 +5821,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 2281 "reflect.h2" +#line 2285 "reflect.h2" auto cpp2_union(meta::type_declaration& t) -> void { std::vector alternatives {}; @@ -5186,7 +5830,7 @@ auto value{0}; // 1. Gather: All the user-written members, and find/compute the max size -#line 2288 "reflect.h2" +#line 2292 "reflect.h2" for ( auto const& m : CPP2_UFCS(get_members)(t) ) { do @@ -5216,7 +5860,7 @@ auto value{0}; } while (false); ++value; } } -#line 2316 "reflect.h2" +#line 2320 "reflect.h2" std::string discriminator_type {}; if (cpp2::impl::cmp_less(CPP2_UFCS(ssize)(alternatives),std::numeric_limits::max())) { discriminator_type = "i8"; @@ -5231,7 +5875,7 @@ auto value{0}; discriminator_type = "i64"; }}} -#line 2331 "reflect.h2" +#line 2335 "reflect.h2" // 2. Replace: Erase the contents and replace with modified contents CPP2_UFCS(remove_marked_members)(t); @@ -5240,7 +5884,7 @@ std::string storage{" _storage: cpp2::aligned_storage t) -> void { std::cout << CPP2_UFCS(print)(t) << "\n"; } -#line 2438 "reflect.h2" +#line 2442 "reflect.h2" //----------------------------------------------------------------------- // // noisy - make each function print its name and signature, // so the programmer can see what's called // -#line 2443 "reflect.h2" +#line 2447 "reflect.h2" auto noisy(cpp2::impl::in t) -> void { for ( @@ -5377,12 +6021,12 @@ auto noisy(cpp2::impl::in t) -> void } } -#line 2460 "reflect.h2" +#line 2464 "reflect.h2" //----------------------------------------------------------------------- // // For reflection test cases // -#line 2464 "reflect.h2" +#line 2468 "reflect.h2" auto sample_print(cpp2::impl::in s, cpp2::impl::in indent) -> void { std::cout @@ -5391,1230 +6035,3091 @@ auto sample_print(cpp2::impl::in s, cpp2::impl::in << "\n"; } -#line 2473 "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 2478 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in decl) -> void{ + traverse(decl); + } -#line 2483 "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 2482 "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 2505 "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 2502 "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 2506 "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); - } - else { - sample_traverser(CPP2_UFCS(get_compound_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)); + } } -} -#line 2535 "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 2527 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in o) -> void{ + traverse(o); } -} - -#line 2545 "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)) +#line 2531 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in o) -> 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); + if (CPP2_UFCS(has_initializer)(o)) { + pre_traverse(CPP2_UFCS(get_initializer)(o)); } - 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 2539 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in t) -> void{ + traverse(t); } -} - -#line 2566 "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); } +#line 2543 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in t) -> void + { + for ( auto const& m : CPP2_UFCS(get_members)(t) ) { + pre_traverse(m); + } + } - sample_print("declaration:", indent + 1); - sample_traverser(CPP2_UFCS(get_declaration)(t), indent + 2); -} +#line 2551 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in t) -> void{ + traverse(t); + } -#line 2585 "reflect.h2" -auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void -{ - if (CPP2_UFCS(is_expression_statement)(stmt)) { - sample_traverser(CPP2_UFCS(get_expression)(CPP2_UFCS(as_expression_statement)(stmt)), indent); +#line 2555 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in t) -> void + { + pre_traverse(CPP2_UFCS(get_declaration)(t)); } - if (CPP2_UFCS(is_compound_statement)(stmt)) { - sample_traverser(CPP2_UFCS(as_compound_statement)(stmt), indent); +#line 2560 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } - if (CPP2_UFCS(is_selection_statement)(stmt)) +#line 2564 "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); + if (CPP2_UFCS(is_expression_statement)(stmt)) { + pre_traverse(CPP2_UFCS(get_expression)(CPP2_UFCS(as_expression_statement)(stmt))); + } - sample_print("condition:", indent + 1); - sample_traverser(CPP2_UFCS(get_expression)(sel), indent + 2); + if (CPP2_UFCS(is_compound_statement)(stmt)) { + pre_traverse(CPP2_UFCS(as_compound_statement)(stmt)); + } - sample_print("true branch:", indent + 1); - sample_traverser(CPP2_UFCS(get_true_branch)(sel), indent + 2); + if (CPP2_UFCS(is_selection_statement)(stmt)) + { + pre_traverse(CPP2_UFCS(as_selection_statement)(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); + if (CPP2_UFCS(is_declaration)(stmt)) { + pre_traverse(CPP2_UFCS(as_declaration)(stmt)); } - } - if (CPP2_UFCS(is_declaration)(stmt)) { - sample_traverser(CPP2_UFCS(as_declaration)(stmt), indent + 1); - } + if (CPP2_UFCS(is_return_statement)(stmt)) { + pre_traverse(CPP2_UFCS(as_return_statement)(stmt)); + } - if (CPP2_UFCS(is_return_statement)(stmt)) { - sample_traverser(CPP2_UFCS(as_return_statement)(stmt), indent + 1); + if (CPP2_UFCS(is_iteration_statement)(stmt)) { + pre_traverse(CPP2_UFCS(as_iteration_statement)(stmt)); + } + + // TODO: + // using + // contract + // inspect + // jump } - if (CPP2_UFCS(is_iteration_statement)(stmt)) { - sample_traverser(CPP2_UFCS(as_iteration_statement)(stmt), indent + 1); +#line 2599 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } - // TODO: - // using - // contract - // inspect - // jump -} +#line 2603 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in stmt) -> void + { + auto stmts {CPP2_UFCS(get_statements)(stmt)}; -#line 2632 "reflect.h2" -auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void -{ - auto stmts {CPP2_UFCS(get_statements)(stmt)}; + for ( auto const& cur : cpp2::move(stmts) ) { + pre_traverse(cur); + } + } - if (CPP2_UFCS(empty)(stmts)) { - sample_print("compound statement (empty)", indent); - return ; +#line 2613 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } - // Else - sample_print("compound statement", indent); - for ( auto const& stmt2 : cpp2::move(stmts) ) { - sample_traverser(stmt2, indent + 1); +#line 2617 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in stmt) -> void + { + if (CPP2_UFCS(has_expression)(stmt)) { + pre_traverse(CPP2_UFCS(get_expression)(stmt)); + } } -} -#line 2649 "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 2625 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } -} -#line 2659 "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 2629 "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 { - sample_print("while loop:", indent); + 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)); } - 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); + +#line 2648 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in stmt) -> void{ + traverse(stmt); } - if (CPP2_UFCS(has_next)(stmt)) { - sample_print("next expression:", indent + 1); - sample_traverser(CPP2_UFCS(get_next_expression)(stmt), indent + 2); +#line 2652 "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(has_false_branch)(stmt)) { + pre_traverse(CPP2_UFCS(get_false_branch)(stmt)); + } } -} -#line 2691 "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 2663 "reflect.h2" + auto simple_traverser::pre_traverse(cpp2::impl::in expr) -> void + { + // Nothing to select here. + traverse(expr); + } - // 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 2669 "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 2705 "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 2683 "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 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 { + traverse(binexpr); + } } - // Else we're at an actual binary expression with a rhs - else { - sample_print("assignment", indent); -{ -auto first{true}; +#line 2700 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2721 "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 2731 "reflect.h2" } -} -#line 2735 "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 2711 "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-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-or", indent); -{ -auto first{true}; +#line 2728 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2751 "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 2761 "reflect.h2" } -} -#line 2765 "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 2740 "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 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-and", indent); -{ -auto first{true}; +#line 2757 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2781 "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 2791 "reflect.h2" } -} -#line 2795 "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 2768 "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-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("bit-or", indent); -{ -auto first{true}; +#line 2785 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2811 "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 2821 "reflect.h2" } -} -#line 2825 "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 2796 "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-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-xor", indent); -{ -auto first{true}; +#line 2813 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2841 "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 2851 "reflect.h2" } -} -#line 2855 "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 2825 "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 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-and", indent); -{ -auto first{true}; +#line 2842 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2871 "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 2881 "reflect.h2" } -} -#line 2885 "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 2854 "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 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("equality", indent); -{ -auto first{true}; +#line 2871 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2901 "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 2911 "reflect.h2" } -} -#line 2915 "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 2882 "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 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); + // 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("relational", indent); -{ -auto first{true}; +#line 2899 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2931 "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 2941 "reflect.h2" } -} -#line 2945 "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 2910 "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 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); + // 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)))); + } + + // 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 2927 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2961 "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 2971 "reflect.h2" } -} -#line 2975 "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 2938 "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 2955 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 2991 "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 3001 "reflect.h2" } -} -#line 3005 "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 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 2983 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3021 "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 3031 "reflect.h2" } -} -#line 3035 "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 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 3012 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in binexpr) -> void + { + auto terms {CPP2_UFCS(get_terms)(binexpr)}; -#line 3051 "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 3061 "reflect.h2" } -} -#line 3065 "reflect.h2" -auto sample_traverser(cpp2::impl::in isas, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(isas)}; +#line 3023 "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 3039 "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 3091 "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 3050 "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 3106 "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 3057 "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 3073 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in prefix) -> void + { + pre_traverse(CPP2_UFCS(get_postfix_expression)(prefix)); } -} -#line 3130 "reflect.h2" -auto sample_traverser(cpp2::impl::in postfix, cpp2::impl::in indent) -> void -{ - auto terms {CPP2_UFCS(get_terms)(postfix)}; +#line 3078 "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 3094 "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 3113 "reflect.h2" + auto simple_traverser::traverse(cpp2::impl::in uid) -> void + { + static_cast(uid); + } + +#line 3119 "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 3129 "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 3146 "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 3166 "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 3184 "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 3194 "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 3216 "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 3246 "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 3256 "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 3277 "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 3296 "reflect.h2" +auto sample_traverser(cpp2::impl::in stmt, cpp2::impl::in indent) -> void +{ + 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 3343 "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 3360 "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 3370 "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 3402 "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 3416 "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 3432 "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 3442 "reflect.h2" + } +} + +#line 3446 "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 3462 "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 3472 "reflect.h2" + } +} + +#line 3476 "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 3492 "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 3502 "reflect.h2" + } +} + +#line 3506 "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 3522 "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 3532 "reflect.h2" + } +} + +#line 3536 "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 3552 "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 3562 "reflect.h2" + } +} + +#line 3566 "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 3582 "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 3592 "reflect.h2" + } +} + +#line 3596 "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 3612 "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 3622 "reflect.h2" + } +} + +#line 3626 "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 3642 "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 3652 "reflect.h2" + } +} + +#line 3656 "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 3672 "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 3682 "reflect.h2" + } +} + +#line 3686 "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 3702 "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 3712 "reflect.h2" + } +} + +#line 3716 "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 3732 "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 3742 "reflect.h2" + } +} + +#line 3746 "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 3762 "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 3772 "reflect.h2" + } +} + +#line 3776 "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 3802 "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 3817 "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 3841 "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 3874 "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 3885 "reflect.h2" +auto sample_traverser(cpp2::impl::in qid, cpp2::impl::in indent) -> void +{ +{ +auto first{true}; + +#line 3888 "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 3898 "reflect.h2" +} + +#line 3901 "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 3918 "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 3938 "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 3955 "reflect.h2" +//----------------------------------------------------------------------- +// +// autodiff - stub +// + +#line 3970 "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_primal_higher_order_, cpp2::impl::in code_fwd_higher_order_) + : name{ name_ } + , n_args{ n_args_ } + , is_member{ is_member_ } + , code_primal{ code_primal_ } + , code_fwd{ code_fwd_ } + , code_primal_higher_order{ code_primal_higher_order_ } + , code_fwd_higher_order{ code_fwd_higher_order_ }{ + +#line 3981 "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; + } + } + +#line 3989 "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_primal_higher_order{ that.code_primal_higher_order } + , code_fwd_higher_order{ that.code_fwd_higher_order }{} +#line 3989 "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_primal_higher_order = that.code_primal_higher_order; + code_fwd_higher_order = that.code_fwd_higher_order; + return *this; } +#line 3989 "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_primal_higher_order{ std::move(that).code_primal_higher_order } + , code_fwd_higher_order{ std::move(that).code_fwd_higher_order }{} +#line 3989 "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_primal_higher_order = std::move(that).code_primal_higher_order; + code_fwd_higher_order = std::move(that).code_fwd_higher_order; + return *this; }// Default copy. + +#line 3991 "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 3998 "reflect.h2" + // TODO: Maybe use variant here. + +#line 4001 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(){} + +#line 4003 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(cpp2::impl::in name_, cpp2::impl::in decl_, cpp2::impl::in is_member_) + : name{ name_ } + , decl{ decl_ } + , is_member{ is_member_ }{ + +#line 4007 "reflect.h2" + } + +#line 4009 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(autodiff_declared_variable const& that) + : name{ that.name } + , decl{ that.decl } + , is_member{ that.is_member }{} +#line 4009 "reflect.h2" + auto autodiff_declared_variable::operator=(autodiff_declared_variable const& that) -> autodiff_declared_variable& { + name = that.name; + decl = that.decl; + is_member = that.is_member; + return *this; } +#line 4009 "reflect.h2" + autodiff_declared_variable::autodiff_declared_variable(autodiff_declared_variable&& that) noexcept + : name{ std::move(that).name } + , decl{ std::move(that).decl } + , is_member{ std::move(that).is_member }{} +#line 4009 "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_member = std::move(that).is_member; + return *this; } + +#line 4013 "reflect.h2" + // namespace + type name + +#line 4021 "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 4024 "reflect.h2" + } + +#line 4026 "reflect.h2" + [[nodiscard]] auto autodiff_declaration_stack_item::lookup_declaration(cpp2::impl::in decl_name) const& -> lookup_declaration_ret{ + std::vector r {}; +#line 4027 "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 4036 "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 {}; +#line 4037 "reflect.h2" + for ( auto const& cur_context : std::ranges::views::reverse(declared_variables_stack) ) { + for ( auto const& cur : cur_context ) { + if (cur.name == decl_name) { + found = true; + r = cur; + return { std::move(found), std::move(r) }; + } + } + }return { std::move(found), std::move(r) }; + } + + 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 4054 "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 4069 "reflect.h2" + /* is_member = */ + +#line 4075 "reflect.h2" + /* is_member = */ + +#line 4081 "reflect.h2" + /* is_member = */ + +#line 4089 "reflect.h2" + // Members depending on order + +#line 4095 "reflect.h2" + auto autodiff_context::add_variable_declaration(cpp2::impl::in name, cpp2::impl::in type, 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_member)); + } + +#line 4099 "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 4116 "reflect.h2" + auto autodiff_context::set_order(cpp2::impl::in new_order) & -> void{ + order = new_order; + + if (1 == order) { + ad_type = "double"; + } + else { + ad_type = "cpp2::taylor"; + } + } + +#line 4127 "reflect.h2" + [[nodiscard]] auto autodiff_context::is_taylor() const& -> decltype(auto) { return order != 1; } + +#line 4129 "reflect.h2" + [[nodiscard]] auto autodiff_context::gen_temporary() & -> std::string{ + temporary_count += 1; + return "temp_" + cpp2::to_string(temporary_count) + ""; + } + +#line 4134 "reflect.h2" + [[nodiscard]] auto autodiff_context::get_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 += suffix; + } + } + + // Replace with AD type for the AD order. + return string_util::replace_all(cpp2::move(type_d), "double", ad_type); + } + +#line 4152 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_declaration(cpp2::impl::in decl_name) & -> lookup_declaration_ret{ + std::vector r {}; +#line 4153 "reflect.h2" + for ( auto const& cur : std::ranges::views::reverse(declaration_stack) ) { + + std::string cur_full_name {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)(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. + } + } + + return r; + } + +#line 4175 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_variable_declaration(cpp2::impl::in name) & -> autodiff_declared_variable{ + if (name == "_") { + return autodiff_declared_variable(name, "_", false); + } + + for ( auto const& cur_context : std::ranges::views::reverse(declaration_stack) ) { + auto r {CPP2_UFCS(lookup_variable_declaration)(cur_context, name)}; + if (r.found) { + return cpp2::move(r).r; + } + } + + 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 4192 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_function_declaration(cpp2::impl::in decl_name) & -> lookup_function_declaration_ret{ + std::vector r {}; +#line 4193 "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 4202 "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 4203 "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 4212 "reflect.h2" + [[nodiscard]] auto autodiff_context::lookup_type_declaration(cpp2::impl::in decl_name) & -> lookup_type_declaration_ret{ + std::vector r {}; +#line 4213 "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 4222 "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; +#line 4223 "reflect.h2" + autodiff_special_func lookup {func_name, n_args, is_member}; + + m.construct(false); + code_primal.construct(""); + code_fwd.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; + } + else { + code_primal.value() = func.code_primal; + code_fwd.value() = func.code_fwd; + } + return { std::move(m.value()), std::move(code_primal.value()), std::move(code_fwd.value()) }; + } + }return { std::move(m.value()), std::move(code_primal.value()), std::move(code_fwd.value()) }; + } + +#line 4244 "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 4252 "reflect.h2" + auto autodiff_context::add_for_differentiation(cpp2::impl::in t) & -> void{ + auto t_parent {CPP2_UFCS(get_parent)(t)}; + + auto found {false}; + for ( auto& cur : std::ranges::views::reverse(declaration_stack) ) { + if (CPP2_UFCS(is_same)(t_parent, cur.decl)) { + if (!(is_in_list(t, cur.diff_request))) { + CPP2_UFCS(push_back)(cur.diff_request, t); + } + + found = true; + break; + } + } + + if (!(cpp2::move(found))) { + CPP2_UFCS(error)(t, "AD: Could not find parent type/namespace for: " + cpp2::to_string(t) + ""); + } + } + +#line 4272 "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 4282 "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 4287 "reflect.h2" + auto autodiff_context::leave_function() & -> void{ + CPP2_UFCS(pop_back)(CPP2_UFCS(back)(declaration_stack).declared_variables_stack); + } + +#line 4291 "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 4304 "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 4319 "reflect.h2" + auto autodiff_context::finish() & -> void{ + while( !(CPP2_UFCS(empty)(declaration_stack)) ) { + pop_stack(); + } + } + +#line 4331 "reflect.h2" + autodiff_handler_base::autodiff_handler_base(autodiff_context* ctx_) + : ctx{ ctx_ }{ + +#line 4333 "reflect.h2" + } +#line 4331 "reflect.h2" + auto autodiff_handler_base::operator=(autodiff_context* ctx_) -> autodiff_handler_base& { + ctx = ctx_; + diff = ""; + return *this; + +#line 4333 "reflect.h2" + } + +#line 4335 "reflect.h2" + auto autodiff_handler_base::append(autodiff_handler_base const& o) & -> void{ + diff += o.diff; + } + +#line 4349 "reflect.h2" + autodiff_expression_handler::autodiff_expression_handler(autodiff_context* ctx_) + : simple_traverser{ } + , autodiff_handler_base{ ctx_ }{ + +#line 4351 "reflect.h2" + } + +#line 4353 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::add_suffix_if_not_wildcard(cpp2::impl::in lhs) const& -> std::string{ + if ("_" == lhs) { + return lhs; + } + else { + return lhs + (*cpp2::impl::assert_not_null(ctx)).suffix; + } + } + +#line 4362 "reflect.h2" + auto autodiff_expression_handler::gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in rhs, cpp2::impl::in rhs_d) & -> void{ + diff += "" + cpp2::to_string(lhs_d) + " = " + cpp2::to_string(rhs_d) + ";\n"; + diff += "" + cpp2::to_string(lhs) + " = " + cpp2::to_string(rhs) + ";\n"; + } +#line 4366 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_assignment(cpp2::impl::in lhs, cpp2::impl::in lhs_d) & -> decltype(auto) { + return gen_assignment(lhs, lhs_d, primal_expr, fwd_expr); } +#line 4368 "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), primal_expr, fwd_expr); } + +#line 4372 "reflect.h2" + auto autodiff_expression_handler::gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in type, cpp2::impl::in type_d) & -> void{ + diff += "" + cpp2::to_string(lhs_d) + ": " + cpp2::to_string(type_d) + " = " + cpp2::to_string(rhs_d) + ";\n"; + diff += "" + cpp2::to_string(lhs) + " : " + cpp2::to_string(type) + " = " + cpp2::to_string(rhs) + ";\n"; + } +#line 4376 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in rhs, cpp2::impl::in rhs_d, cpp2::impl::in type) & -> decltype(auto) { + return gen_declaration(lhs, lhs_d, rhs, rhs_d, type, CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)); } +#line 4378 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::gen_declaration(cpp2::impl::in lhs, cpp2::impl::in lhs_d, cpp2::impl::in type) & -> decltype(auto) { + return gen_declaration(lhs, lhs_d, primal_expr, fwd_expr, type, CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)); } +#line 4380 "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)).suffix, primal_expr, fwd_expr, type, CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)); } + + autodiff_expression_handler::primal_fwd_name::primal_fwd_name(auto&& primal_, auto&& fwd_) +requires (std::is_convertible_v&> && std::is_convertible_v&>) + : primal{ CPP2_FORWARD(primal_) } + , fwd{ CPP2_FORWARD(fwd_) }{} +autodiff_expression_handler::primal_fwd_name::primal_fwd_name(){} + +#line 4390 "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 4399 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::handle_expression_term(auto const& term) & -> primal_fwd_name{ + if (CPP2_UFCS(is_identifier)(term)) { + auto primal {CPP2_UFCS(to_string)(term)}; + auto fwd {primal + (*cpp2::impl::assert_not_null(ctx)).suffix}; + + auto decl {CPP2_UFCS(lookup_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), primal)}; + if (cpp2::move(decl).is_member) { + fwd = "this" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + "." + fwd; + } + return { cpp2::move(primal), cpp2::move(fwd) }; + } + 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", "" }; + } + 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", "" }; + } + + autodiff_expression_handler ad {ctx}; + ad.pre_traverse(CPP2_UFCS(get_term)(CPP2_UFCS(front)(CPP2_UFCS(get_terms)(cpp2::move(bin_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_name r {t, t + (*cpp2::impl::assert_not_null(ctx)).suffix}; // TODO: Check why on return (t, t + ctx*.suffix) the primal is initialized empty. Probably because of the move(t) + static_cast(cpp2::move(t)); + return r; + } + else { + // Nothing special. A regular expression. + auto expr {term}; + + 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_name r {t, t + (*cpp2::impl::assert_not_null(ctx)).suffix}; // TODO: Check why on return (t, t + ctx*.suffix) the primal is initialized empty. Probably because of the move(t) + static_cast(cpp2::move(t)); + return r; + }} + } + +#line 4450 "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 4456 "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 4468 "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 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)(cpp2::move(primary)) + (*cpp2::impl::assert_not_null(ctx)).suffix; + } + else { + function_name = CPP2_UFCS(to_string)(cpp2::move(primary)); + } +{ +auto i{0}; + +#line 4489 "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)).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 4512 "reflect.h2" + if (handle_special_function(object, object_d, 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 ; + } + + // 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))); + diff += "" + 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 + diff += "" + cpp2::to_string(object) + "."; + } + diff += "" + cpp2::to_string(function_name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + "("; + if (!(CPP2_UFCS(empty)(object))) {// Add this_d argument. + diff += "" + cpp2::to_string(cpp2::move(object_d)) + ", "; + } + for ( auto const& arg : cpp2::move(args) ) { + diff += "" + cpp2::to_string(arg.primal) + ", " + cpp2::to_string(arg.fwd) + ","; + } + diff += ");\n"; + + 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)).suffix}; + + primal_expr = "" + cpp2::to_string(ret_temp) + "." + cpp2::to_string(cpp2::move(ret_name)) + ""; + fwd_expr = "" + cpp2::to_string(cpp2::move(ret_temp)) + "." + cpp2::to_string(cpp2::move(ret_name_d)) + ""; + } + + // TODO: Add function to list of functions/objects for differentiation for the no return case. + } + +#line 4594 "reflect.h2" + [[nodiscard]] auto autodiff_expression_handler::handle_special_function(cpp2::impl::in object, cpp2::impl::in object_d, 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_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 {cpp2::move(r).code_fwd}; + + 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); + } +{ +auto i{1}; + +#line 4615 "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); + } +} + +#line 4623 "reflect.h2" + primal_expr = cpp2::move(code_primal); + fwd_expr = cpp2::move(code_fwd); + + return true; + } + +#line 4629 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in expr) -> void{ + base::traverse(expr); + } + +#line 4633 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Assign expressions are not yet handled."); + } + +#line 4637 "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 4641 "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 4645 "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 4649 "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 4653 "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 4657 "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 4661 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + CPP2_UFCS(error)(binexpr, "AD: Relational expressions are not yet handled."); + } + +#line 4665 "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 4669 "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 4673 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + + auto first {true}; + std::string fwd {""}; + std::string primal {""}; + for ( auto const& term : cpp2::move(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)) + " "; + } + + auto var {handle_expression_term(CPP2_UFCS(get_term)(term))}; + fwd += var.fwd; + primal += cpp2::move(var).primal; + + first = false; + } + + primal_expr = cpp2::move(primal); + fwd_expr = cpp2::move(fwd); + } + +#line 4697 "reflect.h2" + auto autodiff_expression_handler::traverse(cpp2::impl::in binexpr) -> void{ + auto terms {CPP2_UFCS(get_terms)(binexpr)}; + + auto var {handle_expression_term(CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS_LITERAL(terms, 0)))}; + auto arg_a {var.primal}; + auto arg_a_d {var.fwd}; + + int i {1}; + for( ; cpp2::impl::cmp_less(i,CPP2_UFCS(ssize)(terms)); i += 1 ) { + var = handle_expression_term(CPP2_UFCS(get_term)(CPP2_ASSERT_IN_BOUNDS(terms, i))); + auto arg_b {var.primal}; + auto arg_b_d {var.fwd}; + + auto op {CPP2_UFCS(to_string)(CPP2_UFCS(get_op)(CPP2_ASSERT_IN_BOUNDS(terms, i)))}; + + std::string fwd {""}; + std::string primal {""}; + + if ("*" == op) { + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + fwd = "" + cpp2::to_string(arg_a_d) + ".mul(" + cpp2::to_string(cpp2::move(arg_b_d)) + ", " + cpp2::to_string(arg_a) + ", " + cpp2::to_string(arg_b) + ")"; + } + else { + fwd = "" + cpp2::to_string(arg_a) + " * " + cpp2::to_string(cpp2::move(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) { + if (CPP2_UFCS(is_taylor)((*cpp2::impl::assert_not_null(ctx)))) { + fwd = "" + cpp2::to_string(arg_a_d) + ".div(" + cpp2::to_string(cpp2::move(arg_b_d)) + ", " + cpp2::to_string(arg_a) + ", " + cpp2::to_string(arg_b) + ")"; + } + else { + fwd = "" + cpp2::to_string(arg_a_d) + " / " + cpp2::to_string(arg_b) + " - " + cpp2::to_string(arg_a) + " * " + cpp2::to_string(cpp2::move(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)(binexpr, "unkown multiplicative operator '" + cpp2::to_string(cpp2::move(op)) + "'"); + }} + +#line 4738 "reflect.h2" + if (i + 1 == CPP2_UFCS(ssize)(terms)) { + primal_expr = cpp2::move(primal); + fwd_expr = cpp2::move(fwd); + } + else { + // Temporary + auto t {CPP2_UFCS(gen_temporary)((*cpp2::impl::assert_not_null(ctx)))}; + auto t_d {t + (*cpp2::impl::assert_not_null(ctx)).suffix}; + gen_declaration(t, t_d, cpp2::move(primal), cpp2::move(fwd), "", ""); + + arg_a = cpp2::move(t); + arg_a_d = cpp2::move(t_d); + } + } + } + +#line 4754 "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 4758 "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 4774 "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 4781 "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 4794 "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)).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)).suffix; + } + + primal_expr = cpp2::move(obj_access); + fwd_expr = cpp2::move(obj_access_d); + } + } + +#line 4814 "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); + + 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)).suffix) + "." + fwd_expr; + } + } + else {if (CPP2_UFCS(is_expression_list)(primary)) { + if (CPP2_UFCS(is_empty)(CPP2_UFCS(as_expression_list)(primary))) { + primal_expr = "()"; + fwd_expr = "()"; + } + 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 = "()"; + } + 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 4855 "reflect.h2" + autodiff_stmt_handler::autodiff_stmt_handler(autodiff_context* ctx_, cpp2::impl::in mf_) + : simple_traverser{ } + , autodiff_handler_base{ ctx_ } + , mf{ mf_ }{ + +#line 4858 "reflect.h2" + } + +#line 4860 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in decl) -> void{ + base::traverse(decl); + } + +#line 4865 "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 4870 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in o) -> void{ + std::string lhs {CPP2_UFCS(name)(o)}; + auto type {o.type()}; + + auto ad_type {CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)}; + + std::string prim_init {""}; + std::string fwd_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; + + if (type == "_" && cpp2::move(ad).fwd_expr == "()") { + // Special handling for auto initialization from a literal. + fwd_init = " = " + CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), "double") + "()"; + } + } + diff += "" + cpp2::to_string(lhs) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + " : " + cpp2::to_string(cpp2::move(ad_type)) + cpp2::to_string(cpp2::move(fwd_init)) + ";\n"; + diff += "" + cpp2::to_string(lhs) + " : " + cpp2::to_string(type) + cpp2::to_string(cpp2::move(prim_init)) + ";\n"; + + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), cpp2::move(lhs), cpp2::move(type)); + } + +#line 4899 "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 4904 "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 4909 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + base::traverse(stmt); + } + +#line 4914 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + // Brackets are handled by the + diff += "{\n"; + base::traverse(stmt); + diff += "}\n"; + } + +#line 4922 "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 4939 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in stmt) -> void{ + if (CPP2_UFCS(is_while)(stmt)) { + // 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)) { + // 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))}; + diff += "(copy " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + "_d_iter := " + cpp2::to_string(range) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + ".begin())\n"; + 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 + diff += "" + cpp2::to_string(CPP2_UFCS(to_string)(CPP2_UFCS(get_next_expression)(stmt))) + ", "; + } + diff += "" + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + "_d_iter++"; + diff += ") do (" + cpp2::to_string(param_style) + " " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + ": " + cpp2::to_string(CPP2_UFCS(type)(param_decl)) + ") {\n"; + 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)).suffix) + ": " + cpp2::to_string(CPP2_UFCS(type)(param_decl)) + " = " + cpp2::to_string(CPP2_UFCS(name)(param_decl)) + "_d_iter*)"; -#line 3163 "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); + 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)) + "");// TODO: Handle loop/compound context variable declarations. + + pre_traverse(CPP2_UFCS(get_for_body)(stmt)); + diff += "}\n"; + }} } -} -#line 3174 "reflect.h2" -auto sample_traverser(cpp2::impl::in qid, cpp2::impl::in indent) -> void -{ -{ -auto first{true}; +#line 4989 "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)); -#line 3177 "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); + if (CPP2_UFCS(has_false_branch)(stmt)) { + diff += "else "; + pre_traverse(CPP2_UFCS(get_false_branch)(stmt)); } - first = false; - sample_print("unqualified:", indent + 1); - sample_traverser(CPP2_UFCS(get_unqualified)(term), indent + 2); } -} -#line 3187 "reflect.h2" -} -#line 3190 "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 5000 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in expr) -> void{ + base::traverse(expr); } - else {if (CPP2_UFCS(is_qualified_id)(tid)) { - sample_traverser(CPP2_UFCS(as_qualified_id)(tid), indent); + +#line 5004 "reflect.h2" + auto autodiff_stmt_handler::traverse(cpp2::impl::in binexpr) -> void{ + 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))); + CPP2_UFCS(gen_assignment)(h, h_lhs.primal_expr, cpp2::move(h_lhs).fwd_expr); + append(cpp2::move(h)); } - else {if (CPP2_UFCS(is_unqualified_id)(tid)) { - sample_traverser(CPP2_UFCS(as_unqualified_id)(tid), indent); + +#line 5017 "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 { - sample_print(CPP2_UFCS(to_string)(tid), indent); - }}} -} -#line 3207 "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 5021 "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_expression_list)(primary)) { - sample_traverser(CPP2_UFCS(as_expression_list)(primary), indent + 1); + +#line 5025 "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 {if (CPP2_UFCS(is_literal)(primary)) { - sample_print(CPP2_UFCS(as_literal)(primary), indent + 1); + +#line 5029 "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_declaration)(primary)) { - sample_traverser(CPP2_UFCS(as_declaration)(primary), indent + 1); + +#line 5033 "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 { - sample_print(CPP2_UFCS(to_string)(primary), indent + 1); - }}}} -} -#line 3227 "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 5037 "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_qualified)(idexpr)) { - sample_traverser(CPP2_UFCS(as_qualified)(idexpr), indent + 1); + +#line 5041 "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 {if (CPP2_UFCS(is_unqualified)(idexpr)) { - sample_traverser(CPP2_UFCS(as_unqualified)(idexpr), indent + 1); + +#line 5045 "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 { - sample_print(CPP2_UFCS(to_string)(idexpr), indent + 1); - }}} -} -#line 3244 "reflect.h2" -//----------------------------------------------------------------------- -// -// autodiff - stub -// +#line 5049 "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."); + } -#line 3255 "reflect.h2" - [[nodiscard]] auto autodiff_impl::gen_temporary() & -> std::string{ - temporary_count += 1; - return "temp_" + cpp2::to_string(temporary_count) + ""; +#line 5053 "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."); } -#line 3260 "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 5057 "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 3272 "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 5061 "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."); + } - return ; - } +#line 5065 "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."); + } - // 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)) + "___"; - } - diff += ";"; +#line 5070 "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_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)) + "___"; +#line 5077 "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 standalone postfix expression. op: " + cpp2::to_string(CPP2_UFCS(get_op)(term)) + " expr: " + cpp2::to_string(postfix) + ""); } - diff += ";"; + } while (false); i += 1; } +} + // Check for function call, everything else is not handled. +#line 5090 "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)(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 += ";"; + 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 5102 "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_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 5119 "reflect.h2" + autodiff_declaration_handler::autodiff_declaration_handler(autodiff_context* ctx_, cpp2::impl::in decl_) + : simple_traverser{ } + , autodiff_handler_base{ ctx_ } + , decl{ decl_ }{ - return ; - } +#line 5122 "reflect.h2" + } - // 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 += ";"; +#line 5124 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in decl) -> void{ + base::traverse(decl); + } - return ; - } +#line 5129 "reflect.h2" + auto autodiff_declaration_handler::traverse(cpp2::impl::in f) -> void{ + CPP2_UFCS(enter_function)((*cpp2::impl::assert_not_null(ctx))); - // 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) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; - } - diff += ";"; + diff = " " + cpp2::to_string(CPP2_UFCS(name)(f)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + ": ("; - return ; - } + // 1. Generate the modified signature + // a) Parameters - // 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) + "___"; - } - diff += CPP2_UFCS(to_string)(CPP2_UFCS(get_term)(term)) + "___"; + for ( auto const& param : CPP2_UFCS(get_parameters)(f) ) { + std::string name {CPP2_UFCS(name)(CPP2_UFCS(get_declaration)(param))}; + + if ("this" == name) { + auto ad_type {CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), std::string(CPP2_UFCS(name)(decl)))}; + diff += "" + cpp2::to_string(name) + ", "; + diff += "" + cpp2::to_string(cpp2::move(name)) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + ": " + cpp2::to_string(cpp2::move(ad_type)) + ", "; } - diff += ";"; + else { + auto type {CPP2_UFCS(get_declaration)(param).type()}; + diff += "" + cpp2::to_string(name) + " : " + cpp2::to_string(type) + ", "; + diff += "" + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + ", "; - return ; + CPP2_UFCS(add_variable_declaration)((*cpp2::impl::assert_not_null(ctx)), cpp2::move(name), cpp2::move(type)); + } } - // 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)) + "___"; - } - diff += ";"; + diff += ") -> ("; - return ; - } + // b) Returns - // Handle binary + and - - if (CPP2_UFCS(ssize)(shift_terms) != 1) { - CPP2_UFCS(error)(mf, "ICE: there should be exactly one shift term here"); + 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. + diff += "r, r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + ", "; + } + else { + diff += "r: " + cpp2::to_string(CPP2_UFCS(get_unnamed_return_type)(f)) + " = (), r" + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + ": " + cpp2::to_string(CPP2_UFCS(get_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)) + " "; - } - - auto var {handle_expression_term(mf, CPP2_UFCS(get_term)(term))}; - fwd += "" + cpp2::to_string(var) + "_d"; - primal += "" + cpp2::to_string(cpp2::move(var)) + ""; + 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()}; + diff += "" + cpp2::to_string(name) + " : " + cpp2::to_string(CPP2_UFCS(type)(CPP2_UFCS(get_declaration)(param))) + " = 0.0, "; + diff += "" + cpp2::to_string(name) + cpp2::to_string((*cpp2::impl::assert_not_null(ctx)).suffix) + " : " + cpp2::to_string(CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), type)) + " = 0.0, "; - 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)) + ""); } + } - fwd += ";"; - 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 5189 "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 5192 "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); } + diff += cpp2::move(ad_impl).diff; - 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)))}; + 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)))}; + CPP2_UFCS(add_member)(decl, diff); + 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 5209 "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)).suffix) + ""}; + std::string ad_type {CPP2_UFCS(get_ad_type)((*cpp2::impl::assert_not_null(ctx)), CPP2_UFCS(type)(o))}; + std::string ad_init {""}; -#line 3546 "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(ad_type)) + cpp2::to_string(cpp2::move(ad_init)) + ";"; + + if (is_type_context) { + + diff_ad_type += "public " + cpp2::to_string(diff) + "\n"; + } + else { + CPP2_UFCS(add_member)(decl, diff); } + 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); } -#line 3565 "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 5237 "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)).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); + diff = ""; } } -#line 3592 "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 5261 "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 5266 "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 5272 "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 order_token{ "order=" }; - diff += ") -> ("; + auto args {CPP2_UFCS(get_arguments)(t)}; - // b) Returns + std::string suffix {"_d"}; + int order {1}; + 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)(arg, CPP2_UFCS(size)(suffix_token)); + continue; + } + 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; + } } - diff += ") = {"; + CPP2_UFCS(error)(t, "AD: Unknown argument: " + cpp2::to_string(arg_str) + ""); + return ; + } - // Generate the body + autodiff_context ad_ctx {}; + ad_ctx.suffix = cpp2::move(suffix); + CPP2_UFCS(set_order)(ad_ctx, order); - if (!(CPP2_UFCS(has_compound_body)(mf))) { - CPP2_UFCS(error)(mf, "temporary alpha limitation: a differentiable function must have a {}-enclosed body"); - return ; - } +#line 5308 "reflect.h2" + 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 3631 "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"); } + + CPP2_UFCS(finish)(ad_ctx); + + static_cast(cpp2::move(ad_ctx)); } @@ -6708,7 +9213,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 3647 "reflect.h2" +#line 5346 "reflect.h2" //----------------------------------------------------------------------- // // regex - creates regular expressions from members @@ -6724,11 +9229,11 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov // ``` // -#line 3663 "reflect.h2" +#line 5362 "reflect.h2" // Possible modifiers for a regular expression. // -#line 3667 "reflect.h2" +#line 5366 "reflect.h2" // mod: i // mod: m // mod: s @@ -6736,116 +9241,116 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov // mod: x // mod: xx -#line 3676 "reflect.h2" +#line 5375 "reflect.h2" // Tokens for regular expressions. // // Basic class for a regex token. // -#line 3685 "reflect.h2" +#line 5384 "reflect.h2" regex_token::regex_token(cpp2::impl::in str) : string_rep{ str }{ -#line 3687 "reflect.h2" +#line 5386 "reflect.h2" } -#line 3689 "reflect.h2" +#line 5388 "reflect.h2" regex_token::regex_token() : string_rep{ "" }{ -#line 3691 "reflect.h2" +#line 5390 "reflect.h2" } //parse: (inout ctx: parse_context) -> token_ptr; // Generate the matching code. // Create a reverse token for look behind expressions. -#line 3697 "reflect.h2" +#line 5396 "reflect.h2" auto regex_token::add_groups([[maybe_unused]] std::set& unnamed_param_2) const -> void{}// Adds all group indices to the set. -#line 3698 "reflect.h2" +#line 5397 "reflect.h2" [[nodiscard]] auto regex_token::to_string() const& -> std::string{return string_rep; }// Create a string representation. -#line 3699 "reflect.h2" +#line 5398 "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 3714 "reflect.h2" +#line 5413 "reflect.h2" regex_token_check::regex_token_check(cpp2::impl::in str, cpp2::impl::in check_) : regex_token{ str } , check{ check_ }{ -#line 3717 "reflect.h2" +#line 5416 "reflect.h2" } -#line 3719 "reflect.h2" +#line 5418 "reflect.h2" auto regex_token_check::generate_code(generation_context& ctx) const -> void{ ctx.add_check(check + "(" + ctx.match_parameters() + ")"); } -#line 3723 "reflect.h2" +#line 5422 "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 3735 "reflect.h2" +#line 5434 "reflect.h2" regex_token_code::regex_token_code(cpp2::impl::in str, cpp2::impl::in code_) : regex_token{ str } , code{ code_ }{ -#line 3738 "reflect.h2" +#line 5437 "reflect.h2" } -#line 3740 "reflect.h2" +#line 5439 "reflect.h2" auto regex_token_code::generate_code(generation_context& ctx) const -> void{ ctx.add(code); } -#line 3744 "reflect.h2" +#line 5443 "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 3754 "reflect.h2" +#line 5453 "reflect.h2" regex_token_empty::regex_token_empty(cpp2::impl::in str) : regex_token{ str }{ -#line 3756 "reflect.h2" +#line 5455 "reflect.h2" } -#line 3758 "reflect.h2" +#line 5457 "reflect.h2" auto regex_token_empty::generate_code([[maybe_unused]] generation_context& unnamed_param_2) const -> void{ // Nothing. } -#line 3762 "reflect.h2" +#line 5461 "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 3774 "reflect.h2" +#line 5473 "reflect.h2" regex_token_list::regex_token_list(cpp2::impl::in t) : regex_token{ gen_string(t) } , tokens{ t }{ -#line 3777 "reflect.h2" +#line 5476 "reflect.h2" } -#line 3779 "reflect.h2" +#line 5478 "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 3785 "reflect.h2" +#line 5484 "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 3791 "reflect.h2" +#line 5490 "reflect.h2" [[nodiscard]] auto regex_token_list::gen_string(cpp2::impl::in vec) -> std::string{ std::string r {""}; for ( auto const& token : vec ) { @@ -6854,7 +9359,7 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov return r; } -#line 3799 "reflect.h2" +#line 5498 "reflect.h2" [[nodiscard]] auto regex_token_list::reverse() const -> token_ptr{ int s {cpp2::unchecked_narrow(tokens.size())}; @@ -6870,7 +9375,7 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov regex_token_list::~regex_token_list() noexcept{} -#line 3827 "reflect.h2" +#line 5526 "reflect.h2" auto parse_context_group_state::next_alternative() & -> void{ token_vec new_list {}; std::swap(new_list, cur_match_list); @@ -6878,14 +9383,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 3835 "reflect.h2" +#line 5534 "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 3842 "reflect.h2" +#line 5541 "reflect.h2" [[nodiscard]] auto parse_context_group_state::get_as_token() & -> token_ptr{ if (alternate_match_lists.empty()) { post_process_list(cur_match_list); @@ -6897,15 +9402,15 @@ std::string str {s}; return from_string(cpp2::string_util::replace_all(cpp2::mov } } -#line 3854 "reflect.h2" +#line 5553 "reflect.h2" auto parse_context_group_state::add(cpp2::impl::in token) & -> void{ cur_match_list.push_back(token); } -#line 3859 "reflect.h2" +#line 5558 "reflect.h2" [[nodiscard]] auto parse_context_group_state::empty() const& -> bool { return cur_match_list.empty(); } -#line 3863 "reflect.h2" +#line 5562 "reflect.h2" auto parse_context_group_state::post_process_list(token_vec& list) -> void{ // Merge all characters auto merge_pos {list.begin()}; @@ -6926,7 +9431,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 3889 "reflect.h2" +#line 5588 "reflect.h2" [[nodiscard]] auto parse_context_branch_reset_state::next() & -> int{ auto g {cur_group}; cur_group += 1; @@ -6935,20 +9440,20 @@ parse_context_group_state::parse_context_group_state(){} return g; } -#line 3898 "reflect.h2" +#line 5597 "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 3904 "reflect.h2" +#line 5603 "reflect.h2" auto parse_context_branch_reset_state::next_alternative() & -> void{ if (is_active) { cur_group = from; } } -#line 3911 "reflect.h2" +#line 5610 "reflect.h2" auto parse_context_branch_reset_state::set_active_reset(cpp2::impl::in restart) & -> void{ is_active = true; cur_group = restart; @@ -6963,16 +9468,16 @@ parse_context_group_state::parse_context_group_state(){} , from{ from_ }{} parse_context_branch_reset_state::parse_context_branch_reset_state(){} -#line 3941 "reflect.h2" +#line 5640 "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 3945 "reflect.h2" +#line 5644 "reflect.h2" } -#line 3951 "reflect.h2" +#line 5650 "reflect.h2" [[nodiscard]] auto parse_context::start_group() & -> parse_context_group_state { parse_context_group_state old_state {}; @@ -6982,7 +9487,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return old_state; } -#line 3961 "reflect.h2" +#line 5660 "reflect.h2" [[nodiscard]] auto parse_context::end_group(cpp2::impl::in old_state) & -> token_ptr { auto inner {cur_group_state.get_as_token()}; @@ -6990,17 +9495,17 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return inner; } -#line 3968 "reflect.h2" +#line 5667 "reflect.h2" [[nodiscard]] auto parse_context::get_modifiers() const& -> expression_flags{ return cur_group_state.modifiers; } -#line 3972 "reflect.h2" +#line 5671 "reflect.h2" auto parse_context::set_modifiers(cpp2::impl::in mod) & -> void{ cur_group_state.modifiers = mod; } -#line 3979 "reflect.h2" +#line 5678 "reflect.h2" [[nodiscard]] auto parse_context::branch_reset_new_state() & -> parse_context_branch_reset_state { parse_context_branch_reset_state old_state {}; @@ -7010,7 +9515,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return old_state; } -#line 3988 "reflect.h2" +#line 5687 "reflect.h2" auto parse_context::branch_reset_restore_state(cpp2::impl::in old_state) & -> void { auto max_group {cur_branch_reset_state.max_group}; @@ -7018,24 +9523,24 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} cur_branch_reset_state.set_next(cpp2::move(max_group)); } -#line 3995 "reflect.h2" +#line 5694 "reflect.h2" auto parse_context::next_alternative() & -> void { cur_group_state.next_alternative(); cur_branch_reset_state.next_alternative(); } -#line 4003 "reflect.h2" +#line 5702 "reflect.h2" auto parse_context::add_token(cpp2::impl::in token) & -> void{ cur_group_state.add(token); } -#line 4007 "reflect.h2" +#line 5706 "reflect.h2" [[nodiscard]] auto parse_context::has_token() const& -> bool{ return !(cur_group_state.empty()); } -#line 4011 "reflect.h2" +#line 5710 "reflect.h2" [[nodiscard]] auto parse_context::pop_token() & -> token_ptr { token_ptr r {nullptr}; @@ -7047,22 +9552,22 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return r; } -#line 4022 "reflect.h2" +#line 5721 "reflect.h2" [[nodiscard]] auto parse_context::get_as_token() & -> token_ptr{ return root; } -#line 4028 "reflect.h2" +#line 5727 "reflect.h2" [[nodiscard]] auto parse_context::get_cur_group() const& -> int{ return cur_branch_reset_state.cur_group; } -#line 4032 "reflect.h2" +#line 5731 "reflect.h2" [[nodiscard]] auto parse_context::next_group() & -> int{ return cur_branch_reset_state.next(); } -#line 4036 "reflect.h2" +#line 5735 "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. @@ -7070,7 +9575,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4043 "reflect.h2" +#line 5742 "reflect.h2" [[nodiscard]] auto parse_context::get_named_group(cpp2::impl::in name) const& -> int { auto iter {named_groups.find(name)}; @@ -7082,10 +9587,10 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4056 "reflect.h2" +#line 5755 "reflect.h2" [[nodiscard]] auto parse_context::current() const& -> char{return CPP2_ASSERT_IN_BOUNDS(regex, pos); } -#line 4059 "reflect.h2" +#line 5758 "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}; @@ -7125,7 +9630,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return cur; } -#line 4099 "reflect.h2" +#line 5798 "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); @@ -7137,14 +9642,14 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4110 "reflect.h2" +#line 5809 "reflect.h2" [[nodiscard]] auto parse_context::next() & -> decltype(auto) { return next_impl(false, false); } -#line 4111 "reflect.h2" +#line 5810 "reflect.h2" [[nodiscard]] auto parse_context::next_in_class() & -> decltype(auto) { return next_impl(true, false); } -#line 4112 "reflect.h2" +#line 5811 "reflect.h2" [[nodiscard]] auto parse_context::next_no_skip() & -> decltype(auto) { return next_impl(false, true); } -#line 4114 "reflect.h2" +#line 5813 "reflect.h2" [[nodiscard]] auto parse_context::next_n(cpp2::impl::in n) & -> bool{ auto r {true}; auto cur {0}; @@ -7154,10 +9659,10 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return r; } -#line 4123 "reflect.h2" +#line 5822 "reflect.h2" [[nodiscard]] auto parse_context::has_next() const& -> bool{return cpp2::impl::cmp_less(pos,regex.size()); } -#line 4125 "reflect.h2" +#line 5824 "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) @@ -7179,14 +9684,14 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4146 "reflect.h2" +#line 5845 "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 4147 "reflect.h2" +#line 5846 "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 4148 "reflect.h2" +#line 5847 "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 4150 "reflect.h2" +#line 5849 "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())) { @@ -7200,7 +9705,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4163 "reflect.h2" +#line 5862 "reflect.h2" [[nodiscard]] auto parse_context::grab_number() & -> std::string { auto start {pos}; @@ -7222,7 +9727,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return cpp2::move(r.value()); } -#line 4184 "reflect.h2" +#line 5883 "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())) { @@ -7233,12 +9738,12 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4194 "reflect.h2" +#line 5893 "reflect.h2" [[nodiscard]] auto parse_context::peek() const& -> decltype(auto) { return peek_impl(false); } -#line 4195 "reflect.h2" +#line 5894 "reflect.h2" [[nodiscard]] auto parse_context::peek_in_class() const& -> decltype(auto) { return peek_impl(true); } -#line 4200 "reflect.h2" +#line 5899 "reflect.h2" [[nodiscard]] auto parse_context::parser_group_modifiers(cpp2::impl::in change_str, expression_flags& parser_modifiers) & -> bool { auto is_negative {false}; @@ -7293,7 +9798,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return true; } -#line 4254 "reflect.h2" +#line 5953 "reflect.h2" [[nodiscard]] auto parse_context::parse_until(cpp2::impl::in term) & -> bool{ token_ptr cur_token {}; @@ -7333,7 +9838,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return true; } -#line 4293 "reflect.h2" +#line 5992 "reflect.h2" [[nodiscard]] auto parse_context::parse(cpp2::impl::in modifiers) & -> bool { @@ -7349,21 +9854,21 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} return r; } -#line 4310 "reflect.h2" +#line 6009 "reflect.h2" [[nodiscard]] auto parse_context::get_pos() const& -> decltype(auto) { return pos; } -#line 4311 "reflect.h2" +#line 6010 "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 4312 "reflect.h2" +#line 6011 "reflect.h2" [[nodiscard]] auto parse_context::valid() const& -> bool{return has_next() && !(has_error); } -#line 4314 "reflect.h2" +#line 6013 "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 4329 "reflect.h2" +#line 6028 "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 ) { @@ -7371,7 +9876,7 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} } } -#line 4336 "reflect.h2" +#line 6035 "reflect.h2" auto generation_function_context::remove_tabs(cpp2::impl::in c) & -> void{ tabs = tabs.substr(0, (cpp2::impl::as_(c)) * 2); } @@ -7381,22 +9886,22 @@ parse_context_branch_reset_state::parse_context_branch_reset_state(){} , tabs{ tabs_ }{} generation_function_context::generation_function_context(){} -#line 4354 "reflect.h2" +#line 6053 "reflect.h2" [[nodiscard]] auto generation_context::match_parameters() const& -> std::string{return "r.pos, ctx"; } -#line 4359 "reflect.h2" +#line 6058 "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 4365 "reflect.h2" +#line 6064 "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 4371 "reflect.h2" +#line 6070 "reflect.h2" auto generation_context::add_statefull(cpp2::impl::in next_func, cpp2::impl::in check) & -> void { end_func_statefull(check); @@ -7405,7 +9910,7 @@ generation_function_context::generation_function_context(){} start_func_named(cpp2::move(name)); } -#line 4379 "reflect.h2" +#line 6078 "reflect.h2" auto generation_context::start_func_named(cpp2::impl::in name) & -> void { auto cur {new_context()}; @@ -7417,7 +9922,7 @@ generation_function_context::generation_function_context(){} (*cpp2::impl::assert_not_null(cpp2::move(cur))).add_tabs(3); } -#line 4390 "reflect.h2" +#line 6089 "reflect.h2" [[nodiscard]] auto generation_context::start_func() & -> std::string { auto name {gen_func_name()}; @@ -7425,7 +9930,7 @@ generation_function_context::generation_function_context(){} return cpp2::move(name) + "()"; } -#line 4397 "reflect.h2" +#line 6096 "reflect.h2" auto generation_context::end_func_statefull(cpp2::impl::in s) & -> void { auto cur {get_current()}; @@ -7446,7 +9951,7 @@ generation_function_context::generation_function_context(){} finish_context(); } -#line 4418 "reflect.h2" +#line 6117 "reflect.h2" [[nodiscard]] auto generation_context::generate_func(cpp2::impl::in token) & -> std::string { auto name {start_func()}; @@ -7456,7 +9961,7 @@ generation_function_context::generation_function_context(){} return name; } -#line 4428 "reflect.h2" +#line 6127 "reflect.h2" [[nodiscard]] auto generation_context::generate_reset(cpp2::impl::in> groups) & -> std::string { if (groups.empty()) { @@ -7479,33 +9984,33 @@ generation_function_context::generation_function_context(){} return cpp2::move(name) + "()"; } -#line 4452 "reflect.h2" +#line 6151 "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 4458 "reflect.h2" +#line 6157 "reflect.h2" [[nodiscard]] auto generation_context::next_func_name() & -> std::string{ return gen_func_name() + "()"; } -#line 4462 "reflect.h2" +#line 6161 "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 4468 "reflect.h2" +#line 6167 "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 4476 "reflect.h2" +#line 6175 "reflect.h2" [[nodiscard]] auto generation_context::new_context() & -> generation_function_context*{ gen_stack.push_back(generation_function_context()); auto cur {get_current()}; @@ -7514,7 +10019,7 @@ generation_function_context::generation_function_context(){} return cur; } -#line 4484 "reflect.h2" +#line 6183 "reflect.h2" auto generation_context::finish_context() & -> void{ auto cur {get_current()}; auto base {get_base()}; @@ -7523,22 +10028,22 @@ generation_function_context::generation_function_context(){} gen_stack.pop_back(); } -#line 4494 "reflect.h2" +#line 6193 "reflect.h2" [[nodiscard]] auto generation_context::get_current() & -> generation_function_context*{ return &gen_stack.back(); } -#line 4498 "reflect.h2" +#line 6197 "reflect.h2" [[nodiscard]] auto generation_context::get_base() & -> generation_function_context*{ return &CPP2_ASSERT_IN_BOUNDS_LITERAL(gen_stack, 0); } -#line 4502 "reflect.h2" +#line 6201 "reflect.h2" [[nodiscard]] auto generation_context::get_entry_func() const& -> std::string{ return entry_func; } -#line 4506 "reflect.h2" +#line 6205 "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"}; @@ -7562,18 +10067,18 @@ generation_function_context::generation_function_context(){} return res; } -#line 4531 "reflect.h2" +#line 6230 "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 4546 "reflect.h2" +#line 6245 "reflect.h2" alternative_token::alternative_token() : regex_token_empty{ "" }{} -#line 4548 "reflect.h2" +#line 6247 "reflect.h2" [[nodiscard]] auto alternative_token::parse(parse_context& ctx) -> token_ptr{ if (ctx.current() != '|') {return nullptr; } @@ -7584,15 +10089,15 @@ generation_function_context::generation_function_context(){} alternative_token::~alternative_token() noexcept{} -#line 4563 "reflect.h2" +#line 6262 "reflect.h2" alternative_token_gen::alternative_token_gen(cpp2::impl::in a) : regex_token{ gen_string(a) } , alternatives{ a }{ -#line 4566 "reflect.h2" +#line 6265 "reflect.h2" } -#line 4568 "reflect.h2" +#line 6267 "reflect.h2" auto alternative_token_gen::generate_code(generation_context& ctx) const -> void { std::string functions {""}; @@ -7610,7 +10115,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 4585 "reflect.h2" +#line 6284 "reflect.h2" auto alternative_token_gen::add_groups(std::set& groups) const -> void { for ( auto const& cur : alternatives ) { @@ -7618,7 +10123,7 @@ generation_function_context::generation_function_context(){} } } -#line 4592 "reflect.h2" +#line 6291 "reflect.h2" [[nodiscard]] auto alternative_token_gen::gen_string(cpp2::impl::in a) -> std::string { std::string r {""}; @@ -7632,7 +10137,7 @@ generation_function_context::generation_function_context(){} return r; } -#line 4605 "reflect.h2" +#line 6304 "reflect.h2" [[nodiscard]] auto alternative_token_gen::reverse() const -> token_ptr{ int s {cpp2::unchecked_narrow(alternatives.size())}; @@ -7648,14 +10153,14 @@ generation_function_context::generation_function_context(){} alternative_token_gen::~alternative_token_gen() noexcept{} -#line 4626 "reflect.h2" +#line 6325 "reflect.h2" any_token::any_token(cpp2::impl::in single_line) : regex_token_check{ ".", "any_token_matcher" }{ -#line 4628 "reflect.h2" +#line 6327 "reflect.h2" } -#line 4630 "reflect.h2" +#line 6329 "reflect.h2" [[nodiscard]] auto any_token::parse(parse_context& ctx) -> token_ptr{ if ('.' != ctx.current()) {return nullptr; } @@ -7664,11 +10169,11 @@ generation_function_context::generation_function_context(){} any_token::~any_token() noexcept{} -#line 4645 "reflect.h2" +#line 6344 "reflect.h2" atomic_group_token::atomic_group_token() : regex_token{ "" }{} -#line 4647 "reflect.h2" +#line 6346 "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))); @@ -7676,7 +10181,7 @@ generation_function_context::generation_function_context(){} return r; } -#line 4654 "reflect.h2" +#line 6353 "reflect.h2" auto atomic_group_token::generate_code(generation_context& ctx) const -> void { auto inner_name {ctx.generate_func(inner_token)}; @@ -7685,37 +10190,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 4662 "reflect.h2" +#line 6361 "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 4676 "reflect.h2" +#line 6375 "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 4680 "reflect.h2" +#line 6379 "reflect.h2" } -#line 4682 "reflect.h2" +#line 6381 "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 4686 "reflect.h2" +#line 6385 "reflect.h2" } -#line 4688 "reflect.h2" +#line 6387 "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 4692 "reflect.h2" +#line 6391 "reflect.h2" auto char_token::generate_code(generation_context& ctx) const -> void { if (ignore_case) { @@ -7724,14 +10229,14 @@ generation_function_context::generation_function_context(){} { size_t i{0}; -#line 4698 "reflect.h2" +#line 6397 "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 4703 "reflect.h2" +#line 6402 "reflect.h2" if (upper != lower) { gen_case_insensitive(cpp2::move(lower), cpp2::move(upper), ctx); } @@ -7744,7 +10249,7 @@ size_t i{0}; } } -#line 4715 "reflect.h2" +#line 6414 "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()) + ""}; @@ -7766,7 +10271,7 @@ size_t i{0}; ctx.add("else { break; }"); } -#line 4736 "reflect.h2" +#line 6435 "reflect.h2" auto char_token::gen_case_sensitive(generation_context& ctx) const& -> void { std::string name {"str_" + cpp2::to_string(ctx.gen_temp()) + ""}; @@ -7785,7 +10290,7 @@ size_t i{0}; ctx.add("else { break; }"); } -#line 4754 "reflect.h2" +#line 6453 "reflect.h2" [[nodiscard]] auto char_token::add_escapes(std::string str) const& -> std::string { str = string_util::replace_all(str, "\\", "\\\\"); @@ -7801,14 +10306,14 @@ size_t i{0}; return cpp2::move(str); } -#line 4769 "reflect.h2" +#line 6468 "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 4775 "reflect.h2" +#line 6474 "reflect.h2" auto char_token::append(char_token const& that) & -> void{ (*this).token += that.token; (*this).string_rep += that.string_rep; @@ -7816,19 +10321,19 @@ size_t i{0}; char_token::~char_token() noexcept{} -#line 4792 "reflect.h2" +#line 6491 "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 4793 "reflect.h2" +#line 6492 "reflect.h2" { -#line 4798 "reflect.h2" +#line 6497 "reflect.h2" } -#line 4801 "reflect.h2" +#line 6500 "reflect.h2" [[nodiscard]] auto class_token::parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '[') {return nullptr; } @@ -7954,7 +10459,7 @@ size_t i{0}; ); } -#line 4926 "reflect.h2" +#line 6625 "reflect.h2" [[nodiscard]] auto class_token::reverse() const -> token_ptr{ return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, negate, @@ -7964,13 +10469,13 @@ size_t i{0}; ); } -#line 4935 "reflect.h2" +#line 6634 "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 4940 "reflect.h2" +#line 6639 "reflect.h2" [[nodiscard]] auto class_token::create_matcher(cpp2::impl::in name, cpp2::impl::in template_arguments) -> std::string { auto sep {", "}; @@ -7981,12 +10486,12 @@ size_t i{0}; class_token::~class_token() noexcept{} -#line 4952 "reflect.h2" +#line 6651 "reflect.h2" [[nodiscard]] auto escape_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } -#line 4957 "reflect.h2" +#line 6656 "reflect.h2" if (std::string::npos == std::string("afenrt^.[]()*{}?+|\\").find(ctx.peek())) { return nullptr; } @@ -8020,7 +10525,7 @@ size_t i{0}; } -#line 4993 "reflect.h2" +#line 6692 "reflect.h2" [[nodiscard]] auto global_group_reset_token_parse(parse_context& ctx) -> token_ptr { if (!((ctx.current() == '\\' && ctx.peek() == 'K'))) {return nullptr; } @@ -8029,19 +10534,19 @@ size_t i{0}; return CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared, "\\K", "ctx..set_group_start(0, r.pos);"); } -#line 5016 "reflect.h2" +#line 6715 "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 5017 "reflect.h2" +#line 6716 "reflect.h2" { -#line 5022 "reflect.h2" +#line 6721 "reflect.h2" } -#line 5024 "reflect.h2" +#line 6723 "reflect.h2" [[nodiscard]] auto group_ref_token::parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8143,19 +10648,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 5125 "reflect.h2" +#line 6824 "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 5129 "reflect.h2" +#line 6828 "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 5153 "reflect.h2" +#line 6852 "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 @@ -8174,7 +10679,7 @@ size_t i{0}; return r; } -#line 5171 "reflect.h2" +#line 6870 "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 @@ -8189,7 +10694,7 @@ size_t i{0}; return r; } -#line 5185 "reflect.h2" +#line 6884 "reflect.h2" [[nodiscard]] auto group_token::parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '(') {return nullptr; } @@ -8349,7 +10854,7 @@ size_t i{0}; } } -#line 5344 "reflect.h2" +#line 7043 "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; @@ -8358,7 +10863,7 @@ size_t i{0}; return r; } -#line 5352 "reflect.h2" +#line 7051 "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 {"("}; @@ -8377,7 +10882,7 @@ size_t i{0}; return cpp2::move(start) + (*cpp2::impl::assert_not_null(inner_)).to_string() + ")"; } -#line 5370 "reflect.h2" +#line 7069 "reflect.h2" auto group_token::generate_code(generation_context& ctx) const -> void { if (-1 != number) { @@ -8409,7 +10914,7 @@ size_t i{0}; } } -#line 5401 "reflect.h2" +#line 7100 "reflect.h2" auto group_token::add_groups(std::set& groups) const -> void { (*cpp2::impl::assert_not_null(inner)).add_groups(groups); @@ -8420,7 +10925,7 @@ size_t i{0}; group_token::~group_token() noexcept{} -#line 5413 "reflect.h2" +#line 7112 "reflect.h2" [[nodiscard]] auto hexadecimal_token_parse(parse_context& ctx) -> token_ptr { if (!((ctx.current() == '\\' && ctx.peek() == 'x'))) {return nullptr; } @@ -8459,7 +10964,7 @@ size_t i{0}; return r; } -#line 5454 "reflect.h2" +#line 7153 "reflect.h2" [[nodiscard]] auto line_end_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() == '$' || (ctx.current() == '\\' && ctx.peek() == '$')) { @@ -8477,7 +10982,7 @@ size_t i{0}; }} } -#line 5474 "reflect.h2" +#line 7173 "reflect.h2" [[nodiscard]] auto line_start_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '^' && !((ctx.current() == '\\' && ctx.peek() == 'A'))) {return nullptr; } @@ -8491,16 +10996,16 @@ size_t i{0}; } } -#line 5500 "reflect.h2" +#line 7199 "reflect.h2" lookahead_lookbehind_token::lookahead_lookbehind_token(cpp2::impl::in lookahead_, cpp2::impl::in positive_) : regex_token{ "" } , lookahead{ lookahead_ } , positive{ positive_ }{ -#line 5503 "reflect.h2" +#line 7202 "reflect.h2" } -#line 5505 "reflect.h2" +#line 7204 "reflect.h2" auto lookahead_lookbehind_token::generate_code(generation_context& ctx) const -> void{ auto inner_name {ctx.generate_func(inner)}; @@ -8512,7 +11017,7 @@ size_t i{0}; } } -#line 5516 "reflect.h2" +#line 7215 "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. @@ -8520,14 +11025,14 @@ size_t i{0}; return r; } -#line 5523 "reflect.h2" +#line 7222 "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 5531 "reflect.h2" +#line 7230 "reflect.h2" [[nodiscard]] auto named_class_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8553,7 +11058,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 5559 "reflect.h2" +#line 7258 "reflect.h2" [[nodiscard]] auto octal_token_parse(parse_context& ctx) -> token_ptr { if (!((ctx.current() == '\\' && ctx.peek() == 'o'))) {return nullptr; } @@ -8579,11 +11084,11 @@ size_t i{0}; return r; } -#line 5596 "reflect.h2" +#line 7295 "reflect.h2" range_token::range_token() : regex_token{ "" }{} -#line 5598 "reflect.h2" +#line 7297 "reflect.h2" [[nodiscard]] auto range_token::parse(parse_context& ctx) -> token_ptr { auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared)}; @@ -8657,7 +11162,7 @@ size_t i{0}; return nullptr; } -#line 5671 "reflect.h2" +#line 7370 "reflect.h2" auto range_token::parse_modifier(parse_context& ctx) & -> void { if (ctx.peek() == '?') { @@ -8670,7 +11175,7 @@ size_t i{0}; }} } -#line 5683 "reflect.h2" +#line 7382 "reflect.h2" [[nodiscard]] auto range_token::gen_mod_string() const& -> std::string { if (kind == range_flags::not_greedy) { @@ -8684,7 +11189,7 @@ size_t i{0}; }} } -#line 5696 "reflect.h2" +#line 7395 "reflect.h2" [[nodiscard]] auto range_token::gen_range_string() const& -> std::string { std::string r {""}; @@ -8704,7 +11209,7 @@ size_t i{0}; return r; } -#line 5715 "reflect.h2" +#line 7414 "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; @@ -8715,7 +11220,7 @@ size_t i{0}; return r; } -#line 5725 "reflect.h2" +#line 7424 "reflect.h2" auto range_token::generate_code(generation_context& ctx) const -> void { auto inner_name {ctx.generate_func(inner_token)}; @@ -8727,14 +11232,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 5736 "reflect.h2" +#line 7435 "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 5748 "reflect.h2" +#line 7447 "reflect.h2" [[nodiscard]] auto special_range_token::parse(parse_context& ctx) -> token_ptr { auto r {CPP2_UFCS_TEMPLATE(cpp2_new)(cpp2::shared)}; @@ -8758,7 +11263,7 @@ size_t i{0}; if (!(ctx.has_token())) {return ctx.error("'" + cpp2::to_string(ctx.current()) + "' without previous element."); } -#line 5772 "reflect.h2" +#line 7471 "reflect.h2" (*cpp2::impl::assert_not_null(r)).parse_modifier(ctx); (*cpp2::impl::assert_not_null(r)).inner_token = ctx.pop_token(); @@ -8768,7 +11273,7 @@ size_t i{0}; special_range_token::~special_range_token() noexcept{} -#line 5784 "reflect.h2" +#line 7483 "reflect.h2" [[nodiscard]] auto start_match_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8784,7 +11289,7 @@ size_t i{0}; } } -#line 5804 "reflect.h2" +#line 7503 "reflect.h2" [[nodiscard]] auto word_boundary_token_parse(parse_context& ctx) -> token_ptr { if (ctx.current() != '\\') {return nullptr; } @@ -8802,15 +11307,15 @@ size_t i{0}; }} } -#line 5840 "reflect.h2" +#line 7539 "reflect.h2" template regex_generator::regex_generator(cpp2::impl::in r, Error_out const& e) : regex{ r } , error_out{ e }{ -#line 5843 "reflect.h2" +#line 7542 "reflect.h2" } -#line 5845 "reflect.h2" +#line 7544 "reflect.h2" template [[nodiscard]] auto regex_generator::parse() & -> std::string { // Extract modifiers and adapt regex. @@ -8846,7 +11351,7 @@ size_t i{0}; return source; } -#line 5880 "reflect.h2" +#line 7579 "reflect.h2" template auto regex_generator::extract_modifiers() & -> void { if (regex.find_first_of("'/") == 0) { @@ -8862,7 +11367,7 @@ size_t i{0}; } } -#line 5896 "reflect.h2" +#line 7595 "reflect.h2" template [[nodiscard]] auto generate_regex(cpp2::impl::in regex, Err const& err) -> std::string { regex_generator parser {regex, err}; @@ -8871,7 +11376,7 @@ template [[nodiscard]] auto generate_regex(cpp2::impl::in void { auto has_default {false}; @@ -8926,7 +11431,7 @@ auto regex_gen(meta::type_declaration& t) -> void CPP2_UFCS(add_runtime_support_include)(t, "cpp2regex.h"); } -#line 5965 "reflect.h2" +#line 7664 "reflect.h2" [[nodiscard]] auto apply_metafunctions( declaration_node& n, type_declaration& rtype, @@ -9048,7 +11553,7 @@ auto regex_gen(meta::type_declaration& t) -> void return true; } -#line 6087 "reflect.h2" +#line 7786 "reflect.h2" } } diff --git a/source/reflect.h2 b/source/reflect.h2 index dcc3a1a4bc..7a752349a5 100644 --- a/source/reflect.h2 +++ b/source/reflect.h2 @@ -206,6 +206,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, o: reflection_base) -> bool = false; // Different types => false } @@ -549,6 +552,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 ); } @@ -2469,1178 +2473,2873 @@ 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) = -{ - if stmt.is_expression_statement() { - sample_traverser(stmt.as_expression_statement().get_expression(), indent); + if stmt.is_iteration_statement() { + pre_traverse(stmt.as_iteration_statement()); + } + + // 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) = +{ + 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); } - // Else we're at an actual postfix expression with ops - else { - sample_print("postfix expression", indent); + // 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 - stub +// + +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_primal_higher_order: std::string; + public code_fwd_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_primal_higher_order_: std::string = "", code_fwd_higher_order_: std::string = "") = { + name = name_; + n_args = n_args_; + is_member = is_member_; + + code_primal = code_primal_; + code_fwd = code_fwd_; + code_primal_higher_order = code_primal_higher_order_; + code_fwd_higher_order = code_fwd_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; + } + } + + 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: type = { + public name : std::string = ""; + public decl : std::string = ""; // TODO: Maybe use variant here. + public is_member: bool = false; + + operator=:(out this) = {} + + operator=:(out this, name_: std::string, decl_: std::string, is_member_: bool) = { + name = name_; + decl = decl_; + 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 = ()) = { + for std::ranges::views::reverse(declared_variables_stack) do (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_", + "sin(_a1_)", + "_ad1_.sin(_a1_)", + + ), + autodiff_special_func("cos", 1, /* is_member = */ false, + "cos(_a1_)", + "-sin(_a1_) * _ad1_", + "cos(_a1_)", + "_ad1_.cos(_a1_)", + ), + autodiff_special_func("exp", 1, /* is_member = */ false, + "exp(_a1_)", + "exp(_a1_) * _ad1_", + "exp(_a1_)", + "_ad1_.exp(_a1_)", + ), + autodiff_special_func("push_back", 1, /* is_member = */ true, + "_o_.push_back(_a1_);", + "_od_.push_back(_ad1_);") + ); + + public suffix: std::string = "_d"; + private order: int = 1; + + // Members depending on order + public ad_type: std::string = "double"; + + public declaration_map : std::map> = (); + public declaration_stack: std::vector = (); + + add_variable_declaration: (inout this, name: std::string, type: std::string, is_member: bool = false) = { + declaration_stack.back().declared_variables_stack.back().push_back(autodiff_declared_variable(name, type, is_member)); + } + + 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)); + } + + set_order : (inout this, new_order: int) = { + order = new_order; + + if 1 == order { + ad_type = "double"; + } + else { + ad_type = "cpp2::taylor"; + } + } + + is_taylor: (this) = order != 1; + + gen_temporary : (inout this) -> std::string = { + temporary_count += 1; + return "temp_(temporary_count)$"; + } + + get_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 += suffix; + } + } + + // Replace with AD type for the AD order. + return string_util::replace_all(type_d, "double", ad_type); + } + + lookup_declaration: (inout this, decl_name: std::string) -> (r : std::vector = ()) = { + for std::ranges::views::reverse(declaration_stack) do (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); + } + + for std::ranges::views::reverse(declaration_stack) do (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) = { + lookup : autodiff_special_func = (func_name, n_args, is_member); + + m = false; + code_primal = ""; + code_fwd = ""; + 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; + } + else { + code_primal = func.code_primal; + code_fwd = func.code_fwd; + } + 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; + for std::ranges::views::reverse(declaration_stack) do (inout 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_handler_base: type = { + public ctx: *autodiff_context; + + public diff : std::string = ""; + + operator=: (out this, ctx_: *autodiff_context) = { + ctx = ctx_; + } + + append: (inout this, in_ref o: autodiff_handler_base) = { + diff += o.diff; + } +} + +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 = ""; + + operator=: (out this, ctx_: *autodiff_context) = { + autodiff_handler_base = (ctx_); + } + + add_suffix_if_not_wildcard: (this, lhs: std::string) -> std::string = { + if "_" == lhs { + return lhs; + } + else { + return lhs + ctx*.suffix; + } + } + + gen_assignment: (inout this, lhs: std::string, lhs_d: std::string, rhs: std::string, rhs_d: std::string) = { + diff += "(lhs_d)$ = (rhs_d)$;\n"; + diff += "(lhs)$ = (rhs)$;\n"; + } + gen_assignment: (inout this, lhs: std::string, lhs_d: std::string) + = gen_assignment(lhs, lhs_d, primal_expr, fwd_expr); + gen_assignment: (inout this, lhs: std::string) + = gen_assignment(lhs, add_suffix_if_not_wildcard(lhs), primal_expr, fwd_expr); + + + gen_declaration: (inout this, lhs: std::string, lhs_d: std::string, rhs: std::string, rhs_d: std::string, type: std::string, type_d: std::string) = { + diff += "(lhs_d)$: (type_d)$ = (rhs_d)$;\n"; + diff += "(lhs)$ : (type)$ = (rhs)$;\n"; + } + gen_declaration: (inout this, lhs: std::string, lhs_d: std::string, rhs: std::string, rhs_d: std::string, type: std::string) + = gen_declaration(lhs, lhs_d, rhs, rhs_d, type, ctx*.get_ad_type(type)); + gen_declaration: (inout this, lhs: std::string, lhs_d: std::string, type: std::string) + = gen_declaration(lhs, lhs_d, primal_expr, fwd_expr, type, ctx*.get_ad_type(type)); + gen_declaration: (inout this, lhs: std::string, type: std::string) + = gen_declaration(lhs, lhs + ctx*.suffix, primal_expr, fwd_expr, type, ctx*.get_ad_type(type)); + + + + primal_fwd_name: @struct type = { + primal: std::string = ""; + fwd : std::string = ""; + } + + 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_name = { + if term.is_identifier() { + primal := term.to_string(); + fwd := primal + ctx*.suffix; + + decl := ctx*.lookup_variable_declaration(primal); + if decl.is_member { + fwd = "this(ctx*.suffix)$." + fwd; + } + return (primal, fwd); + } + 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", ""); + } + 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", ""); + } + + ad : autodiff_expression_handler = (ctx); + ad..pre_traverse(bin_expr.get_terms().front().get_term()); + t := ctx*.gen_temporary(); + ad.gen_declaration(t, "double"); // TODO: get type of expression + append(ad); + + r : primal_fwd_name = (t, t + ctx*.suffix); // TODO: Check why on return (t, t + ctx*.suffix) the primal is initialized empty. Probably because of the move(t) + _ = t; + return r; + } + else { + // Nothing special. A regular expression. + expr := term; + + 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_name = (t, t + ctx*.suffix); // TODO: Check why on return (t, t + ctx*.suffix) the primal is initialized empty. Probably because of the move(t) + _ = t; + return r; + } + } + + 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 = ""; + 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*.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*.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, function_name, args) { + return; + } + + if object.contains(".") { + postfix.error("AD: can not handle nested member function calls: (postfix.to_string())$"); + return; + } + + // All arguments have now been handled. Form the function call + ret_temp : std::string = ""; + if has_return { + ret_temp = ctx*.gen_temporary(); + diff += "(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 + diff += "(object)$."; + } + diff += "(function_name)$(ctx*.suffix)$("; + if !object.empty() { // Add this_d argument. + diff += "(object_d)$, "; + } + for args do (arg) { + diff += "(arg.primal)$, (arg.fwd)$,"; + } + diff += ");\n"; + + 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*.suffix; + + primal_expr = "(ret_temp)$.(ret_name)$"; + fwd_expr = "(ret_temp)$.(ret_name_d)$"; + } + + // 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, function_name: std::string, args: std::vector) -> bool = { + + r := ctx*.lookup_special_function_handling(function_name, 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; + + 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); + } + + (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); + } + + primal_expr = code_primal; + fwd_expr = code_fwd; + + 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; + fwd : std::string = ""; + primal: std::string = ""; + for terms do (term) { + if !first { + op := term.get_op().to_string(); + fwd += " (op)$ "; + primal += " (op)$ "; + } + + var := handle_expression_term(term.get_term()); + fwd += var.fwd; + primal += var.primal; + + first = false; + } + + primal_expr = primal; + fwd_expr = fwd; + } + + traverse: (override inout this, binexpr: meta::multiplicative_expression) = { + terms := binexpr.get_terms(); + + var := handle_expression_term(terms[0].get_term()); + arg_a := var.primal; + arg_a_d := var.fwd; + + i : int = 1; + while i < terms.ssize() next i += 1 { + var = handle_expression_term(terms[i].get_term()); + arg_b := var.primal; + arg_b_d := var.fwd; + + op := terms[i].get_op().to_string(); + + fwd : std::string = ""; + primal : std::string = ""; + + if "*" == op { + if ctx*.is_taylor() { + fwd = "(arg_a_d)$.mul((arg_b_d)$, (arg_a)$, (arg_b)$)"; + } + else { + fwd = "(arg_a)$ * (arg_b_d)$ + (arg_b)$ * (arg_a_d)$"; + } + primal = "(arg_a)$ * (arg_b)$"; + } + else if "/" == op { + if ctx*.is_taylor() { + fwd = "(arg_a_d)$.div((arg_b_d)$, (arg_a)$, (arg_b)$)"; + } + else { + fwd = "(arg_a_d)$ / (arg_b)$ - (arg_a)$ * (arg_b_d)$ / ((arg_b)$ * (arg_b)$)"; + } + primal = "(arg_a)$ / (arg_b)$"; + } + else { + binexpr.error( "unkown multiplicative operator '(op)$'"); + } + + + if i + 1 == terms.ssize() { + primal_expr = primal; + fwd_expr = fwd; + } + else { + // Temporary + t := ctx*.gen_temporary(); + t_d := t + ctx*.suffix; + gen_declaration(t, t_d, primal, fwd, "", ""); + + arg_a = t; + arg_a_d = t_d; + } + } + } + + 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*.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*.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); + + decl := ctx*.lookup_variable_declaration(primal_expr); + if decl.is_member { + fwd_expr = "this(ctx*.suffix)$." + fwd_expr; + } + } + else if primary.is_expression_list() { + if primary.as_expression_list().is_empty() { + primal_expr = "()"; + fwd_expr = "()"; + } + 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 = "()"; + } + 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; + + operator=: (out this, ctx_: *autodiff_context, mf_: meta::function_declaration) = { + autodiff_handler_base = (ctx_); + mf = mf_; + } + + 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(); + + ad_type : = ctx*.get_ad_type(type); + + prim_init: std::string = ""; + fwd_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; + + if type == "_" && ad.fwd_expr == "()" { + // Special handling for auto initialization from a literal. + fwd_init = " = " + ctx*.get_ad_type("double") + "()"; + } + } + diff += "(lhs)$(ctx*.suffix)$ : (ad_type)$(fwd_init)$;\n"; + diff += "(lhs)$ : (type)$(prim_init)$;\n"; + + ctx*.add_variable_declaration(lhs, type); + } + + + 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) = { + base::traverse(stmt); + } + + + traverse: (override inout this, stmt: meta::compound_statement) = { + // Brackets are handled by the + diff += "{\n"; + base::traverse(stmt); + diff += "}\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"; + } + } - 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); + traverse: (override inout this, stmt: meta::iteration_statement) = { + if stmt.is_while() { + // 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())$ "; } - else if term.is_expression_list() { - sample_traverser(term.get_expression_list(), indent+1); + + pre_traverse(stmt.get_do_while_body()); + } + else if stmt.is_do() { + // 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())$ "; } - else if term.is_expression() { - sample_traverser(term.get_expression(), indent+1); + 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(); + diff += "(copy (param_decl.name())$_d_iter := (range)$(ctx*.suffix)$.begin())\n"; + diff += "for (range)$ next ("; + if stmt.has_next() { + // TODO: Assumption is here that nothing is in the next expression + diff += "(stmt.get_next_expression().to_string())$, "; } + diff += "(param_decl.name())$_d_iter++"; + diff += ") do ((param_style)$ (param_decl.name())$: (param_decl.type())$) {\n"; + diff += "((param_style)$ (param_decl.name())$(ctx*.suffix)$: (param_decl.type())$ = (param_decl.name())$_d_iter*)"; + + ctx*.add_variable_declaration("(param_decl.name())$", "(param_decl.type())$"); // TODO: Handle loop/compound context variable declarations. + + pre_traverse(stmt.get_for_body()); + diff += "}\n"; } } -} -sample_traverser: (uid: meta::unqualified_id, indent: i32) = -{ - if uid.is_identifier() { - sample_print(uid.get_identifier(), indent); + 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()); + } } - else { - sample_print(uid.to_string(), indent+1); + + traverse : (override inout this, expr: meta::expression) = { + base::traverse(expr); } -} + traverse: (override inout this, binexpr: meta::assignment_expression) = { + h_lhs: autodiff_expression_handler = (ctx); + h_lhs.pre_traverse(binexpr.get_lhs_postfix_expression()); -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); - } -} + // 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()); + h.gen_assignment(h_lhs.primal_expr, h_lhs.fwd_expr); + append(h); + } -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::logical_or_expression) = { + binexpr.error( "AD: Logical 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::logical_and_expression) = { + binexpr.error( "AD: Logical and 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::bit_or_expression) = { + binexpr.error( "AD: Bit or expressions are not yet handled as standalone statements." ); } - else { - sample_print(tid.to_string(), indent); + + 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: (primary: meta::primary_expression, indent: i32) = -{ - if primary.is_identifier() { - sample_print(primary.as_identifier(), indent+1); + traverse: (override inout this, binexpr: meta::equality_expression) = { + binexpr.error( "AD: Equality or 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, binexpr: meta::relational_expression) = { + binexpr.error( "AD: Relational expressions are not yet handled as standalone statements." ); } - else if primary.is_literal() { - sample_print(primary.as_literal(), indent+1); + + traverse: (override inout this, binexpr: meta::compare_expression) = { + binexpr.error( "AD: Compare or expressions are not yet handled as standalone statements." ); } - else if primary.is_declaration() { - sample_traverser(primary.as_declaration(), indent+1); + + traverse: (override inout this, binexpr: meta::shift_expression) = { + binexpr.error( "AD: Shift or expressions are not yet handled as standalone statements." ); } - else { - sample_print(primary.to_string(), indent+1); + + traverse: (override inout this, binexpr: meta::additive_expression) = { + binexpr.error( "AD: Additive expressions are not yet handled as standalone statements." ); } -} + traverse: (override inout this, binexpr: meta::multiplicative_expression) = { + binexpr.error( "AD: Multiplicative expressions are not yet handled as standalone statements." ); + } -sample_traverser: (idexpr: meta::id_expression, indent: i32) = -{ - if idexpr.is_identifier() { - sample_print(idexpr.as_identifier(), 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 idexpr.is_qualified() { - sample_traverser(idexpr.as_qualified(), indent+1); + + traverse: (override inout this, prefix: meta::prefix_expression) = + { + prefix.error( "AD: Prefix expressions are not yet handled as standalone statements." ); } - else if idexpr.is_unqualified() { - sample_traverser(idexpr.as_unqualified(), 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(idexpr.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; -//----------------------------------------------------------------------- -// -// autodiff - stub -// - -autodiff_impl: type = { + base: type == simple_traverser; - private temporary_count : int = 0; + decl: meta::type_or_namespace_declaration; - public diff : std::string = ""; + is_type_context: bool = false; + diff_ad_type : std::string = ""; - gen_temporary : (inout this) -> std::string = { - temporary_count += 1; - return "temp_(temporary_count)$"; + operator=: (out this, ctx_: *autodiff_context, decl_: meta::type_or_namespace_declaration) = { + autodiff_handler_base = (ctx_); + decl = decl_; } - 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; - } + traverse: (override inout this, decl: meta::declaration) = { + base::traverse(decl); } - 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 += ";"; - return; - } + traverse: (override inout this, f: meta::function_declaration) = { + ctx*.enter_function(); - // 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 += term.get_term().to_string() + "___"; - } - diff += ";"; + diff = " (f.name())$(ctx*.suffix)$: ("; - return; - } + // 1. Generate the modified signature + // a) Parameters - // 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() + "___"; - } - diff += term.get_term().to_string() + "___"; + for f.get_parameters() do (param) { + name : std::string = param.get_declaration().name(); + + if "this" == name{ + ad_type := ctx*.get_ad_type(std::string(decl.name())); + diff += "(name)$, "; + diff += "(name)$(ctx*.suffix)$: (ad_type)$, "; } - diff += ";"; + else { + type := param.get_declaration().type(); + diff += "(name)$ : (type)$, "; + diff += "(name)$(ctx*.suffix)$ : (ctx*.get_ad_type(type))$, "; - return; + ctx*.add_variable_declaration(name, type); + } } - // 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 += ";"; + diff += ") -> ("; - return; - } + // b) Returns - // 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() + "___"; + 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 += "r, r(ctx*.suffix)$, "; + } + else { + diff += "r: (f.get_unnamed_return_type())$ = (), r(ctx*.suffix)$: (ctx*.get_ad_type(f.get_unnamed_return_type()))$ = (), "; } - diff += ";"; - - return; } + else { + for f.get_returns() do (param) { + name := param.get_declaration().name(); + type := param.get_declaration().type(); + diff += "(name)$ : (param.get_declaration().type())$ = 0.0, "; + diff += "(name)$(ctx*.suffix)$ : (ctx*.get_ad_type(type))$ = 0.0, "; - // 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() + "___"; + ctx*.add_variable_declaration("(name)$", "(type)$"); } - diff += ";"; - - return; } - // 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() + "___"; - } - diff += term.get_term().to_string() + "___"; - } - diff += ";"; + diff += ") = {"; + + // Generate the body + if !f.has_compound_body() { + f.error( "temporary alpha limitation: a differentiable function must have a {}-enclosed body" ); 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() + "___"; - } - diff += term.get_term().to_string() + "___"; - } - diff += ";"; - return; - } + ad_impl : autodiff_stmt_handler = (ctx*&, f); - // 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() + "___"; - } - diff += term.get_term().to_string() + "___"; - } - diff += ";"; - return; + for f.get_compound_body().get_statements() do (stmt) + { + ad_impl..pre_traverse(stmt); } + diff += ad_impl.diff; - // 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)$ "; - } + diff += "}"; - var := handle_expression_term(mf, term.get_term()); - fwd += "(var)$_d"; - primal += "(var)$"; + ctx*.leave_function(); - first = false; - } + decl.add_member( diff ); + diff = ""; - fwd += ";"; - primal += ";"; + ctx*.add_as_differentiated(f); + } - diff += fwd + primal; - return; - } + traverse: (override inout this, o: meta::object_declaration) = { + ad_name : std::string = "(o.name())$(ctx*.suffix)$"; + ad_type : std::string = ctx*.get_ad_type(o.type()); + ad_init : std::string = ""; - // Handle binary * / % - if additive_terms.ssize() != 1 { - mf.error( "ICE: there should be exactly one additive term here" ); - } - multiplicative_terms := additive_terms.front().get_term().get_terms(); + if o.has_initializer() { + ad: autodiff_expression_handler = (ctx); + ad.pre_traverse(o.get_initializer()); - // 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"; - } - } + assert(ad.diff.empty()); + ad_init = " = " +ad.fwd_expr; } - if multiplicative_terms.ssize() > 1 - { - arg_a := handle_expression_term(mf, multiplicative_terms[0].get_term()); - - i : int = 1; - while i < multiplicative_terms.ssize() next i += 1 { - arg_b := handle_expression_term(mf, multiplicative_terms[i].get_term()); + diff = "(ad_name)$ : (ad_type)$(ad_init)$;"; - op := multiplicative_terms[i].get_op().to_string(); + if is_type_context { - fwd : std::string = ""; - primal : std::string = ""; + diff_ad_type += "public (diff)$\n"; + } + else { + decl.add_member(diff); + } + diff = ""; - 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)$'"); - } + ctx*.add_variable_declaration("(o.name())$", "(o.type())$", true); + } - 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)$;"; + traverse: (override inout this, t: meta::type_declaration) = { + ctx*.push_stack(t); + ad: autodiff_declaration_handler = (ctx, t); + ad.is_type_context = true; - arg_a = t; - } - } + for t.get_members() + do (m) + { + ad.pre_traverse(m); } - } + ctx*.pop_stack(); - 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; - } + if !ad.diff_ad_type.empty() { + diff = "(t.name())$(ctx*.suffix)$ : type = {\n"; + diff += "(ad.diff_ad_type)$"; + diff += "}"; - assignment := expr.as_assignment_expression(); + decl.add_member(diff); + diff = ""; + } + } - // 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" ); - } - // Now we handle sequences of binary "expr1 @ expr2 @ ..." where each - // @ is one of a list of operators at the same grammar precedence + traverse: (override inout this, t: meta::parameter_declaration) = { + t.error("AD: Do not know how to handle parameter_declaration: (t.to_string())$"); + } + - handle_expression_terms(mf, lhs.to_string(), assignment_terms[1].get_term().get_terms()); - } + traverse: (override inout this, stmt: meta::statement) = { + stmt.error("AD: Do not know how to handle statement in declaration context: (stmt.to_string())$"); } } + 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: ("; - - // 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())$, "; - } + suffix_token : std::string_view == "suffix="; + order_token : std::string_view == "order="; - diff += ") -> ("; + args := t.get_arguments(); - // b) Returns + suffix : std::string = "_d"; + order : int = 1; + for args do (arg_str) { + if arg_str.starts_with("\"") && arg_str.ends_with("\"") { + arg := arg_str.substr(1, arg_str.ssize() - 2); - 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, "; + if arg.starts_with(suffix_token) { + suffix = arg.substr(suffix_token.size()); + continue; + } + 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; + } } - diff += ") = {"; - - // Generate the body + t.error("AD: Unknown argument: (arg_str)$"); + return; + } - if !mf.has_compound_body() { - mf.error( "temporary alpha limitation: a differentiable function must have a {}-enclosed body" ); - return; - } + ad_ctx: autodiff_context = (); + ad_ctx.suffix = suffix; + ad_ctx.set_order(order); - ad_impl : autodiff_impl = (); + 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" ); } + + ad_ctx.finish(); + + _ = ad_ctx; }