From c06df5ccb524f9a7783797042ae3e2bca6c8a493 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 --- include/xo/expression/Apply.hpp | 13 ++++ include/xo/expression/Primitive.hpp | 19 ++++++ include/xo/expression/llvmintrinsic.hpp | 10 +-- src/expression/Apply.cpp | 38 +++++++++++ src/expression/GlobalEnv.cpp | 1 + src/expression/Primitive.cpp | 88 +++++++++++++++++++++++++ 6 files changed, 165 insertions(+), 4 deletions(-) diff --git a/include/xo/expression/Apply.hpp b/include/xo/expression/Apply.hpp index a4eac339..aae28585 100644 --- a/include/xo/expression/Apply.hpp +++ b/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/include/xo/expression/Primitive.hpp b/include/xo/expression/Primitive.hpp index 29409209..cb940092 100644 --- a/include/xo/expression/Primitive.hpp +++ b/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/include/xo/expression/llvmintrinsic.hpp b/include/xo/expression/llvmintrinsic.hpp index b13bccac..ede8719a 100644 --- a/include/xo/expression/llvmintrinsic.hpp +++ b/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/src/expression/Apply.cpp b/src/expression/Apply.cpp index 220b5aa5..d3403784 100644 --- a/src/expression/Apply.cpp +++ b/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/src/expression/GlobalEnv.cpp b/src/expression/GlobalEnv.cpp index e9ec1acc..8ae06f69 100644 --- a/src/expression/GlobalEnv.cpp +++ b/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/src/expression/Primitive.cpp b/src/expression/Primitive.cpp index bc73ebd7..db44d820 100644 --- a/src/expression/Primitive.cpp +++ b/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 {