xo-interpreter2 stack: streamline op== impl + utests

This commit is contained in:
Roland Conybeare 2026-02-19 09:03:02 -08:00
commit 8743aa44ef
2 changed files with 139 additions and 3 deletions

View file

@ -43,6 +43,7 @@ namespace xo {
using xo::scm::Variable; using xo::scm::Variable;
using xo::scm::Apply; using xo::scm::Apply;
#endif #endif
using xo::mm::AAllocator;
using xo::mm::AGCObject; using xo::mm::AGCObject;
using xo::print::APrintable; using xo::print::APrintable;
using xo::facet::FacetRegistry; using xo::facet::FacetRegistry;
@ -1185,6 +1186,45 @@ namespace xo {
namespace { namespace {
// make_builtin_apply_pm2 // make_builtin_apply_pm2
// helper function for making apply expression that invokes
// a binary primitive. Use for numeric operators:
// {*, /, +, -, ==}
//
obj<AExpression>
assemble_numeric_expr_aux(obj<AAllocator> expr_alloc,
const TypeRef::prefix_type & prefix,
DPrimitive_gco_2_gco_gco * p_gco_pm,
obj<AExpression> lhs,
obj<AExpression> rhs)
{
auto pm_obj = with_facet<AGCObject>::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<AExpression> obj<AExpression>
@ -1223,9 +1263,16 @@ namespace xo {
break; break;
case optype::op_equal: 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<AGCObject>::mkobj auto pm_obj = (with_facet<AGCObject>::mkobj
(&Primitives::s_equal_gco_gco_pm)); (&NumericPrimitives::s_cmpeq_gco_gco_pm));
auto fn_expr = (DConstant::make auto fn_expr = (DConstant::make
(p_psm->expr_alloc(), pm_obj)); (p_psm->expr_alloc(), pm_obj));
@ -1240,6 +1287,7 @@ namespace xo {
fn_expr, lhs_, rhs_); fn_expr, lhs_, rhs_);
} }
break; break;
#endif
case optype::op_not_equal: case optype::op_not_equal:
case optype::op_less: case optype::op_less:
@ -1250,6 +1298,13 @@ namespace xo {
break; break;
case optype::op_multiply: 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<AGCObject>::mkobj auto pm_obj = (with_facet<AGCObject>::mkobj
(&NumericPrimitives::s_mul_gco_gco_pm)); (&NumericPrimitives::s_mul_gco_gco_pm));
@ -1281,6 +1336,7 @@ namespace xo {
return DApplyExpr::make2(p_psm->expr_alloc(), return DApplyExpr::make2(p_psm->expr_alloc(),
tref, fn_expr, lhs_, rhs_); tref, fn_expr, lhs_, rhs_);
} }
#endif
break; break;
case optype::op_divide: case optype::op_divide:

View file

@ -11,6 +11,7 @@
#include <xo/reader2/init_reader2.hpp> #include <xo/reader2/init_reader2.hpp>
#include <xo/expression2/DefineExpr.hpp> #include <xo/expression2/DefineExpr.hpp>
#include <xo/expression2/ApplyExpr.hpp> #include <xo/expression2/ApplyExpr.hpp>
#include <xo/expression2/IfElseExpr.hpp>
#include <xo/expression2/VarRef.hpp> #include <xo/expression2/VarRef.hpp>
#include <xo/expression2/Constant.hpp> #include <xo/expression2/Constant.hpp>
#include <xo/procedure2/Primitive_gco_2_gco_gco.hpp> #include <xo/procedure2/Primitive_gco_2_gco_gco.hpp>
@ -31,6 +32,7 @@ namespace xo {
using xo::scm::AExpression; using xo::scm::AExpression;
using xo::scm::DDefineExpr; using xo::scm::DDefineExpr;
using xo::scm::DIfElseExpr;
using xo::scm::DApplyExpr; using xo::scm::DApplyExpr;
using xo::scm::DVarRef; using xo::scm::DVarRef;
using xo::scm::DConstant; using xo::scm::DConstant;
@ -680,7 +682,7 @@ namespace xo {
auto pm = obj<AGCObject,DPrimitive_gco_2_gco_gco>::from(fn->value()); auto pm = obj<AGCObject,DPrimitive_gco_2_gco_gco>::from(fn->value());
REQUIRE(pm); REQUIRE(pm);
REQUIRE(pm->name() == "_equal"); REQUIRE(pm->name() == "_cmpeq");
auto lhs = obj<AExpression,DConstant>::from(expr->arg(0)); auto lhs = obj<AExpression,DConstant>::from(expr->arg(0));
REQUIRE(lhs); REQUIRE(lhs);
@ -700,6 +702,84 @@ namespace xo {
log && fixture.log_memory_layout(&log); 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<Token> 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<AExpression,DDefineExpr>::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<Token> 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<AExpression,DIfElseExpr>::from(result.result_expr());
REQUIRE(expr);
}
log && fixture.log_memory_layout(&log);
}
TEST_CASE("SchematikaParser-interactive-lambda", "[reader2][SchematikaParser]") TEST_CASE("SchematikaParser-interactive-lambda", "[reader2][SchematikaParser]")
{ {
const auto & testname = Catch::getResultCapture().getCurrentTestName(); const auto & testname = Catch::getResultCapture().getCurrentTestName();
@ -743,7 +823,7 @@ namespace xo {
log && fixture.log_memory_layout(&log); 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(); const auto & testname = Catch::getResultCapture().getCurrentTestName();