diff --git a/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp index 8508402f..972e5736 100644 --- a/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp +++ b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp @@ -36,6 +36,8 @@ namespace xo { DFloat * x, DInteger * y); static obj cmp_lessequal(obj rcx, DFloat * x, DInteger * y); + static obj cmp_greater(obj rcx, + DFloat * x, DInteger * y); static obj cmp_greatequal(obj rcx, DFloat * x, DInteger * y); }; @@ -62,6 +64,8 @@ namespace xo { DInteger * x, DFloat * y); static obj cmp_lessequal(obj rcx, DInteger * x, DFloat * y); + static obj cmp_greater(obj rcx, + DInteger * x, DFloat * y); static obj cmp_greatequal(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 3eaabc9c..f9e6338c 100644 --- a/xo-numeric/include/xo/numeric/FloatOps.hpp +++ b/xo-numeric/include/xo/numeric/FloatOps.hpp @@ -35,6 +35,8 @@ namespace xo { DFloat * x, DFloat * y); static obj cmp_lessequal(obj rcx, DFloat * x, DFloat * y); + static obj cmp_greater(obj rcx, + DFloat * x, DFloat * y); static obj cmp_greatequal(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 b8342555..90eb6e05 100644 --- a/xo-numeric/include/xo/numeric/IntegerOps.hpp +++ b/xo-numeric/include/xo/numeric/IntegerOps.hpp @@ -37,6 +37,8 @@ namespace xo { DInteger * x, DInteger * y); static obj cmp_lessequal(obj rcx, DInteger * x, DInteger * y); + static obj cmp_greater(obj rcx, + DInteger * x, DInteger * y); static obj cmp_greatequal(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 53b35b97..bd1f4bf4 100644 --- a/xo-numeric/include/xo/numeric/NumericDispatch.hpp +++ b/xo-numeric/include/xo/numeric/NumericDispatch.hpp @@ -93,27 +93,32 @@ namespace xo { obj x, obj y); - /** compare two numeric values for equality **/ + /** compare two numeric values for equality (==) **/ static obj cmp_equal(obj rcx, obj x, obj y); - /** compare two numeric values for inequality **/ + /** compare two numeric values for inequality (!~=) **/ static obj cmp_notequal(obj rcx, obj x, obj y); - /** compare two numeric values for less **/ + /** compare two numeric values for less (<) **/ static obj cmp_less(obj rcx, obj x, obj y); - /** compare two numeric values for less-or-equal **/ + /** compare two numeric values for less-or-equal (<=) **/ static obj cmp_lessequal(obj rcx, obj x, obj y); - /** compare two numeric values for greater-or-equal **/ + /** compare two numeric values for greater (>) **/ + static obj cmp_greater(obj rcx, + obj x, + obj y); + + /** compare two numeric values for greater-or-equal (>=) **/ static obj cmp_greatequal(obj rcx, obj x, obj y); @@ -135,6 +140,7 @@ namespace xo { typename NumericOps::BinaryOp_Impl cmpne_fn, typename NumericOps::BinaryOp_Impl cmplt_fn, typename NumericOps::BinaryOp_Impl cmple_fn, + typename NumericOps::BinaryOp_Impl cmpgt_fn, typename NumericOps::BinaryOp_Impl cmpge_fn) { KeyType key(typeseq::id().seqno(), @@ -150,6 +156,7 @@ namespace xo { cmpne_fn, cmplt_fn, cmple_fn, + cmpgt_fn, cmpge_fn); } diff --git a/xo-numeric/include/xo/numeric/NumericOps.hpp b/xo-numeric/include/xo/numeric/NumericOps.hpp index 5d983a98..ea25fb28 100644 --- a/xo-numeric/include/xo/numeric/NumericOps.hpp +++ b/xo-numeric/include/xo/numeric/NumericOps.hpp @@ -30,9 +30,12 @@ namespace xo { BinaryOp cmpne, BinaryOp cmplt, BinaryOp cmple, + BinaryOp cmpgt, BinaryOp cmpge) : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, - cmpeq_{cmpeq}, cmpne_{cmpne}, cmplt_{cmplt}, cmple_{cmple}, cmpge_{cmpge} {} + cmpeq_{cmpeq}, cmpne_{cmpne}, + cmplt_{cmplt}, cmple_{cmple}, + cmpgt_{cmpgt}, cmpge_{cmpge} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; @@ -47,6 +50,8 @@ namespace xo { BinaryOp cmplt_ = nullptr; /** compare numerics (<=) **/ BinaryOp cmple_ = nullptr; + /** compare numerics (>) **/ + BinaryOp cmpgt_ = nullptr; /** compare numerics (>=) **/ BinaryOp cmpge_ = nullptr; }; @@ -68,6 +73,7 @@ namespace xo { BinaryOp_Impl cmpne, BinaryOp_Impl cmplt, BinaryOp_Impl cmple, + BinaryOp_Impl cmpgt, BinaryOp_Impl cmpge) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), @@ -77,6 +83,7 @@ namespace xo { reinterpret_cast(cmpne), reinterpret_cast(cmplt), reinterpret_cast(cmple), + reinterpret_cast(cmpgt), reinterpret_cast(cmpge)); } }; diff --git a/xo-numeric/src/numeric/FloatIntegerOps.cpp b/xo-numeric/src/numeric/FloatIntegerOps.cpp index d2fedcfa..fab04cae 100644 --- a/xo-numeric/src/numeric/FloatIntegerOps.cpp +++ b/xo-numeric/src/numeric/FloatIntegerOps.cpp @@ -74,6 +74,14 @@ namespace xo { x->value() <= DFloat::value_type(y->value())); } + obj + FloatIntegerOps::cmp_greater(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() > DFloat::value_type(y->value())); + } + obj FloatIntegerOps::cmp_greatequal(obj rcx, DFloat * x, DInteger * y) @@ -144,6 +152,14 @@ namespace xo { DFloat::value_type(x->value()) <= y->value()); } + obj + IntegerFloatOps::cmp_greater(obj rcx, + DInteger * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) > y->value()); + } + obj IntegerFloatOps::cmp_greatequal(obj rcx, DInteger * x, DFloat * y) diff --git a/xo-numeric/src/numeric/FloatOps.cpp b/xo-numeric/src/numeric/FloatOps.cpp index a549c8ac..be522624 100644 --- a/xo-numeric/src/numeric/FloatOps.cpp +++ b/xo-numeric/src/numeric/FloatOps.cpp @@ -75,6 +75,14 @@ namespace xo { x->value() <= y->value()); } + obj + FloatOps::cmp_greater(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + x->value() > y->value()); + } + obj FloatOps::cmp_greatequal(obj rcx, DFloat * x, DFloat * y) diff --git a/xo-numeric/src/numeric/IntegerOps.cpp b/xo-numeric/src/numeric/IntegerOps.cpp index af67a5ee..280e89d3 100644 --- a/xo-numeric/src/numeric/IntegerOps.cpp +++ b/xo-numeric/src/numeric/IntegerOps.cpp @@ -69,6 +69,13 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() <= y->value()); } + obj + IntegerOps::cmp_greater(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() > y->value()); + } + obj IntegerOps::cmp_greatequal(obj rcx, DInteger * x, DInteger * y) diff --git a/xo-numeric/src/numeric/NumericDispatch.cpp b/xo-numeric/src/numeric/NumericDispatch.cpp index 0cc0af11..1ebdd414 100644 --- a/xo-numeric/src/numeric/NumericDispatch.cpp +++ b/xo-numeric/src/numeric/NumericDispatch.cpp @@ -162,13 +162,25 @@ namespace xo { x, y); } + obj + NumericDispatch::cmp_greater(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_greater", + "incomparable types in x>y", + &AnonymizedNumericOps::cmpgt_, + x, y); + } + obj NumericDispatch::cmp_greatequal(obj rcx, obj x, obj y) { return dispatch(rcx, - "NumericDispatch::cmp_great", + "NumericDispatch::cmp_greatequal", "incomparable types in x>=y", &AnonymizedNumericOps::cmpge_, x, y); diff --git a/xo-numeric/src/numeric/numeric_register_facets.cpp b/xo-numeric/src/numeric/numeric_register_facets.cpp index e70abe39..7ef2555a 100644 --- a/xo-numeric/src/numeric/numeric_register_facets.cpp +++ b/xo-numeric/src/numeric/numeric_register_facets.cpp @@ -43,6 +43,7 @@ namespace xo { &FloatOps::cmp_notequal, &FloatOps::cmp_less, &FloatOps::cmp_lessequal, + &FloatOps::cmp_greater, &FloatOps::cmp_greatequal); NumericDispatch::instance().register_impl @@ -54,6 +55,7 @@ namespace xo { &FloatIntegerOps::cmp_notequal, &FloatIntegerOps::cmp_less, &FloatIntegerOps::cmp_lessequal, + &FloatIntegerOps::cmp_greater, &FloatIntegerOps::cmp_greatequal); NumericDispatch::instance().register_impl @@ -65,6 +67,7 @@ namespace xo { &IntegerFloatOps::cmp_notequal, &IntegerFloatOps::cmp_less, &IntegerFloatOps::cmp_lessequal, + &IntegerFloatOps::cmp_greater, &IntegerFloatOps::cmp_greatequal); NumericDispatch::instance().register_impl @@ -76,6 +79,7 @@ namespace xo { &IntegerOps::cmp_notequal, &IntegerOps::cmp_less, &IntegerOps::cmp_lessequal, + &IntegerOps::cmp_greater, &IntegerOps::cmp_greatequal); log && log(xtag("ANumeric.tseq", typeseq::id())); diff --git a/xo-numeric/src/numeric/numeric_register_primitives.cpp b/xo-numeric/src/numeric/numeric_register_primitives.cpp index 63c6f5fe..ff2749e3 100644 --- a/xo-numeric/src/numeric/numeric_register_primitives.cpp +++ b/xo-numeric/src/numeric/numeric_register_primitives.cpp @@ -74,6 +74,8 @@ namespace xo { flags & InstallFlags::f_essential); ok = ok & install_aux(sink, mm, "_cmple", &NumericDispatch::cmp_lessequal, flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmpgt", &NumericDispatch::cmp_greater, + flags & InstallFlags::f_essential); ok = ok & install_aux(sink, mm, "_cmpge", &NumericDispatch::cmp_greatequal, flags & InstallFlags::f_essential); diff --git a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp index 3ae647dc..4f14f72a 100644 --- a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp +++ b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp @@ -108,6 +108,8 @@ namespace xo { obj cmplt_pm() const; /** polymorphic less-or-equal comparison. Use to implement infix op<= **/ obj cmple_pm() const; + /** polymorphic greater comparison. Use to implement infix op> **/ + obj cmpgt_pm() const; /** polymorphic greater-or-equal comparison. Use to implement infix op>= **/ obj cmpge_pm() const; @@ -423,6 +425,7 @@ namespace xo { Binding cmpne_binding_; Binding cmplt_binding_; Binding cmple_binding_; + Binding cmpgt_binding_; Binding cmpge_binding_; /** current output from parser **/ diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index 80b7bb26..90fb5d16 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -136,7 +136,7 @@ namespace xo { return optype::op_less; case tokentype::tk_cmple: // [<=] return optype::op_less_equal; - case tokentype::tk_rightangle: + case tokentype::tk_rightangle: // [>] return optype::op_great; case tokentype::tk_cmpge: // [>=] return optype::op_great_equal; @@ -290,7 +290,6 @@ namespace xo { case tokentype::tk_leftbracket: case tokentype::tk_rightbracket: case tokentype::tk_leftbrace: - case tokentype::tk_rightangle: case tokentype::tk_dot: case tokentype::tk_doublecolon: case tokentype::tk_assign: @@ -304,6 +303,7 @@ namespace xo { case tokentype::tk_cmpeq: case tokentype::tk_cmpne: case tokentype::tk_leftangle: + case tokentype::tk_rightangle: case tokentype::tk_cmple: case tokentype::tk_cmpge: this->on_operator_token(tk, p_psm); @@ -1170,7 +1170,11 @@ namespace xo { lhs_, rhs_); case optype::op_great: - assert(false); + return assemble_numeric_expr_aux + (p_psm->expr_alloc(), + TypeRef::prefix_type::from_chars("_cmpgt_gco"), + p_psm->cmpgt_pm(), + lhs_, rhs_); break; case optype::op_great_equal: @@ -1184,14 +1188,14 @@ namespace xo { return assemble_numeric_expr_aux (p_psm->expr_alloc(), TypeRef::prefix_type::from_chars("_mul_gco"), - p_psm->multiply_pm(), //&NumericPrimitives::s_mul_gco_gco_pm + p_psm->multiply_pm(), lhs_, rhs_); case optype::op_divide: return assemble_numeric_expr_aux (p_psm->expr_alloc(), TypeRef::prefix_type::from_chars("_div_gco"), - p_psm->divide_pm(), // &NumericPrimitives::s_div_gco_gco_pm + p_psm->divide_pm(), lhs_, rhs_); case optype::op_add: @@ -1200,39 +1204,6 @@ namespace xo { TypeRef::prefix_type::from_chars("_add_gco"), p_psm->add_pm(), lhs_, rhs_); -#ifdef OBSOLETE - { - 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_); - } -#endif break; @@ -1260,122 +1231,6 @@ case optype::op_assign: this->rhs_); } -case optype::op_equal: - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_cmp_eq_i64(lhs_, rhs_); - } else { - - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; - -case optype::op_not_equal: - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_cmp_ne_i64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; - -case optype::op_less: - // TODO: floating-point less-than - - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_cmp_lt_i64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; - -case optype::op_less_equal: - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_cmp_le_i64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; - -case optype::op_great: - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_cmp_gt_i64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; - -case optype::op_great_equal: - // TODO: upconvert integer->double - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_cmp_ge_i64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - - assert(false); - -case optype::op_add: - // TODO: upconvert integer->double - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_add2_i64(lhs_, rhs_); - } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { - return Apply::make_add2_f64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; -case optype::op_subtract: - // TODO: upconvert integer->double - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_sub2_i64(lhs_, rhs_); - } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { - return Apply::make_sub2_f64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; - -case optype::op_multiply: - // TODO: upconvert integer->double - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_mul2_i64(lhs_, rhs_); - } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { - return Apply::make_mul2_f64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - - break; - -case optype::op_divide: - // TODO: upconvert integer->double - if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { - return Apply::make_div2_i64(lhs_, rhs_); - } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { - return Apply::make_div2_f64(lhs_, rhs_); - } else { - this->apply_type_error(c_self_name, - op_type_, lhs_, rhs_, p_psm); - return nullptr; - } - break; #endif case optype::n_optype: diff --git a/xo-reader2/src/reader2/ParserStateMachine.cpp b/xo-reader2/src/reader2/ParserStateMachine.cpp index 1bc9066f..0634a564 100644 --- a/xo-reader2/src/reader2/ParserStateMachine.cpp +++ b/xo-reader2/src/reader2/ParserStateMachine.cpp @@ -151,6 +151,12 @@ namespace xo { this->cmple_binding_ = global_symtab_->lookup_binding(name); } + { + const DUniqueString * name = stringtable_.lookup("_cmpgt"); + assert(name); + this->cmpgt_binding_ = global_symtab_->lookup_binding(name); + } + { const DUniqueString * name = stringtable_.lookup("_cmpge"); assert(name); @@ -241,6 +247,15 @@ namespace xo { return retval; } + obj + ParserStateMachine::cmpgt_pm() const + { + obj retval = global_env_->lookup_value(cmpgt_binding_); + assert(retval); + + return retval; + } + obj ParserStateMachine::cmpge_pm() const {