diff --git a/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp index 97a2c3f6..9d21540f 100644 --- a/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp +++ b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp @@ -23,6 +23,10 @@ namespace xo { DFloat * x, DInteger * y); static obj divide(obj rcx, DFloat * x, DInteger * y); + static obj add(obj rcx, + DFloat * x, DInteger * y); + static obj subtract(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -34,6 +38,10 @@ namespace xo { DInteger * x, DFloat * y); static obj divide(obj rcx, DInteger * x, DFloat * y); + static obj add(obj rcx, + DInteger * x, DFloat * y); + static obj subtract(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 c3a2c288..75ffb5e4 100644 --- a/xo-numeric/include/xo/numeric/FloatOps.hpp +++ b/xo-numeric/include/xo/numeric/FloatOps.hpp @@ -22,6 +22,10 @@ namespace xo { DFloat * x, DFloat * y); static obj divide(obj rcx, DFloat * x, DFloat * y); + static obj add(obj rcx, + DFloat * x, DFloat * y); + static obj subtract(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 4f9138de..d839ad36 100644 --- a/xo-numeric/include/xo/numeric/IntegerOps.hpp +++ b/xo-numeric/include/xo/numeric/IntegerOps.hpp @@ -23,6 +23,12 @@ namespace xo { static obj divide(obj rcx, DInteger * x, DInteger * y); + static obj add(obj rcx, + DInteger * x, DInteger * y); + + static obj subtract(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 5174430e..0f7a4ffd 100644 --- a/xo-numeric/include/xo/numeric/NumericDispatch.hpp +++ b/xo-numeric/include/xo/numeric/NumericDispatch.hpp @@ -70,6 +70,18 @@ namespace xo { obj x, obj y); + /** add w/ runtime polymorphism (double-dispatch) + **/ + static obj add(obj rcx, + obj x, + obj y); + + /** subtract w/ runtime polymorphism (double-dispatch) + **/ + static obj subtract(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -80,13 +92,19 @@ namespace xo { **/ template void register_impl(typename NumericOps::BinaryOp_Impl mul_fn, - typename NumericOps::BinaryOp_Impl div_fn) { + typename NumericOps::BinaryOp_Impl div_fn, + typename NumericOps::BinaryOp_Impl add_fn, + typename NumericOps::BinaryOp_Impl sub_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); // note: copying op table so they're in proximity - this->dispatch_[key] = NumericOps::make(mul_fn, div_fn); + this->dispatch_[key] + = NumericOps::make(mul_fn, + div_fn, + add_fn, + sub_fn); } private: diff --git a/xo-numeric/include/xo/numeric/NumericOps.hpp b/xo-numeric/include/xo/numeric/NumericOps.hpp index 4e900534..bc8630a6 100644 --- a/xo-numeric/include/xo/numeric/NumericOps.hpp +++ b/xo-numeric/include/xo/numeric/NumericOps.hpp @@ -23,11 +23,15 @@ namespace xo { AnonymizedNumericOps() = default; /** @p multiply to multiply (x,y); allocate from mm **/ explicit AnonymizedNumericOps(BinaryOp multiply, - BinaryOp divide) - : multiply_{multiply}, divide_{divide} {} + BinaryOp divide, + BinaryOp add, + BinaryOp subtract) + : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; + BinaryOp add_ = nullptr; + BinaryOp subtract_ = nullptr; }; template @@ -40,9 +44,13 @@ namespace xo { public: static AnonymizedNumericOps make(BinaryOp_Impl multiply, - BinaryOp_Impl divide) { + BinaryOp_Impl divide, + BinaryOp_Impl add, + BinaryOp_Impl subtract) { return AnonymizedNumericOps(reinterpret_cast(multiply), - reinterpret_cast(divide)); + reinterpret_cast(divide), + reinterpret_cast(add), + reinterpret_cast(subtract)); } }; diff --git a/xo-numeric/include/xo/numeric/NumericPrimitives.hpp b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp index 3eab681a..f5ce374e 100644 --- a/xo-numeric/include/xo/numeric/NumericPrimitives.hpp +++ b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp @@ -18,6 +18,10 @@ namespace xo { static DPrimitive_gco_2_gco_gco s_mul_gco_gco_pm; /** polymorphic (in both arguments) divide **/ static DPrimitive_gco_2_gco_gco s_div_gco_gco_pm; + /** polymorphic (in both arguments) add **/ + 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; }; } } diff --git a/xo-numeric/src/numeric/FloatIntegerOps.cpp b/xo-numeric/src/numeric/FloatIntegerOps.cpp index 65a106ab..5b15d5bb 100644 --- a/xo-numeric/src/numeric/FloatIntegerOps.cpp +++ b/xo-numeric/src/numeric/FloatIntegerOps.cpp @@ -27,6 +27,20 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() / y->value()); } + obj + FloatIntegerOps::add(obj rcx, + DFloat * x, DInteger * y) + { + return DFloat::box(rcx.allocator(), x->value() + y->value()); + } + + obj + FloatIntegerOps::subtract(obj rcx, + DFloat * x, DInteger * y) + { + return DFloat::box(rcx.allocator(), x->value() - y->value()); + } + // ----- Integer op Float ----- obj @@ -42,6 +56,21 @@ namespace xo { { return DFloat::box(rcx.allocator(), x->value() / y->value()); } + + obj + IntegerFloatOps::add(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() + y->value()); + } + + obj + IntegerFloatOps::subtract(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() - y->value()); + } + } } diff --git a/xo-numeric/src/numeric/FloatOps.cpp b/xo-numeric/src/numeric/FloatOps.cpp index 9db149b9..8821e48e 100644 --- a/xo-numeric/src/numeric/FloatOps.cpp +++ b/xo-numeric/src/numeric/FloatOps.cpp @@ -25,6 +25,21 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() / y->value()); } + obj + FloatOps::add(obj rcx, + DFloat * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() + y->value()); + } + + obj + FloatOps::subtract(obj rcx, + DFloat * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() - y->value()); + } + + } } diff --git a/xo-numeric/src/numeric/IntegerOps.cpp b/xo-numeric/src/numeric/IntegerOps.cpp index c8322266..0f435b74 100644 --- a/xo-numeric/src/numeric/IntegerOps.cpp +++ b/xo-numeric/src/numeric/IntegerOps.cpp @@ -25,6 +25,20 @@ namespace xo { return DInteger::box(rcx.allocator(), x->value() / y->value()); } + obj + IntegerOps::add(obj rcx, + DInteger * x, DInteger * y) + { + return DInteger::box(rcx.allocator(), x->value() + y->value()); + } + + obj + IntegerOps::subtract(obj rcx, + DInteger * x, DInteger * y) + { + return DInteger::box(rcx.allocator(), x->value() - y->value()); + } + } } diff --git a/xo-numeric/src/numeric/NumericDispatch.cpp b/xo-numeric/src/numeric/NumericDispatch.cpp index bfc65586..ded8c420 100644 --- a/xo-numeric/src/numeric/NumericDispatch.cpp +++ b/xo-numeric/src/numeric/NumericDispatch.cpp @@ -27,6 +27,9 @@ namespace xo { auto target_fn = NumericDispatch::instance().dispatch_[key].multiply_; + if (!target_fn) + assert(false); + return (*target_fn)(rcx, x.data(), y.data()); } @@ -35,23 +38,48 @@ namespace xo { obj x, obj y) { - scope log(XO_DEBUG(true)); - KeyType key(x._typeseq(), y._typeseq()); - log && log(xtag("x.tseq", x._typeseq().seqno()), - xtag("y.tseq", y._typeseq().seqno())); - auto target_fn = NumericDispatch::instance().dispatch_[key].divide_; - log && log(xtag("target_fn", target_fn)); - - assert(target_fn); + if (!target_fn) + assert(false); return (*target_fn)(rcx, x.data(), y.data()); } + obj + NumericDispatch::add(obj rcx, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].add_; + + if (!target_fn) + assert(false); + + return (*target_fn)(rcx, x.data(), y.data()); + } + + obj + NumericDispatch::subtract(obj rcx, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].subtract_; + + 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 a17de848..ebbcb30b 100644 --- a/xo-numeric/src/numeric/NumericPrimitives.cpp +++ b/xo-numeric/src/numeric/NumericPrimitives.cpp @@ -19,6 +19,14 @@ namespace xo { NumericPrimitives::s_div_gco_gco_pm("_div", &NumericDispatch::divide); + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_add_gco_gco_pm("_add", + &NumericDispatch::add); + + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_sub_gco_gco_pm("_sub", + &NumericDispatch::subtract); + } /*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 3e2d94a5..20e2093d 100644 --- a/xo-numeric/src/numeric/numeric_register_facets.cpp +++ b/xo-numeric/src/numeric/numeric_register_facets.cpp @@ -36,19 +36,27 @@ namespace xo { NumericDispatch::instance().register_impl (&FloatOps::multiply, - &FloatOps::divide); + &FloatOps::divide, + &FloatOps::add, + &FloatOps::subtract); NumericDispatch::instance().register_impl (&FloatIntegerOps::multiply, - &FloatIntegerOps::divide); + &FloatIntegerOps::divide, + &FloatIntegerOps::add, + &FloatIntegerOps::subtract); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, - &IntegerFloatOps::divide); + &IntegerFloatOps::divide, + &IntegerFloatOps::add, + &IntegerFloatOps::subtract); NumericDispatch::instance().register_impl (&IntegerOps::multiply, - &IntegerOps::divide); + &IntegerOps::divide, + &IntegerOps::add, + &IntegerOps::subtract); log && log(xtag("ANumeric.tseq", typeseq::id())); diff --git a/xo-procedure2/include/xo/procedure2/init_primitives.hpp b/xo-procedure2/include/xo/procedure2/init_primitives.hpp index 562a984c..411b3d3e 100644 --- a/xo-procedure2/include/xo/procedure2/init_primitives.hpp +++ b/xo-procedure2/include/xo/procedure2/init_primitives.hpp @@ -22,7 +22,6 @@ namespace xo { * so we can dispatch on vector, matrix, function types **/ static DPrimitive_gco_2_gco_gco s_mul_gco_gco_pm; -#endif /** polymorphic subtract * @@ -30,6 +29,7 @@ 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 * diff --git a/xo-procedure2/src/procedure2/init_primitives.cpp b/xo-procedure2/src/procedure2/init_primitives.cpp index 1d1d50fc..c3cc5176 100644 --- a/xo-procedure2/src/procedure2/init_primitives.cpp +++ b/xo-procedure2/src/procedure2/init_primitives.cpp @@ -99,7 +99,6 @@ namespace xo { xtag("y.tseq", y_tseq))); return obj(); } -#endif obj sub_gco_gco(obj rcx, @@ -160,6 +159,7 @@ namespace xo { xtag("y.tseq", y_tseq))); return obj(); } +#endif obj equal_gco_gco(obj rcx, @@ -260,10 +260,10 @@ namespace xo { #ifdef OSOLETE DPrimitive_gco_2_gco_gco Primitives::s_mul_gco_gco_pm("_mul", &mul_gco_gco); -#endif 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); diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index dd201b65..ad3a0297 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -295,11 +295,11 @@ namespace xo { case tokentype::tk_doublecolon: case tokentype::tk_assign: case tokentype::tk_yields: - case tokentype::tk_plus: break; case tokentype::tk_star: case tokentype::tk_slash: + case tokentype::tk_plus: case tokentype::tk_minus: case tokentype::tk_cmpeq: this->on_operator_token(tk, p_psm); @@ -1246,7 +1246,6 @@ namespace xo { case optype::op_less_equal: case optype::op_great: case optype::op_great_equal: - case optype::op_add: assert(false); break; @@ -1319,10 +1318,45 @@ namespace xo { break; + case optype::op_add: + { + auto pm_obj = (with_facet::mkobj + (&NumericPrimitives::s_add_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("_add_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 - (&Primitives::s_sub_gco_gco_pm)); + (&NumericPrimitives::s_sub_gco_gco_pm)); auto fn_expr = (DConstant::make (p_psm->expr_alloc(), pm_obj));