diff --git a/xo-expression2/include/xo/expression2/ApplyExpr.hpp b/xo-expression2/include/xo/expression2/ApplyExpr.hpp new file mode 100644 index 00000000..fd9c0764 --- /dev/null +++ b/xo-expression2/include/xo/expression2/ApplyExpr.hpp @@ -0,0 +1,13 @@ +/** @file ApplyExpr.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DApplyExpr.hpp" +#include "detail/IExpression_DApplyExpr.hpp" +//#include "detail/IGCObject_DApplyExpr.hpp" +#include "detail/IPrintable_DApplyExpr.hpp" + +/* end ApplyExpr.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/DPrimitive.hpp b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp index 90fdba50..abec46cc 100644 --- a/xo-procedure2/include/xo/procedure2/DPrimitive.hpp +++ b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp @@ -76,9 +76,11 @@ namespace xo { TypeDescr fn_td() const noexcept { return fn_td_; } - bool is_nary() const noexcept { return false; } + std::string_view name() const noexcept { return name_; } static constexpr std::int32_t n_args() noexcept { return Traits::n_args; } + bool is_nary() const noexcept { return false; } + obj apply_nocheck(obj rcx, const DArray * args) { return _apply_nocheck(rcx, args, std::make_index_sequence{}); diff --git a/xo-procedure2/include/xo/procedure2/Primitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/Primitive_gco_2_gco_gco.hpp new file mode 100644 index 00000000..9e6814f4 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/Primitive_gco_2_gco_gco.hpp @@ -0,0 +1,11 @@ +/** @file Primitive_gco_2_gco_gco.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DPrimitive_gco_2_gco_gco.hpp" +#include "detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp" +#include "detail/IGCObject_DPrimitive_gco_2_gco_gco.hpp" +#include "detail/IPrintable_DPrimitive_gco_2_gco_gco.hpp" + +/* end Primitive_gco_2_gco_gco.hpp */ diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index 9fd6e7b1..102384e2 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -1038,21 +1038,27 @@ namespace xo { obj lhs = FacetRegistry::instance().variant(lhs_); - obj rhs; - if (rhs_) - rhs = FacetRegistry::instance().variant(rhs_); - - (void)lhs; - - return ppii.pps()->pretty_struct - (ppii, - "DProgressSsm", - refrtag("lhs", lhs), - refrtag("op", op_type_), - cond(rhs, refrtag("rhs", rhs), "nullptr"), - refrtag("expect", this->get_expect_str()) - ); + obj rhs + = FacetRegistry::instance().try_variant(rhs_); + if (rhs) { + return ppii.pps()->pretty_struct + (ppii, + "DProgressSsm", + refrtag("lhs", lhs), + refrtag("op", op_type_), + refrtag("rhs", rhs), + refrtag("expect", this->get_expect_str()) + ); + } else { + return ppii.pps()->pretty_struct + (ppii, + "DProgressSsm", + refrtag("lhs", lhs), + refrtag("op", op_type_), + refrtag("expect", this->get_expect_str()) + ); + } } obj @@ -1065,7 +1071,7 @@ namespace xo { constexpr const char * c_self_name = "DProgressSsm::assemble_expr"; - if ((op_type_ != optype::invalid) && rhs_) { + if ((op_type_ != optype::invalid) && !rhs_) { std::string errmsg_string = tostr("expected expression on rhs of operator op", xtag("lhs", lhs_), xtag("op", op_type_)); diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index 9ccad56b..2fb10ea5 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -26,11 +28,13 @@ namespace xo { using xo::scm::AExpression; using xo::scm::DDefineExpr; + using xo::scm::DApplyExpr; using xo::scm::DConstant; //using xo::scm::ParserResult; using xo::scm::Token; using xo::mm::AGCObject; + using xo::scm::DPrimitive_gco_2_gco_gco; using xo::scm::DString; using xo::scm::DFloat; using xo::scm::DInteger; @@ -407,6 +411,110 @@ namespace xo { //REQUIRE(result.error_description()); } + TEST_CASE("SchematikaParser-interactive-arith", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ArenaConfig config; + config.name_ = "test-arena"; + config.size_ = 16 * 1024; + + DArena expr_arena = DArena::map(config); + obj expr_alloc = with_facet::mkobj(&expr_arena); + + SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * 3.14159265 * 0.5 ; + * + **/ + + { + auto & result = parser.on_token(Token::f64_token("3.14159265")); + + log && log("after float(3.14159265) token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::star_token()); + + log && log("after star token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::f64_token("0.5")); + + log && log("after float(0.5) token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::semicolon_token()); + + log && log("after semicolon token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == false); + REQUIRE(!result.is_error()); + REQUIRE(result.is_expression()); + REQUIRE(result.result_expr()); + + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + + REQUIRE(expr->n_args() == 2); + + auto fn = obj::from(expr->fn()); + REQUIRE(fn); + + auto pm = obj::from(fn->value()); + REQUIRE(pm); + REQUIRE(pm->name() == "_mul"); + + auto lhs = obj::from(expr->arg(0)); + REQUIRE(lhs); + + auto lhs_f64 = obj::from(lhs->value()); + REQUIRE(lhs_f64); + REQUIRE(lhs_f64->value() == 3.14159265); + + auto rhs = obj::from(expr->arg(1)); + REQUIRE(rhs); + + auto rhs_f64 = obj::from(rhs->value()); + REQUIRE(rhs_f64); + REQUIRE(rhs_f64->value() == 0.5); + } + + //REQUIRE(result.is_error()); + //// illegal input on token + //REQUIRE(result.error_description()); + } + TEST_CASE("SchematikaParser-interactive-lambda", "[reader2][SchematikaParser]") { constexpr bool c_debug_flag = true;