From 911818e9572b8da4757e2fced63cd7636cd2c0d0 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 18 Feb 2026 21:47:02 -0800 Subject: [PATCH] xo-reader2 stack: + xo-numeric + setup multi dispatch for *,/ --- cmake/xo_reader2Config.cmake.in | 1 + src/reader2/CMakeLists.txt | 1 + src/reader2/DProgressSsm.cpp | 49 +++++++++++++++++++++----- src/reader2/init_reader2.cpp | 2 ++ utest/SchematikaParser.test.cpp | 61 +++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 8 deletions(-) diff --git a/cmake/xo_reader2Config.cmake.in b/cmake/xo_reader2Config.cmake.in index ed161c20..06d291b4 100644 --- a/cmake/xo_reader2Config.cmake.in +++ b/cmake/xo_reader2Config.cmake.in @@ -6,6 +6,7 @@ include(CMakeFindDependencyMacro) # must coordinate with xo_dependency() calls # in CMakeLists.txt # +find_dependency(xo_numeric) find_dependency(xo_procedure2) find_dependency(xo_gc) find_dependency(xo_tokenizer2) diff --git a/src/reader2/CMakeLists.txt b/src/reader2/CMakeLists.txt index 6ad71cdf..f9c6511c 100644 --- a/src/reader2/CMakeLists.txt +++ b/src/reader2/CMakeLists.txt @@ -73,6 +73,7 @@ set(SELF_SRCS xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) # note: deps here must also appear in cmake/xo_expression2Config.cmake.in +xo_dependency(${SELF_LIB} xo_numeric) xo_dependency(${SELF_LIB} xo_procedure2) xo_dependency(${SELF_LIB} xo_gc) xo_dependency(${SELF_LIB} xo_tokenizer2) diff --git a/src/reader2/DProgressSsm.cpp b/src/reader2/DProgressSsm.cpp index 72ec3e93..eafe88b8 100644 --- a/src/reader2/DProgressSsm.cpp +++ b/src/reader2/DProgressSsm.cpp @@ -12,6 +12,8 @@ #include "ApplySsm.hpp" #include "ParenSsm.hpp" +#include + #include #include @@ -118,15 +120,15 @@ namespace xo { switch (tktype) { case tokentype::tk_assign: return optype::op_assign; - case tokentype::tk_plus: + case tokentype::tk_plus: // [+] return optype::op_add; - case tokentype::tk_minus: + case tokentype::tk_minus: // [-] return optype::op_subtract; - case tokentype::tk_star: + case tokentype::tk_star: // [*] return optype::op_multiply; - case tokentype::tk_slash: + case tokentype::tk_slash: // [/] return optype::op_divide; - case tokentype::tk_cmpeq: + case tokentype::tk_cmpeq: // [==] return optype::op_equal; case tokentype::tk_cmpne: return optype::op_not_equal; @@ -297,12 +299,12 @@ namespace xo { break; case tokentype::tk_star: + case tokentype::tk_slash: case tokentype::tk_minus: case tokentype::tk_cmpeq: this->on_operator_token(tk, p_psm); return; - case tokentype::tk_slash: case tokentype::tk_cmpne: case tokentype::tk_type: case tokentype::tk_lambda: @@ -1283,9 +1285,40 @@ namespace xo { break; case optype::op_divide: - // TODO: implement binary operator expression assembly - assert(false); + { + auto pm_obj = (with_facet::mkobj + (&NumericPrimitives::s_div_gco_gco_pm)); + auto fn_expr = (DConstant::make + (p_psm->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 + (TypeRef::prefix_type::from_chars("_div_gco"), + nullptr); + + return DApplyExpr::make2(p_psm->expr_alloc(), + tref, fn_expr, lhs_, rhs_); + } + break; + case optype::op_subtract: /* editor bait: op_minus */ { auto pm_obj = (with_facet::mkobj diff --git a/src/reader2/init_reader2.cpp b/src/reader2/init_reader2.cpp index aa7e291c..a6e1a7b0 100644 --- a/src/reader2/init_reader2.cpp +++ b/src/reader2/init_reader2.cpp @@ -8,6 +8,7 @@ #include "reader2_register_types.hpp" #include +#include #include namespace xo { @@ -30,6 +31,7 @@ namespace xo { /* direct subsystem deps for xo-reader2/ */ retval ^= InitSubsys::require(); + retval ^= InitSubsys::require(); /* xo-reader2/'s own initialization code */ retval ^= Subsystem::provide("reader2", &init); diff --git a/utest/SchematikaParser.test.cpp b/utest/SchematikaParser.test.cpp index 2b92161a..b6934f18 100644 --- a/utest/SchematikaParser.test.cpp +++ b/utest/SchematikaParser.test.cpp @@ -578,6 +578,67 @@ namespace xo { log && fixture.log_memory_layout(&log); } + TEST_CASE("SchematikaParser-interactive-arith2", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + 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: + * + * 3.14159265 / 10.0 ; + * + **/ + + std::vector tk_v{ + Token::f64_token("3.14159265"), + Token::slash_token(), + Token::f64_token("10.0"), + Token::semicolon_token(), + }; + + INFO(testname); + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + const auto & result = parser.result(); + { + 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() == "_div"); + + 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() == 10.0); + } + + log && fixture.log_memory_layout(&log); + } + TEST_CASE("SchematikaParser-interactive-cmp", "[reader2][SchematikaParser]") { const auto & testname = Catch::getResultCapture().getCurrentTestName();