From 788363dd4c7aae01b1bf2c569174bde034bcaf6f Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 19 Feb 2026 09:03:02 -0800 Subject: [PATCH] xo-interpreter2 stack: streamline op== impl + utests --- .../interpreter2/VirtualSchematikaMachine.cpp | 8 ++ .../utest/VirtualSchematikaMachine.test.cpp | 49 ++++++++++- .../include/xo/numeric/FloatIntegerOps.hpp | 6 ++ xo-numeric/include/xo/numeric/FloatOps.hpp | 3 + xo-numeric/include/xo/numeric/IntegerOps.hpp | 3 + .../include/xo/numeric/NumericDispatch.hpp | 11 ++- xo-numeric/include/xo/numeric/NumericOps.hpp | 15 +++- .../include/xo/numeric/NumericPrimitives.hpp | 3 + xo-numeric/src/numeric/FloatIntegerOps.cpp | 17 ++++ xo-numeric/src/numeric/FloatOps.cpp | 8 ++ xo-numeric/src/numeric/IntegerOps.cpp | 9 ++ xo-numeric/src/numeric/NumericDispatch.cpp | 16 ++++ xo-numeric/src/numeric/NumericPrimitives.cpp | 4 + .../src/numeric/numeric_register_facets.cpp | 12 ++- xo-object2/src/object2/DBoolean.cpp | 2 +- xo-object2/src/object2/DRuntimeError.cpp | 9 +- .../include/xo/procedure2/init_primitives.hpp | 2 +- .../src/procedure2/init_primitives.cpp | 4 +- xo-reader2/src/reader2/DProgressSsm.cpp | 58 ++++++++++++- xo-reader2/utest/SchematikaParser.test.cpp | 84 ++++++++++++++++++- 20 files changed, 302 insertions(+), 21 deletions(-) diff --git a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp index 9104fa2f..40ccb834 100644 --- a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp +++ b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp @@ -185,6 +185,14 @@ namespace xo { if (expr_pr) log && log(xtag("expr", expr_pr)); + if (value_.value()) { + auto value_pr = const_cast *>(value_.value())->to_facet(); + if (value_pr) + log && log(xtag("value", value_pr)); + } else { + log && log("value not present or tk error"); + } + auto stack_pr = stack_.to_facet(); if (stack_pr) log && log(xtag("stack", stack_pr)); diff --git a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp index 75726b72..a42746ae 100644 --- a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp +++ b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp @@ -490,7 +490,7 @@ namespace xo { log && vsm_fixture.log_memory_layout(&log); } - TEST_CASE("VirtualSchematikaMachine-fact0", "[interpreter2][VSM]") + TEST_CASE("VirtualSchematikaMachine-if2", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); @@ -504,6 +504,53 @@ namespace xo { vsm.begin_interactive_session(); + span_type input = span_type::from_cstr("def n = 4; if (n == 4) then n * 3 else n * 5;"); + + for (int i_expr = 0; i_expr < 2; ++i_expr) { + log && log(xtag("input", input)); + + VsmResultExt res + = vsm.read_eval_print(input, eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq()), + xtag("res.type", TypeRegistry::id2name(res.value()->_typeseq()))); + + if (i_expr == 0) { + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE(strcmp(x->chars(), "n") == 0); + input = res.remaining_; + } else if (i_expr == 1) { + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE(x->value() == 12); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + input = res.remaining_; + } + } + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-fact0", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = true; + + vsm.begin_interactive_session(); + span_type input = span_type::from_cstr("def fact = lambda (n) { if (n == 0) then 1 else n * fact(n - 1) }; fact(4);"); for (int i_expr = 0; i_expr < 2; ++i_expr) { diff --git a/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp index 9d21540f..5cf301ad 100644 --- a/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp +++ b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp @@ -27,6 +27,9 @@ namespace xo { DFloat * x, DInteger * y); static obj subtract(obj rcx, DFloat * x, DInteger * y); + + static obj cmp_equal(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -42,6 +45,9 @@ namespace xo { DInteger * x, DFloat * y); static obj subtract(obj rcx, DInteger * x, DFloat * y); + + static obj cmp_equal(obj rcx, + DInteger * x, DFloat * y); }; } diff --git a/xo-numeric/include/xo/numeric/FloatOps.hpp b/xo-numeric/include/xo/numeric/FloatOps.hpp index 75ffb5e4..5f7d06be 100644 --- a/xo-numeric/include/xo/numeric/FloatOps.hpp +++ b/xo-numeric/include/xo/numeric/FloatOps.hpp @@ -26,6 +26,9 @@ namespace xo { DFloat * x, DFloat * y); static obj subtract(obj rcx, DFloat * x, DFloat * y); + + static obj cmp_equal(obj rcx, + DFloat * x, DFloat * y); }; } diff --git a/xo-numeric/include/xo/numeric/IntegerOps.hpp b/xo-numeric/include/xo/numeric/IntegerOps.hpp index d839ad36..001a915f 100644 --- a/xo-numeric/include/xo/numeric/IntegerOps.hpp +++ b/xo-numeric/include/xo/numeric/IntegerOps.hpp @@ -29,6 +29,9 @@ namespace xo { static obj subtract(obj rcx, DInteger * x, DInteger * y); + static obj cmp_equal(obj rcx, + DInteger * x, DInteger * y); + }; } diff --git a/xo-numeric/include/xo/numeric/NumericDispatch.hpp b/xo-numeric/include/xo/numeric/NumericDispatch.hpp index 0f7a4ffd..58d06565 100644 --- a/xo-numeric/include/xo/numeric/NumericDispatch.hpp +++ b/xo-numeric/include/xo/numeric/NumericDispatch.hpp @@ -82,6 +82,11 @@ namespace xo { obj x, obj y); + /** compare two numeric values for equality **/ + static obj cmp_equal(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -94,7 +99,8 @@ namespace xo { void register_impl(typename NumericOps::BinaryOp_Impl mul_fn, typename NumericOps::BinaryOp_Impl div_fn, typename NumericOps::BinaryOp_Impl add_fn, - typename NumericOps::BinaryOp_Impl sub_fn) { + typename NumericOps::BinaryOp_Impl sub_fn, + typename NumericOps::BinaryOp_Impl cmpeq_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); @@ -104,7 +110,8 @@ namespace xo { = NumericOps::make(mul_fn, div_fn, add_fn, - sub_fn); + sub_fn, + cmpeq_fn); } private: diff --git a/xo-numeric/include/xo/numeric/NumericOps.hpp b/xo-numeric/include/xo/numeric/NumericOps.hpp index bc8630a6..f85b20f4 100644 --- a/xo-numeric/include/xo/numeric/NumericOps.hpp +++ b/xo-numeric/include/xo/numeric/NumericOps.hpp @@ -25,13 +25,18 @@ namespace xo { explicit AnonymizedNumericOps(BinaryOp multiply, BinaryOp divide, BinaryOp add, - BinaryOp subtract) - : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract} {} + BinaryOp subtract, + BinaryOp cmpeq) + : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, + cmpeq_{cmpeq} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; BinaryOp add_ = nullptr; BinaryOp subtract_ = nullptr; + + /** compare numerics for equality **/ + BinaryOp cmpeq_ = nullptr; }; template @@ -46,11 +51,13 @@ namespace xo { static AnonymizedNumericOps make(BinaryOp_Impl multiply, BinaryOp_Impl divide, BinaryOp_Impl add, - BinaryOp_Impl subtract) { + BinaryOp_Impl subtract, + BinaryOp_Impl cmpeq) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), reinterpret_cast(add), - reinterpret_cast(subtract)); + reinterpret_cast(subtract), + reinterpret_cast(cmpeq)); } }; diff --git a/xo-numeric/include/xo/numeric/NumericPrimitives.hpp b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp index f5ce374e..8f9c40db 100644 --- a/xo-numeric/include/xo/numeric/NumericPrimitives.hpp +++ b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp @@ -22,6 +22,9 @@ namespace xo { static DPrimitive_gco_2_gco_gco s_add_gco_gco_pm; /** polymorphic (in both arguments) subtract **/ static DPrimitive_gco_2_gco_gco s_sub_gco_gco_pm; + + /** polymorphic (in both arguments) compare (==) **/ + static DPrimitive_gco_2_gco_gco s_cmpeq_gco_gco_pm; }; } } diff --git a/xo-numeric/src/numeric/FloatIntegerOps.cpp b/xo-numeric/src/numeric/FloatIntegerOps.cpp index 5b15d5bb..476a6745 100644 --- a/xo-numeric/src/numeric/FloatIntegerOps.cpp +++ b/xo-numeric/src/numeric/FloatIntegerOps.cpp @@ -5,6 +5,7 @@ #include "FloatIntegerOps.hpp" #include "float/INumeric_DFloat.hpp" +#include namespace xo { using xo::mm::AGCObject; @@ -41,6 +42,14 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() - y->value()); } + obj + FloatIntegerOps::cmp_equal(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() == DFloat::value_type(y->value())); + } + // ----- Integer op Float ----- obj @@ -71,6 +80,14 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() - y->value()); } + obj + IntegerFloatOps::cmp_equal(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), + DFloat::value_type(x->value() == y->value())); + } + } } diff --git a/xo-numeric/src/numeric/FloatOps.cpp b/xo-numeric/src/numeric/FloatOps.cpp index 8821e48e..d0aa57aa 100644 --- a/xo-numeric/src/numeric/FloatOps.cpp +++ b/xo-numeric/src/numeric/FloatOps.cpp @@ -5,6 +5,7 @@ #include "FloatOps.hpp" #include "float/INumeric_DFloat.hpp" +#include namespace xo { using xo::mm::AGCObject; @@ -39,6 +40,13 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() - y->value()); } + obj + FloatOps::cmp_equal(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), x->value() == y->value()); + } + } } diff --git a/xo-numeric/src/numeric/IntegerOps.cpp b/xo-numeric/src/numeric/IntegerOps.cpp index 0f435b74..062cbeef 100644 --- a/xo-numeric/src/numeric/IntegerOps.cpp +++ b/xo-numeric/src/numeric/IntegerOps.cpp @@ -5,8 +5,10 @@ #include "IntegerOps.hpp" #include "integer/INumeric_DInteger.hpp" +#include namespace xo { + using xo::scm::DBoolean; using xo::mm::AGCObject; namespace scm { @@ -39,6 +41,13 @@ namespace xo { return DInteger::box(rcx.allocator(), x->value() - y->value()); } + obj + IntegerOps::cmp_equal(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() == y->value()); + } + } } diff --git a/xo-numeric/src/numeric/NumericDispatch.cpp b/xo-numeric/src/numeric/NumericDispatch.cpp index ded8c420..935d92eb 100644 --- a/xo-numeric/src/numeric/NumericDispatch.cpp +++ b/xo-numeric/src/numeric/NumericDispatch.cpp @@ -81,6 +81,22 @@ namespace xo { return (*target_fn)(rcx, x.data(), y.data()); } + obj + NumericDispatch::cmp_equal(obj rcx, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].cmpeq_; + + if (!target_fn) + assert(false); + + return (*target_fn)(rcx, x.data(), y.data()); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-numeric/src/numeric/NumericPrimitives.cpp b/xo-numeric/src/numeric/NumericPrimitives.cpp index ebbcb30b..28031fac 100644 --- a/xo-numeric/src/numeric/NumericPrimitives.cpp +++ b/xo-numeric/src/numeric/NumericPrimitives.cpp @@ -27,6 +27,10 @@ namespace xo { NumericPrimitives::s_sub_gco_gco_pm("_sub", &NumericDispatch::subtract); + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_cmpeq_gco_gco_pm("_cmpeq", + &NumericDispatch::cmp_equal); + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-numeric/src/numeric/numeric_register_facets.cpp b/xo-numeric/src/numeric/numeric_register_facets.cpp index 20e2093d..9cc6e1f9 100644 --- a/xo-numeric/src/numeric/numeric_register_facets.cpp +++ b/xo-numeric/src/numeric/numeric_register_facets.cpp @@ -38,25 +38,29 @@ namespace xo { (&FloatOps::multiply, &FloatOps::divide, &FloatOps::add, - &FloatOps::subtract); + &FloatOps::subtract, + &FloatOps::cmp_equal); NumericDispatch::instance().register_impl (&FloatIntegerOps::multiply, &FloatIntegerOps::divide, &FloatIntegerOps::add, - &FloatIntegerOps::subtract); + &FloatIntegerOps::subtract, + &FloatIntegerOps::cmp_equal); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, &IntegerFloatOps::divide, &IntegerFloatOps::add, - &IntegerFloatOps::subtract); + &IntegerFloatOps::subtract, + &IntegerFloatOps::cmp_equal); NumericDispatch::instance().register_impl (&IntegerOps::multiply, &IntegerOps::divide, &IntegerOps::add, - &IntegerOps::subtract); + &IntegerOps::subtract, + &IntegerOps::cmp_equal); log && log(xtag("ANumeric.tseq", typeseq::id())); diff --git a/xo-object2/src/object2/DBoolean.cpp b/xo-object2/src/object2/DBoolean.cpp index a926b0ec..ff5fa38a 100644 --- a/xo-object2/src/object2/DBoolean.cpp +++ b/xo-object2/src/object2/DBoolean.cpp @@ -24,7 +24,7 @@ namespace xo { bool DBoolean::pretty(const ppindentinfo & ppii) const { - return ppdetail_atomic::print_pretty + return ppdetail_atomic::print_pretty (ppii, (value_ ? "true" : "false")); } diff --git a/xo-object2/src/object2/DRuntimeError.cpp b/xo-object2/src/object2/DRuntimeError.cpp index 2b9fa62f..b683716e 100644 --- a/xo-object2/src/object2/DRuntimeError.cpp +++ b/xo-object2/src/object2/DRuntimeError.cpp @@ -6,6 +6,7 @@ #include "RuntimeError.hpp" namespace xo { + using xo::print::APrintable; using xo::mm::AGCObject; using xo::facet::typeseq; @@ -89,12 +90,14 @@ namespace xo { bool DRuntimeError::pretty(const ppindentinfo & ppii) const { - return ppii.pps()->pretty_struct(ppii, - "DRuntimeError"); + return ppii.pps()->pretty_struct + (ppii, + "DRuntimeError", + refrtag("src", obj(src_function_)), + refrtag("err", obj(error_descr_))); } } /*namespace scm*/ } /*namespace xo*/ /* end DRuntimeError.cpp */ - diff --git a/xo-procedure2/include/xo/procedure2/init_primitives.hpp b/xo-procedure2/include/xo/procedure2/init_primitives.hpp index 411b3d3e..14f5fdc8 100644 --- a/xo-procedure2/include/xo/procedure2/init_primitives.hpp +++ b/xo-procedure2/include/xo/procedure2/init_primitives.hpp @@ -29,13 +29,13 @@ namespace xo { * so we can dispatch on vector, matrix, function types **/ static DPrimitive_gco_2_gco_gco s_sub_gco_gco_pm; -#endif /** polymorphic equality comparison * * TODO: this will want to move to x-numeric/ **/ static DPrimitive_gco_2_gco_gco s_equal_gco_gco_pm; +#endif #ifdef NOT_YET static Primitive_f64_1_f64 s_neg_f64_pm; diff --git a/xo-procedure2/src/procedure2/init_primitives.cpp b/xo-procedure2/src/procedure2/init_primitives.cpp index c3cc5176..1fd3950c 100644 --- a/xo-procedure2/src/procedure2/init_primitives.cpp +++ b/xo-procedure2/src/procedure2/init_primitives.cpp @@ -159,7 +159,6 @@ namespace xo { xtag("y.tseq", y_tseq))); return obj(); } -#endif obj equal_gco_gco(obj rcx, @@ -219,6 +218,7 @@ namespace xo { xtag("y.tseq", y_tseq))); return obj(); } +#endif #ifdef NOT_YET double @@ -263,10 +263,10 @@ namespace xo { DPrimitive_gco_2_gco_gco Primitives::s_sub_gco_gco_pm("_sub", &sub_gco_gco); -#endif DPrimitive_gco_2_gco_gco Primitives::s_equal_gco_gco_pm("_equal", &equal_gco_gco); +#endif #ifdef NOT_YET Primitive_f64_1_f64 diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index ad3a0297..46321b0a 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -43,6 +43,7 @@ namespace xo { using xo::scm::Variable; using xo::scm::Apply; #endif + using xo::mm::AAllocator; using xo::mm::AGCObject; using xo::print::APrintable; using xo::facet::FacetRegistry; @@ -1185,6 +1186,45 @@ namespace xo { namespace { // make_builtin_apply_pm2 + + // helper function for making apply expression that invokes + // a binary primitive. Use for numeric operators: + // {*, /, +, -, ==} + // + obj + assemble_numeric_expr_aux(obj expr_alloc, + const TypeRef::prefix_type & prefix, + DPrimitive_gco_2_gco_gco * p_gco_pm, + obj lhs, + obj rhs) + { + auto pm_obj = with_facet::mkobj(p_gco_pm); + auto fn_expr = DConstant::make(expr_alloc, pm_obj); + + /* note: + * 1. don't assume we know lhs_ / rhs_ value types yet. + * perhaps have expression like + * f(..) * g(..) + * where f is the function that contains current ssm. + * + * 2. consequence: we need representation for + * polymorphic multiply on unknown numeric arguments. + * + * 3. TypeRef::dwim(..) is a placeholder. + * Plan to later provide abstract interpreter + * (ie compiler pass :) to drive type inference/unification + * + * 4. Alternatively could supply type-annotation syntax + * so human can assist inference; context here is we want + * to automate the boring stuff + */ + + TypeRef tref = TypeRef::dwim(prefix, nullptr); + + return DApplyExpr::make2(expr_alloc, + tref, fn_expr, lhs, rhs); + + } } obj @@ -1223,9 +1263,16 @@ namespace xo { break; case optype::op_equal: + return assemble_numeric_expr_aux + (p_psm->expr_alloc(), + TypeRef::prefix_type::from_chars("_cmpeq_gco"), + &NumericPrimitives::s_cmpeq_gco_gco_pm, + lhs_, rhs_); + +#ifdef OBSOLETE { auto pm_obj = (with_facet::mkobj - (&Primitives::s_equal_gco_gco_pm)); + (&NumericPrimitives::s_cmpeq_gco_gco_pm)); auto fn_expr = (DConstant::make (p_psm->expr_alloc(), pm_obj)); @@ -1240,6 +1287,7 @@ namespace xo { fn_expr, lhs_, rhs_); } break; +#endif case optype::op_not_equal: case optype::op_less: @@ -1250,6 +1298,13 @@ namespace xo { break; case optype::op_multiply: + return assemble_numeric_expr_aux + (p_psm->expr_alloc(), + TypeRef::prefix_type::from_chars("_mul_gco"), + &NumericPrimitives::s_mul_gco_gco_pm, + lhs_, rhs_); + +#ifdef OBSOLETE { auto pm_obj = (with_facet::mkobj (&NumericPrimitives::s_mul_gco_gco_pm)); @@ -1281,6 +1336,7 @@ namespace xo { return DApplyExpr::make2(p_psm->expr_alloc(), tref, fn_expr, lhs_, rhs_); } +#endif break; case optype::op_divide: diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index b6934f18..fa108af3 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ namespace xo { using xo::scm::AExpression; using xo::scm::DDefineExpr; + using xo::scm::DIfElseExpr; using xo::scm::DApplyExpr; using xo::scm::DVarRef; using xo::scm::DConstant; @@ -680,7 +682,7 @@ namespace xo { auto pm = obj::from(fn->value()); REQUIRE(pm); - REQUIRE(pm->name() == "_equal"); + REQUIRE(pm->name() == "_cmpeq"); auto lhs = obj::from(expr->arg(0)); REQUIRE(lhs); @@ -700,6 +702,84 @@ namespace xo { log && fixture.log_memory_layout(&log); } + TEST_CASE("SchematikaParser-interactive-if1", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), + xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + { + /** Walkthrough parsing input equivalent to: + * + * def n = 4 ; + * ^ ^ ^ ^ ^ + * 0 1 2 3 4 + **/ + + std::vector tk_v{ + /* [0] */ Token::def_token(), + /* [1] */ Token::symbol_token("n"), + /* [2] */ Token::singleassign_token(), + /* [3] */ Token::i64_token("4"), + /* [4] */ Token::semicolon_token() + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + } + + { + const auto & result = parser.result(); + + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + } + + { + parser.reset_result(); + + /** Walkthrough parsing input equivalent to: + * + * if (n == 4) then 1 else n * 5 ; + * ^ ^^ ^ ^^ ^ ^ ^ ^ ^ ^ ^ + * 0 1| 3 4| 6 7 8 9 a b c + * 2 5 + **/ + + std::vector tk_v{ + /* [0] */ Token::if_token(), + /* [1] */ Token::leftparen_token(), + /* [2] */ Token::symbol_token("n"), + /* [3] */ Token::cmpeq_token(), + /* [4] */ Token::i64_token("4"), + /* [5] */ Token::rightparen_token(), + /* [6] */ Token::then_token(), + /* [7] */ Token::i64_token("1"), + /* [8] */ Token::else_token(), + /* [9] */ Token::symbol_token("n"), + /* [a] */ Token::star_token(), + /* [b] */ Token::i64_token("5"), + /* [c] */ Token::semicolon_token() + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + } + + const auto & result = parser.result(); + { + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + } + + log && fixture.log_memory_layout(&log); + } + TEST_CASE("SchematikaParser-interactive-lambda", "[reader2][SchematikaParser]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); @@ -743,7 +823,7 @@ namespace xo { log && fixture.log_memory_layout(&log); } - TEST_CASE("SchematikaParser-interactive-if", "[reader2][SchematikaParser]") + TEST_CASE("SchematikaParser-interactive-if2", "[reader2][SchematikaParser]") { const auto & testname = Catch::getResultCapture().getCurrentTestName();