diff --git a/src/reader2/DProgressSsm.cpp b/src/reader2/DProgressSsm.cpp index ad3a0297..46321b0a 100644 --- a/src/reader2/DProgressSsm.cpp +++ b/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/utest/SchematikaParser.test.cpp b/utest/SchematikaParser.test.cpp index b6934f18..fa108af3 100644 --- a/utest/SchematikaParser.test.cpp +++ b/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();