From 8d5a9c825f9a83e8fcc4a23a1d60e97240557aad Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 27 Jul 2025 13:35:20 -0400 Subject: [PATCH] xo-reader: integer arithmetic + parser + pretty-printing adds --- xo-expression/include/xo/expression/Apply.hpp | 13 ++ .../include/xo/expression/Primitive.hpp | 19 +++ .../include/xo/expression/llvmintrinsic.hpp | 10 +- xo-expression/src/expression/Apply.cpp | 38 ++++++ xo-expression/src/expression/GlobalEnv.cpp | 1 + xo-expression/src/expression/Primitive.cpp | 88 ++++++++++++++ .../xo/indentlog/print/ppdetail_atomic.hpp | 1 + .../include/xo/indentlog/print/pretty.hpp | 4 +- xo-reader/include/xo/reader/apply_xs.hpp | 5 +- xo-reader/include/xo/reader/define_xs.hpp | 1 + xo-reader/include/xo/reader/exprseq_xs.hpp | 2 + xo-reader/include/xo/reader/exprstate.hpp | 4 + xo-reader/include/xo/reader/if_else_xs.hpp | 7 +- xo-reader/include/xo/reader/lambda_xs.hpp | 5 + .../xo/reader/pretty_envframestack.hpp | 7 ++ .../xo/reader/pretty_exprstatestack.hpp | 14 +++ xo-reader/include/xo/reader/progress_xs.hpp | 10 ++ xo-reader/src/reader/define_xs.cpp | 10 +- xo-reader/src/reader/exprseq_xs.cpp | 29 ++++- xo-reader/src/reader/exprstate.cpp | 8 ++ xo-reader/src/reader/if_else_xs.cpp | 1 + xo-reader/src/reader/lambda_xs.cpp | 7 ++ xo-reader/src/reader/progress_xs.cpp | 113 ++++++++++++++++-- xo-reflect/include/xo/reflect/TypeDescr.hpp | 16 ++- xo-reflect/src/reflect/TypeDescr.cpp | 21 ++++ 25 files changed, 408 insertions(+), 26 deletions(-) diff --git a/xo-expression/include/xo/expression/Apply.hpp b/xo-expression/include/xo/expression/Apply.hpp index a4eac339..aae28585 100644 --- a/xo-expression/include/xo/expression/Apply.hpp +++ b/xo-expression/include/xo/expression/Apply.hpp @@ -35,6 +35,19 @@ namespace xo { static rp make_cmp_ne_i64(const rp & lhs, const rp & rhs); + /** create apply-expression to add two 64-bit integers **/ + static rp make_add2_i64(const rp & lhs, + const rp & rhs); + /** create apply-expression to subtract two 64-bit integers **/ + static rp make_sub2_i64(const rp & lhs, + const rp & rhs); + /** create apply-expression to multiply two 64-bit integers **/ + static rp make_mul2_i64(const rp & lhs, + const rp & rhs); + /** create apply-expression to divide two 64-bit integers **/ + static rp make_div2_i64(const rp & lhs, + const rp & rhs); + /** create apply-expression to add two 64-bit floating-point numbers **/ static rp make_add2_f64(const rp & lhs, const rp & rhs); diff --git a/xo-expression/include/xo/expression/Primitive.hpp b/xo-expression/include/xo/expression/Primitive.hpp index 29409209..cb940092 100644 --- a/xo-expression/include/xo/expression/Primitive.hpp +++ b/xo-expression/include/xo/expression/Primitive.hpp @@ -191,6 +191,9 @@ namespace xo { return Primitive::make(name, x, explicit_symbol_def, intrinsic); } + // NOTE: see xo-reader/src/reader/progress_xs.cpp + // binding operators to primitive applications. + /** builtin primitives :: i64 x i64 -> bool **/ class Primitive_cmp_i64 : public Primitive { public: @@ -203,6 +206,22 @@ namespace xo { static rp make_cmp_ne2_i64(); }; + /** builtin primitives :: i64 x i64 -> i64 **/ + class Primitive_i64 : public Primitive { + public: + using PrimitiveType = Primitive; + + public: + /** add2_i64: add two 64-bit integers **/ + static rp make_add2_i64(); + /** sub2_i64: subtract two 64-bit integers **/ + static rp make_sub2_i64(); + /** mul2_i64: multiply two 64-bit integers **/ + static rp make_mul2_i64(); + /** div2_i64: divide two 64-bit integers **/ + static rp make_div2_i64(); + }; + /** builtin primitives :: f64 x f64 -> f64 **/ class Primitive_f64 : public Primitive { public: diff --git a/xo-expression/include/xo/expression/llvmintrinsic.hpp b/xo-expression/include/xo/expression/llvmintrinsic.hpp index b13bccac..ede8719a 100644 --- a/xo-expression/include/xo/expression/llvmintrinsic.hpp +++ b/xo-expression/include/xo/expression/llvmintrinsic.hpp @@ -37,6 +37,8 @@ namespace xo { * NSW stands for 'no signed wrap' -> poison value if overflow (costs more) * NUW stands for 'no unsigned wrap' -> poison value if overflow (costs more) * @endnote + * + * See: xo-jit/src/jit/MachPipeline.cpp **/ enum class llvmintrinsic { // see /nix/store/x5yz...llvm-18.1.5-dev/include/llvm/IR/IRBuilder.h @@ -82,16 +84,16 @@ namespace xo { // TODO: unsigned comparisons - /** -> IRBuilder::CreateFadd (add 2 floating-point numbers) **/ + /** -> IRBuilder::CreateFAdd (add 2 floating-point numbers) **/ fp_add, - /** -> IRBuilder::CreateFsub (subtract 2 floating-pointer numbers) **/ + /** -> IRBuilder::CreateFSub (subtract 2 floating-pointer numbers) **/ fp_sub, - /** -> IRBuilder::CreateFmul (multiply 2 floating-point numbers) **/ + /** -> IRBuilder::CreateFMul (multiply 2 floating-point numbers) **/ fp_mul, - /** -> IRBuilder::CreateFdiv (divide 2 floating-point numbers) **/ + /** -> IRBuilder::CreateFDiv (divide 2 floating-point numbers) **/ fp_div, // TODO: floating-point comparisons diff --git a/xo-expression/src/expression/Apply.cpp b/xo-expression/src/expression/Apply.cpp index 220b5aa5..d3403784 100644 --- a/xo-expression/src/expression/Apply.cpp +++ b/xo-expression/src/expression/Apply.cpp @@ -30,6 +30,8 @@ namespace xo { return new Apply(fn_retval_type, fn, argv); } + // ----- integer comparison ----- + rp Apply::make_cmp_eq_i64(const rp & lhs, const rp & rhs) @@ -46,6 +48,42 @@ namespace xo { {lhs, rhs}); } + // ----- integer arithmetic ----- + + rp + Apply::make_add2_i64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_i64::make_add2_i64(), + {lhs, rhs}); + } + + rp + Apply::make_sub2_i64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_i64::make_sub2_i64(), + {lhs, rhs}); + } + + rp + Apply::make_mul2_i64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_i64::make_mul2_i64(), + {lhs, rhs}); + } + + rp + Apply::make_div2_i64(const rp & lhs, + const rp & rhs) + { + return Apply::make(Primitive_i64::make_div2_i64(), + {lhs, rhs}); + } + + // ----- floating point arithmetic ----- + rp Apply::make_add2_f64(const rp & lhs, const rp & rhs) diff --git a/xo-expression/src/expression/GlobalEnv.cpp b/xo-expression/src/expression/GlobalEnv.cpp index e9ec1acc..8ae06f69 100644 --- a/xo-expression/src/expression/GlobalEnv.cpp +++ b/xo-expression/src/expression/GlobalEnv.cpp @@ -3,6 +3,7 @@ * author: Roland Conybeare, Jul 2025 */ +#include "xo/indentlog/print/ppdetail_atomic.hpp" #include "GlobalEnv.hpp" #include "Expression.hpp" diff --git a/xo-expression/src/expression/Primitive.cpp b/xo-expression/src/expression/Primitive.cpp index bc73ebd7..db44d820 100644 --- a/xo-expression/src/expression/Primitive.cpp +++ b/xo-expression/src/expression/Primitive.cpp @@ -1,8 +1,17 @@ /* @file Primitive.cpp */ #include "Primitive.hpp" +#include extern "C" { + /** code here is used in two context: + * 1. Fallback implementation under llvm. + * In practice will use llvm intrinsic instead. + * See xo-jit/src/jit/MachPipeline.cpp + * 2. Schematika interpreter (aspirational asof jul 2025) + * + **/ + bool cmp_eq2_i64(std::int64_t x, std::int64_t y) { return x == y; @@ -13,6 +22,26 @@ extern "C" { return x != y; } + std::int64_t + add2_i64(std::int64_t x, std::int64_t y) { + return x + y; + } + + std::int64_t + sub2_i64(std::int64_t x, std::int64_t y) { + return x - y; + } + + std::int64_t + mul2_i64(std::int64_t x, std::int64_t y) { + return x * y; + } + + std::int64_t + div2_i64(std::int64_t x, std::int64_t y) { + return x / y; + } + double add2_f64(double x, double y) { return x + y; @@ -64,6 +93,65 @@ namespace xo { return s_retval; } + /* TODO: remaining integer arithmetic */ + + auto + Primitive_i64::make_add2_i64() -> rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("add2_i64", + &add2_i64, + true /*explicit_symbol_def*/, + llvmintrinsic::i_add); + + return s_retval; + } + + auto + Primitive_i64::make_sub2_i64() -> rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("sub2_i64", + &sub2_i64, + true /*explicit_symbol_def*/, + llvmintrinsic::i_sub); + + return s_retval; + } + + auto + Primitive_i64::make_mul2_i64() -> rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("mul2_i64", + &mul2_i64, + true /*explicit_symbol_def*/, + llvmintrinsic::i_mul); + + return s_retval; + } + + auto + Primitive_i64::make_div2_i64() -> rp + { + static rp s_retval; + + if (!s_retval) + s_retval = Primitive::make("div2_i64", + &div2_i64, + true /*explicit_symbol+def*/, + llvmintrinsic::i_sdiv); + return s_retval; + } + + // ----- floating-point arithmetic ----- + auto Primitive_f64::make_add2_f64() -> rp { diff --git a/xo-indentlog/include/xo/indentlog/print/ppdetail_atomic.hpp b/xo-indentlog/include/xo/indentlog/print/ppdetail_atomic.hpp index 3a14399b..795eae1d 100644 --- a/xo-indentlog/include/xo/indentlog/print/ppdetail_atomic.hpp +++ b/xo-indentlog/include/xo/indentlog/print/ppdetail_atomic.hpp @@ -112,6 +112,7 @@ namespace xo { PPDETAIL_ATOMIC(bool); PPDETAIL_ATOMIC(char); + PPDETAIL_ATOMIC(unsigned long); PPDETAIL_ATOMIC(std::int64_t); PPDETAIL_ATOMIC(std::uint64_t); PPDETAIL_ATOMIC(std::int32_t); diff --git a/xo-indentlog/include/xo/indentlog/print/pretty.hpp b/xo-indentlog/include/xo/indentlog/print/pretty.hpp index aa50ca3c..8068a297 100644 --- a/xo-indentlog/include/xo/indentlog/print/pretty.hpp +++ b/xo-indentlog/include/xo/indentlog/print/pretty.hpp @@ -107,7 +107,7 @@ namespace xo { /** pretty-print empty struct **/ template - std::uint32_t pretty_struct(const ppindentinfo & ppii, StructName && structname, Members&&...); + bool pretty_struct(const ppindentinfo & ppii, StructName && structname, Members&&...); /** auxiliary function supporting @ref pretty_stuct . * pretty-print a single member name on behalf of a struct/class. @@ -224,7 +224,7 @@ namespace xo { }; template - std::uint32_t + bool ppstate::pretty_struct(const ppindentinfo & ppii, StructName && structname, Members&&... members) { if (ppii.upto()) { diff --git a/xo-reader/include/xo/reader/apply_xs.hpp b/xo-reader/include/xo/reader/apply_xs.hpp index f3975dab..cf57b9ab 100644 --- a/xo-reader/include/xo/reader/apply_xs.hpp +++ b/xo-reader/include/xo/reader/apply_xs.hpp @@ -106,8 +106,11 @@ namespace xo { /** evaluates to the arguments to pass to @ref fn_ **/ std::vector> args_expr_v_; }; - } /*namespace scm */ + + namespace print { + PPDETAIL_ATOMIC(xo::scm::applyexprstatetype); + } } /*namespace xo*/ /* end apply_xs.hpp */ diff --git a/xo-reader/include/xo/reader/define_xs.hpp b/xo-reader/include/xo/reader/define_xs.hpp index d34b3254..76e1bcd8 100644 --- a/xo-reader/include/xo/reader/define_xs.hpp +++ b/xo-reader/include/xo/reader/define_xs.hpp @@ -107,6 +107,7 @@ namespace xo { parserstatemachine * p_psm) override; virtual void print(std::ostream & os) const override; + virtual bool pretty_print(const print::ppindentinfo & ppii) const override; private: static std::unique_ptr make(); diff --git a/xo-reader/include/xo/reader/exprseq_xs.hpp b/xo-reader/include/xo/reader/exprseq_xs.hpp index 2dc58e13..22b07f9e 100644 --- a/xo-reader/include/xo/reader/exprseq_xs.hpp +++ b/xo-reader/include/xo/reader/exprseq_xs.hpp @@ -57,6 +57,8 @@ namespace xo { parserstatemachine * p_psm) override; virtual void on_i64_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_f64_token(const token_type & tk, + parserstatemachine * p_psm) override; // ----- victory methods ----- diff --git a/xo-reader/include/xo/reader/exprstate.hpp b/xo-reader/include/xo/reader/exprstate.hpp index 6d3f8cd6..24e5f6d0 100644 --- a/xo-reader/include/xo/reader/exprstate.hpp +++ b/xo-reader/include/xo/reader/exprstate.hpp @@ -7,6 +7,7 @@ #include "xo/expression/Expression.hpp" #include "xo/tokenizer/token.hpp" +#include "xo/indentlog/print/ppdetail_atomic.hpp" #include //#include @@ -145,6 +146,9 @@ namespace xo { /** print human-readable representation on @p os **/ virtual void print(std::ostream & os) const; + /** pretty-print using @p ppii **/ + virtual bool pretty_print(const print::ppindentinfo & ppii) const; + // ----- input methods ----- /** handle incoming 'def' token **/ diff --git a/xo-reader/include/xo/reader/if_else_xs.hpp b/xo-reader/include/xo/reader/if_else_xs.hpp index ce7947d9..6086eac0 100644 --- a/xo-reader/include/xo/reader/if_else_xs.hpp +++ b/xo-reader/include/xo/reader/if_else_xs.hpp @@ -91,7 +91,10 @@ namespace xo { }; } /*namespace scm*/ + + namespace print { + PPDETAIL_ATOMIC(xo::scm::ifexprstatetype); + } } /*namespace xo*/ - -/** end if_else_xs.hpp **/ +/* end if_else_xs.hpp */ diff --git a/xo-reader/include/xo/reader/lambda_xs.hpp b/xo-reader/include/xo/reader/lambda_xs.hpp index 0832add2..2eb39e2a 100644 --- a/xo-reader/include/xo/reader/lambda_xs.hpp +++ b/xo-reader/include/xo/reader/lambda_xs.hpp @@ -83,6 +83,7 @@ namespace xo { parserstatemachine * p_psm) override; virtual void print(std::ostream & os) const override; + virtual bool pretty_print(const print::ppindentinfo & ppii) const override; private: static std::unique_ptr make(); @@ -105,6 +106,10 @@ namespace xo { }; } /*namespace scm*/ + + namespace print { + PPDETAIL_ATOMIC(xo::scm::lambdastatetype); + } } /*namespace xo*/ diff --git a/xo-reader/include/xo/reader/pretty_envframestack.hpp b/xo-reader/include/xo/reader/pretty_envframestack.hpp index be890b59..842368fa 100644 --- a/xo-reader/include/xo/reader/pretty_envframestack.hpp +++ b/xo-reader/include/xo/reader/pretty_envframestack.hpp @@ -10,6 +10,13 @@ namespace xo { namespace print { + template <> + struct ppdetail { + static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::envframestack * p) { + return p->pretty_print(ppii); + } + }; + template <> struct ppdetail { static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::envframestack * p) { diff --git a/xo-reader/include/xo/reader/pretty_exprstatestack.hpp b/xo-reader/include/xo/reader/pretty_exprstatestack.hpp index 4c2b04f1..bc8f6606 100644 --- a/xo-reader/include/xo/reader/pretty_exprstatestack.hpp +++ b/xo-reader/include/xo/reader/pretty_exprstatestack.hpp @@ -16,5 +16,19 @@ namespace xo { return p->pretty_print(ppii); } }; + + template <> + struct ppdetail { + static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::exprstatestack * p) { + return p->pretty_print(ppii); + } + }; + + template <> + struct ppdetail { + static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::exprstate * p) { + return p->pretty_print(ppii); + } + }; } /*namespace print*/ } /*namespace xo*/ diff --git a/xo-reader/include/xo/reader/progress_xs.hpp b/xo-reader/include/xo/reader/progress_xs.hpp index 8713a9f0..ce77966d 100644 --- a/xo-reader/include/xo/reader/progress_xs.hpp +++ b/xo-reader/include/xo/reader/progress_xs.hpp @@ -6,6 +6,7 @@ #pragma once #include "exprstate.hpp" +#include "xo/reflect/TypeDescr.hpp" #include //#include @@ -90,6 +91,12 @@ namespace xo { bool admits_f64() const; + void apply_type_error(const char * self_name, + optype op, + bp expr1, + bp expr2, + parserstatemachine * p_psm) const; + virtual const char * get_expect_str() const override; virtual void on_expr(bp expr, @@ -113,6 +120,8 @@ namespace xo { parserstatemachine * p_psm) override; virtual void on_rightparen_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; virtual void on_then_token(const token_type & tk, parserstatemachine * p_psm) override; virtual void on_else_token(const token_type & tk, @@ -132,6 +141,7 @@ namespace xo { parserstatemachine * p_psm) override; virtual void print(std::ostream & os) const override; + virtual bool pretty_print(const print::ppindentinfo & ppii) const override; private: static std::unique_ptr make(rp valex, diff --git a/xo-reader/src/reader/define_xs.cpp b/xo-reader/src/reader/define_xs.cpp index 2403359a..d5cf23df 100644 --- a/xo-reader/src/reader/define_xs.cpp +++ b/xo-reader/src/reader/define_xs.cpp @@ -351,11 +351,17 @@ namespace xo { void define_xs::print(std::ostream & os) const { os << ""; } + + bool + define_xs::pretty_print(const xo::print::ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, "define_xs", + refrtag("defxs_type", defxs_type_)); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-reader/src/reader/exprseq_xs.cpp b/xo-reader/src/reader/exprseq_xs.cpp index 03314cd7..77c5e696 100644 --- a/xo-reader/src/reader/exprseq_xs.cpp +++ b/xo-reader/src/reader/exprseq_xs.cpp @@ -152,8 +152,7 @@ namespace xo { { using xo::ast::Constant; - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); constexpr const char * c_self_name = "exprseq_xs::on_i64_token"; @@ -173,6 +172,32 @@ namespace xo { } } + void + exprseq_xs::on_f64_token(const token_type & tk, + parserstatemachine * p_psm) + { + using xo::ast::Constant; + + scope log(XO_DEBUG(p_psm->debug_flag())); + + constexpr const char * c_self_name = "exprseq_xs::on_i64_token"; + + if (xseqtype_ == exprseqtype::toplevel_interactive) + { + progress_xs::start(Constant::make(tk.f64_value()), p_psm); + } else { + /* policy: don't allow literals as toplevel expressions + * unless interactive session. + */ + const char * exp = get_expect_str(); + + this->illegal_input_on_token(c_self_name, + tk, + exp, + p_psm); + } + } + void exprseq_xs::on_typedescr(TypeDescr /*td*/, parserstatemachine * /*p_psm*/) diff --git a/xo-reader/src/reader/exprstate.cpp b/xo-reader/src/reader/exprstate.cpp index e4311bd8..a9642063 100644 --- a/xo-reader/src/reader/exprstate.cpp +++ b/xo-reader/src/reader/exprstate.cpp @@ -21,6 +21,7 @@ namespace xo { //using xo::ast::Constant; //using xo::reflect::Reflect; using xo::reflect::TypeDescr; + using xo::print::ppindentinfo; namespace scm { const char * @@ -552,6 +553,13 @@ namespace xo { os << ">"; } + bool + exprstate::pretty_print(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, "exprstate", + refrtag("type", exs_type_)); + } + void exprstate::illegal_input_error(const char * self_name, const token_type & tk) const diff --git a/xo-reader/src/reader/if_else_xs.cpp b/xo-reader/src/reader/if_else_xs.cpp index f94e6e9d..2fada024 100644 --- a/xo-reader/src/reader/if_else_xs.cpp +++ b/xo-reader/src/reader/if_else_xs.cpp @@ -7,6 +7,7 @@ //#include "exprstatestack.hpp" #include "parserstatemachine.hpp" #include "expect_expr_xs.hpp" +#include "xo/indentlog/print/ppdetail_atomic.hpp" namespace xo { namespace scm { diff --git a/xo-reader/src/reader/lambda_xs.cpp b/xo-reader/src/reader/lambda_xs.cpp index 61144b54..bbbd19b8 100644 --- a/xo-reader/src/reader/lambda_xs.cpp +++ b/xo-reader/src/reader/lambda_xs.cpp @@ -212,6 +212,13 @@ namespace xo { << ">"; } + bool + lambda_xs::pretty_print(const xo::print::ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, "lambda_xs", + refrtag("lmxs_type", lmxs_type_)); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-reader/src/reader/progress_xs.cpp b/xo-reader/src/reader/progress_xs.cpp index a09b8c26..150e092e 100644 --- a/xo-reader/src/reader/progress_xs.cpp +++ b/xo-reader/src/reader/progress_xs.cpp @@ -124,6 +124,21 @@ namespace xo { this->illegal_input_on_token(c_self_name, tk, exp, p_psm); } + void + progress_xs::apply_type_error(const char * self_name, + optype op, + bp expr1, + bp expr2, + parserstatemachine * p_psm) const + { + std::string errmsg = tostr("incompatible argument types T1,T2 to op", + xtag("op", op), + xtag("T1", expr1->valuetype()), + xtag("T2", expr2->valuetype())); + + p_psm->on_error(self_name, std::move(errmsg)); + } + rp progress_xs::assemble_expr(parserstatemachine * p_psm) { /* need to defer building Apply incase expr followed by higher-precedence operator: @@ -177,16 +192,56 @@ namespace xo { assert(false); case optype::op_add: - return Apply::make_add2_f64(lhs_, rhs_); - + // 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: - return Apply::make_sub2_f64(lhs_, rhs_); + // 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: - return Apply::make_mul2_f64(lhs_, rhs_); + // 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: - return Apply::make_div2_f64(lhs_, rhs_); + // 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; case optype::n_optype: /* unreachable */ @@ -250,9 +305,11 @@ namespace xo { rp expr2 = this->assemble_expr(p_psm); - std::unique_ptr self = p_psm->pop_exprstate(); + if (expr2) { + std::unique_ptr self = p_psm->pop_exprstate(); - p_psm->on_expr_with_semicolon(expr2); + p_psm->on_expr_with_semicolon(expr2); + } } void @@ -438,6 +495,27 @@ namespace xo { */ } + void + progress_xs::on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + rp expr = this->assemble_expr(p_psm); + + log && log(xtag("assembled-expr", expr)); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr(expr); + p_psm->on_rightbrace_token(tk); + + /* control here on input like: + * + * { n * n } + */ + } + namespace { optype tk2op(const tokentype & tktype) { @@ -599,6 +677,27 @@ namespace xo { os << ">"; } + bool + progress_xs::pretty_print(const xo::print::ppindentinfo & ppii) const + { + if (ppii.upto()) { + return (ppii.pps()->print_upto("print_upto(refrtag("lhs", lhs_)) : true) + && (op_type_ != optype::invalid ? ppii.pps()->print_upto(refrtag("op", op_type_)) : true) + && (rhs_ ? ppii.pps()->print_upto(refrtag("rhs", rhs_)) : true) + && ppii.pps()->print_upto(">")); + } else { + ppii.pps()->write("pretty(refrtag("lhs", lhs_)); + if (op_type_ != optype::invalid) + ppii.pps()->pretty(refrtag("op", op_type_)); + if (rhs_) + ppii.pps()->pretty(refrtag("rhs", rhs_)); + ppii.pps()->write(">"); + return false; + } + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-reflect/include/xo/reflect/TypeDescr.hpp b/xo-reflect/include/xo/reflect/TypeDescr.hpp index 57deb81d..8896ed3a 100644 --- a/xo-reflect/include/xo/reflect/TypeDescr.hpp +++ b/xo-reflect/include/xo/reflect/TypeDescr.hpp @@ -240,13 +240,13 @@ namespace xo { TypeDescrExtra * tdextra() const { return tdextra_.get(); } Metatype metatype() const { return tdextra_->metatype(); } - /* true iff the type represented by *this is the same as the type - * represented by T. + /** true iff the type represented by _c *this is the same as the type + * represented by @tparam T * - * Warning: comparing typeinfo address can give false negatives. - * suspect this is caused by problems coalescing linker symbols - * in the clang toolchain. - */ + * Warning: comparing typeinfo address can give false negatives. + * suspect this is caused by problems coalescing linker symbols + * in the clang toolchain. + **/ template [[deprecated]] bool is_native() const { @@ -317,6 +317,10 @@ namespace xo { } } /*recover_native2*/ + bool is_i128() const; + bool is_i64() const; + bool is_f64() const; + bool is_pointer() const { return this->tdextra_->is_pointer(); } bool is_vector() const { return this->tdextra_->is_vector(); } bool is_struct() const { return this->tdextra_->is_struct(); } diff --git a/xo-reflect/src/reflect/TypeDescr.cpp b/xo-reflect/src/reflect/TypeDescr.cpp index 4d048015..8b40678f 100644 --- a/xo-reflect/src/reflect/TypeDescr.cpp +++ b/xo-reflect/src/reflect/TypeDescr.cpp @@ -254,6 +254,22 @@ namespace xo { { } + bool + TypeDescrBase::is_i64() const + { + static_assert(sizeof(long long) == 8); + + return Reflect::is_native(this); + } + + bool + TypeDescrBase::is_f64() const + { + static_assert(sizeof(double) == 8); + + return Reflect::is_native(this); + } + TaggedPtr TypeDescrBase::most_derived_self_tp(void * object) const { @@ -311,6 +327,11 @@ namespace xo { #endif TypeDescrTable::TypeDescrTable() { + /* want long == i64 */ + static_assert(sizeof(long) == 8); + /* want double == f64 */ + static_assert(sizeof(double) == 8); + Reflect::require(); Reflect::require(); Reflect::require();