diff --git a/xo-expression2/CMakeLists.txt b/xo-expression2/CMakeLists.txt index 52e9d380..869f891d 100644 --- a/xo-expression2/CMakeLists.txt +++ b/xo-expression2/CMakeLists.txt @@ -124,6 +124,32 @@ xo_add_genfacetimpl( # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-expression-applyexpr + FACET_PKG xo_expression2 + FACET Expression + REPR ApplyExpr + INPUT idl/IExpression_DApplyExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail + OUTPUT_CPP_DIR src/expression2 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-applyexpr + FACET_PKG xo_printable2 + FACET Printable + REPR ApplyExpr + INPUT idl/IPrintable_DApplyExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail + OUTPUT_CPP_DIR src/expression2 +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-expression2-facetimpl-gcobject-uniquestring diff --git a/xo-expression2/idl/IExpression_DApplyExpr.json5 b/xo-expression2/idl/IExpression_DApplyExpr.json5 new file mode 100644 index 00000000..6814547c --- /dev/null +++ b/xo-expression2/idl/IExpression_DApplyExpr.json5 @@ -0,0 +1,12 @@ +{ + mode: "implementation", + includes: [ "\"Expression.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Expression.json5", + brief: "provide AExpression interface for DApplyExpr state", + using_doxygen: true, + repr: "DApplyExpr", + doc: ["doc for IExpression+DApplyExpr" ], +} diff --git a/xo-expression2/idl/IPrintable_DApplyExpr.json5 b/xo-expression2/idl/IPrintable_DApplyExpr.json5 new file mode 100644 index 00000000..fe743b0b --- /dev/null +++ b/xo-expression2/idl/IPrintable_DApplyExpr.json5 @@ -0,0 +1,13 @@ +{ + mode: "implementation", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DApplyExpr", + using_doxygen: true, + repr: "DApplyExpr", + doc: [ "implement APrintable for DApplyExpr" ], +} diff --git a/xo-expression2/include/xo/expression2/DApplyExpr.hpp b/xo-expression2/include/xo/expression2/DApplyExpr.hpp index 882cf5cd..8502c62a 100644 --- a/xo-expression2/include/xo/expression2/DApplyExpr.hpp +++ b/xo-expression2/include/xo/expression2/DApplyExpr.hpp @@ -20,18 +20,55 @@ namespace xo { **/ class DApplyExpr { public: + using AAllocator = xo::mm::AAllocator; using TypeDescr = xo::reflect::TypeDescr; using ppindentinfo = xo::print::ppindentinfo; - using size_type = std::size_t; + using size_type = std::uint32_t; public: + /** @defgroup scm-applyexpr-constructors **/ + ///@{ + + /** construct empty instance, but with argument expressions empty **/ + DApplyExpr(TypeRef typeref, + obj fn_expr, + size_type n_args); + + /** create apply for function with 2 arguments **/ + static obj make2(obj mm, + TypeRef typeref, + obj fn_expr, + obj arg1, + obj arg2); + + /** create apply for function with 2 arguments **/ + static DApplyExpr * _make2(obj mm, + TypeRef typeref, + obj fn_expr, + obj arg1, + obj arg2); + + /** scaffold incomplete instance. + * apply-expr using memory from @p mm. + * will construct instance with space for @p n_args arguments + * but expressions left empty. + * use @ref assign_arg for all arguments to complete. + **/ + static DApplyExpr * scaffold(obj mm, + TypeRef typeref, + obj fn_expr, + size_type n_args); + void assign_arg(size_type i_arg, obj expr); + + ///@} + /** @defgroup scm-applyexpr-access-methods **/ + ///@{ obj fn() const noexcept { return fn_; } - const DArray * args() const noexcept { return args_; } - - size_type n_arg() const noexcept { return args_->size(); } + size_type n_args() const noexcept { return n_args_; } obj arg(size_type i) const; + ///@} /** @defgroup scm-applyexpr-expression-facet **/ ///@{ @@ -40,6 +77,12 @@ namespace xo { TypeDescr valuetype() const noexcept { return typeref_.td(); } void assign_valuetype(TypeDescr td) noexcept; + ///@} + /** @defgroup scm-applyexpr-gcobject-facet **/ + ///@{ + + // shallow_copy() etc. + ///@} /** @defgroup scm-applyexpr-printable-facet **/ ///@{ @@ -55,8 +98,10 @@ namespace xo { TypeRef typeref_; /** expression for function/procedure to invoke **/ obj fn_; - /** expression for each argument vector **/ - const DArray * args_; + /** number of arguments (not counting @ref fn_ **/ + size_type n_args_ = 0; + /** args_[i] is expression for i'th argument to @ref fn_ **/ + obj args_[]; }; } } diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DApplyExpr.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DApplyExpr.hpp new file mode 100644 index 00000000..c8952199 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DApplyExpr.hpp @@ -0,0 +1,66 @@ +/** @file IExpression_DApplyExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DApplyExpr.json5] + **/ + +#pragma once + +#include "Expression.hpp" +#include "Expression.hpp" +#include "DApplyExpr.hpp" + +namespace xo { namespace scm { class IExpression_DApplyExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IExpression_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IExpression_DApplyExpr + **/ + class IExpression_DApplyExpr { + public: + /** @defgroup scm-expression-dapplyexpr-type-traits **/ + ///@{ + using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; + ///@} + /** @defgroup scm-expression-dapplyexpr-methods **/ + ///@{ + // const methods + /** expression type (constant | apply | ..) **/ + static exprtype extype(const DApplyExpr & self) noexcept; + /** placeholder for type giving possible values for this expression **/ + static TypeRef typeref(const DApplyExpr & self) noexcept; + /** type giving possible values for this expression. Maybe null before typecheck **/ + static TypeDescr valuetype(const DApplyExpr & self) noexcept; + + // non-const methods + /** assing to valuetype member. Useful when scaffolding expressions **/ + static void assign_valuetype(DApplyExpr & self, TypeDescr td) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DApplyExpr.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DApplyExpr.hpp new file mode 100644 index 00000000..c05e87e2 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DApplyExpr.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DApplyExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DApplyExpr.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DApplyExpr.hpp" + +namespace xo { namespace scm { class IPrintable_DApplyExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DApplyExpr + **/ + class IPrintable_DApplyExpr { + public: + /** @defgroup scm-printable-dapplyexpr-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dapplyexpr-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DApplyExpr & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/src/expression2/CMakeLists.txt b/xo-expression2/src/expression2/CMakeLists.txt index 9dea6457..b8be9468 100644 --- a/xo-expression2/src/expression2/CMakeLists.txt +++ b/xo-expression2/src/expression2/CMakeLists.txt @@ -22,6 +22,9 @@ set(SELF_SRCS IExpression_DDefineExpr.cpp IPrintable_DDefineExpr.cpp + IExpression_DApplyExpr.cpp + IPrintable_DApplyExpr.cpp + DLocalSymtab.cpp DGlobalSymtab.cpp diff --git a/xo-expression2/src/expression2/DApplyExpr.cpp b/xo-expression2/src/expression2/DApplyExpr.cpp index 0c0546f3..ce5e1951 100644 --- a/xo-expression2/src/expression2/DApplyExpr.cpp +++ b/xo-expression2/src/expression2/DApplyExpr.cpp @@ -11,30 +11,62 @@ namespace xo { using xo::print::APrintable; using xo::facet::FacetRegistry; + using xo::reflect::typeseq; using xo::mm::AGCObject; namespace scm { + /* incomplete! */ + DApplyExpr::DApplyExpr(TypeRef typeref, + obj fn_expr, + size_type n_args) : typeref_{typeref}, + fn_{fn_expr}, + n_args_{n_args} + {} + + DApplyExpr * + DApplyExpr::scaffold(obj mm, + TypeRef typeref, + obj fn_expr, + size_type n_args) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DApplyExpr) + (n_args * sizeof(obj))); + + DApplyExpr * result = new (mem) DApplyExpr(typeref, + fn_expr, + n_args); + + return result; + } + + void + DApplyExpr::assign_arg(size_type i_arg, + obj expr) + { + if (i_arg < n_args_) { + this->args_[i_arg] = expr; + } else { + assert(false); + + throw std::runtime_error(tostr("assign out-of-range argument i_arg where [0..n_args) expected", + xtag("i_arg", i_arg), + xtag("expr", expr), + xtag("n_args", n_args_))); + + } + } + obj DApplyExpr::arg(size_type i) const { - if (i >= args_->size()) [[unlikely]] { + if (i >= n_args_) [[unlikely]] { throw std::runtime_error(tostr("attempt to fetch argument i where [0..n) expected", xtag("i", i), - xtag("n", args_->size()), + xtag("n", n_args_), xtag("src", "DApplyExpr::arg"))); } - obj arg_i = args_->at(i); - - auto expr_i = FacetRegistry::instance().variant(arg_i); - - if (!expr_i) [[unlikely]] { - throw std::runtime_error(tostr("expected expression interface on argument i", - xtag("i", i), - xtag("arg[i]", arg_i))); - } - - return expr_i; + return args_[i]; } void @@ -60,9 +92,9 @@ namespace xo { return false; } - for (size_t i_arg = 0, n_arg = this->n_arg(); i_arg < n_arg; ++i_arg) { + for (size_t i_arg = 0; i_arg < n_args_; ++i_arg) { obj arg_i - = FacetRegistry::instance().variant(this->arg(i_arg)); + = FacetRegistry::instance().variant(args_[i_arg]); if (!pps->print_upto(refrtag(concat("arg", 1+i_arg), arg_i))) return false; @@ -78,13 +110,14 @@ namespace xo { pps->newline_indent(ppii.ci1()); pps->pretty(refrtag("fn", fn)); - for (size_t i_arg = 0, n_arg = this->n_arg(); i_arg < n_arg; ++i_arg) { + for (size_t i_arg = 0; i_arg < n_args_; ++i_arg) { obj arg_i - = FacetRegistry::instance().variant(fn_); + = FacetRegistry::instance().variant(args_[i_arg]); pps->newline_indent(ppii.ci1()); pps->pretty(refrtag(concat("arg", 1+i_arg), arg_i)); } + return false; } } diff --git a/xo-expression2/src/expression2/IExpression_DApplyExpr.cpp b/xo-expression2/src/expression2/IExpression_DApplyExpr.cpp new file mode 100644 index 00000000..2098e050 --- /dev/null +++ b/xo-expression2/src/expression2/IExpression_DApplyExpr.cpp @@ -0,0 +1,45 @@ +/** @file IExpression_DApplyExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DApplyExpr.json5] +**/ + +#include "detail/IExpression_DApplyExpr.hpp" + +namespace xo { + namespace scm { + auto + IExpression_DApplyExpr::extype(const DApplyExpr & self) noexcept -> exprtype + { + return self.extype(); + } + + auto + IExpression_DApplyExpr::typeref(const DApplyExpr & self) noexcept -> TypeRef + { + return self.typeref(); + } + + auto + IExpression_DApplyExpr::valuetype(const DApplyExpr & self) noexcept -> TypeDescr + { + return self.valuetype(); + } + + auto + IExpression_DApplyExpr::assign_valuetype(DApplyExpr & self, TypeDescr td) noexcept -> void + { + self.assign_valuetype(td); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IExpression_DApplyExpr.cpp */ \ No newline at end of file diff --git a/xo-expression2/src/expression2/IPrintable_DApplyExpr.cpp b/xo-expression2/src/expression2/IPrintable_DApplyExpr.cpp new file mode 100644 index 00000000..4f4a50d3 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DApplyExpr.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DApplyExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DApplyExpr.json5] +**/ + +#include "detail/IPrintable_DApplyExpr.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DApplyExpr::pretty(const DApplyExpr & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DApplyExpr.cpp */ \ No newline at end of file diff --git a/xo-expression2/src/expression2/expression2_register_facets.cpp b/xo-expression2/src/expression2/expression2_register_facets.cpp index 1854f3eb..fc6ef3c1 100644 --- a/xo-expression2/src/expression2/expression2_register_facets.cpp +++ b/xo-expression2/src/expression2/expression2_register_facets.cpp @@ -17,6 +17,9 @@ #include #include +#include +#include + #include #include #include @@ -40,7 +43,8 @@ namespace xo { // Expression // +- Constant // +- Variable - // \- DefineExpr + // +- DefineExpr + // \- ApplyExpr FacetRegistry::register_impl(); FacetRegistry::register_impl(); @@ -51,10 +55,14 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + log && log(xtag("DUniqueString.tseq", typeseq::id())); log && log(xtag("DDefineExpr.tseq", typeseq::id())); log && log(xtag("DVariable.tseq", typeseq::id())); log && log(xtag("DConstant.tseq", typeseq::id())); + log && log(xtag("DApplyExpr.tseq", typeseq::id())); log && log(xtag("AExpression.tqseq", typeseq::id())); diff --git a/xo-procedure2/idl/Procedure.json5 b/xo-procedure2/idl/Procedure.json5 index f26a4e56..91c8bdf3 100644 --- a/xo-procedure2/idl/Procedure.json5 +++ b/xo-procedure2/idl/Procedure.json5 @@ -1,3 +1,7 @@ +// can regenerate downstream .*pp files with either: +// cmake --build -- xo-procedure2-facet-procedure +// cmake --build -- xo-procedure2-genfacet-all + { mode: "facet", // includes in ASyntaxStateMachine.hpp @@ -56,6 +60,7 @@ doc: ["invoke procedure; assume arguments satisfy type system" ], return_type: "obj", args: [ + {type: "obj", name: "rcx"}, {type: "const DArray *", name: "args"}, ] } diff --git a/xo-procedure2/include/xo/procedure2/DPrimitive.hpp b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp index cf913a15..afd2ada2 100644 --- a/xo-procedure2/include/xo/procedure2/DPrimitive.hpp +++ b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp @@ -19,43 +19,49 @@ namespace xo { namespace scm { - /** @brief Extract return type and argument types from a function type. - * - * Primary template (undefined) - specializations handle specific cases + namespace detail { + /** @brief Extract return type and argument types from a function type. + * + * Primary template (undefined) - specializations handle specific cases + **/ + template + struct PmFnTraits; + + /** specialization for function pointers **/ + template + struct PmFnTraits rcx, Args...)> { + /** function return type **/ + using return_type = R; + /** tuple type for function arguments (except for runtime context) **/ + using args_tuple = std::tuple; + /** number of arguments (except for runtime context) **/ + static constexpr std::size_t n_args = sizeof...(Args); + + /** arg_type is the type of the i'th argument to Fn. + * (starting from argument after runtime context) + **/ + template + using arg_type = std::tuple_element_t; + }; + + /** specialization for function references **/ + template + struct PmFnTraits, Args...)> : PmFnTraits, Args...)> {}; + + /** specialization for plain function types **/ + template + struct PmFnTraits, Args...)> : PmFnTraits, Args...)> {}; + } + + /** @brief Schematika primitive with fixed number of arguments **/ - template - struct FnTraits; - - /** specialization for function pointers **/ - template - struct FnTraits { - /** function return type **/ - using return_type = R; - /** tuple type for function arguments **/ - using args_tuple = std::tuple; - /** number of arguments **/ - static constexpr std::size_t n_args = sizeof...(Args); - - /** arg_type is the type of the i'th argument to Fn **/ - template - using arg_type = std::tuple_element_t; - }; - - /** specialization for function references **/ - template - struct FnTraits : FnTraits {}; - - /** specialization for plain function types **/ - template - struct FnTraits : FnTraits {}; - template class Primitive { public: using AAllocator = xo::mm::AAllocator; using AGCObject = xo::mm::AGCObject; using DArray = xo::scm::DArray; - using Traits = FnTraits; + using Traits = detail::PmFnTraits; public: Primitive(std::string_view name, Fn fn) : name_{name}, fn_{fn} {} @@ -63,14 +69,15 @@ namespace xo { bool is_nary() const noexcept { return false; } static constexpr std::int32_t n_args() noexcept { return Traits::n_args; } - obj apply_nocheck(const DArray * args) { - return _apply_nocheck(args, + obj apply_nocheck(obj rcx, const DArray * args) { + return _apply_nocheck(rcx, args, std::make_index_sequence{}); } private: template - obj _apply_nocheck(const DArray * args, + obj _apply_nocheck(obj rcx, + const DArray * args, std::index_sequence) { using xo::facet::FacetRegistry; @@ -80,12 +87,11 @@ namespace xo { assert(args); assert(args->size() > 0); - obj rcx - = FacetRegistry::instance().variant(args->at(0)); obj mm = rcx.allocator(); R result - = fn_(GCObjectConversion>::from_gco(mm, args->at(Is))... ); + = fn_(rcx, + GCObjectConversion>::from_gco(mm, args->at(Is))... ); return GCObjectConversion::to_gco(mm, result); } diff --git a/xo-procedure2/include/xo/procedure2/DPrimitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/DPrimitive_gco_2_gco_gco.hpp index 24ad3b41..78dd26b9 100644 --- a/xo-procedure2/include/xo/procedure2/DPrimitive_gco_2_gco_gco.hpp +++ b/xo-procedure2/include/xo/procedure2/DPrimitive_gco_2_gco_gco.hpp @@ -1,3 +1,8 @@ +/** @file DPrimitive_gco_2_gco_gco.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + #pragma once #include @@ -13,3 +18,5 @@ namespace xo { obj)>; } } + +/* end DPrimitive_gco_2_gco_gco.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/Procedure.hpp b/xo-procedure2/include/xo/procedure2/Procedure.hpp index 8b2cd91a..784608ed 100644 --- a/xo-procedure2/include/xo/procedure2/Procedure.hpp +++ b/xo-procedure2/include/xo/procedure2/Procedure.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/Procedure.json5] * 2. jinja2 template for facet .hpp file: diff --git a/xo-procedure2/include/xo/procedure2/RuntimeContext.hpp b/xo-procedure2/include/xo/procedure2/RuntimeContext.hpp index 2e8300ed..3241451b 100644 --- a/xo-procedure2/include/xo/procedure2/RuntimeContext.hpp +++ b/xo-procedure2/include/xo/procedure2/RuntimeContext.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/RuntimeContext.json5] * 2. jinja2 template for facet .hpp file: diff --git a/xo-procedure2/include/xo/procedure2/detail/AProcedure.hpp b/xo-procedure2/include/xo/procedure2/detail/AProcedure.hpp index 1be5e0d1..63a4da9b 100644 --- a/xo-procedure2/include/xo/procedure2/detail/AProcedure.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/AProcedure.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/Procedure.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -56,7 +56,7 @@ public: // nonconst methods /** invoke procedure; assume arguments satisfy type system **/ - virtual obj apply_nocheck(Opaque data, const DArray * args) = 0; + virtual obj apply_nocheck(Opaque data, obj rcx, const DArray * args) = 0; ///@} }; /*AProcedure*/ diff --git a/xo-procedure2/include/xo/procedure2/detail/ARuntimeContext.hpp b/xo-procedure2/include/xo/procedure2/detail/ARuntimeContext.hpp index 42030d9d..4e96bc8f 100644 --- a/xo-procedure2/include/xo/procedure2/detail/ARuntimeContext.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/ARuntimeContext.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/RuntimeContext.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-procedure2/include/xo/procedure2/detail/IProcedure_Any.hpp b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Any.hpp index 3f66fcd5..5d711d4c 100644 --- a/xo-procedure2/include/xo/procedure2/detail/IProcedure_Any.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Any.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/Procedure.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -60,7 +60,7 @@ namespace scm { [[noreturn]] std::int32_t n_args(Copaque) const noexcept override { _fatal(); } // nonconst methods - [[noreturn]] obj apply_nocheck(Opaque, const DArray *) override; + [[noreturn]] obj apply_nocheck(Opaque, obj, const DArray *) override; ///@} diff --git a/xo-procedure2/include/xo/procedure2/detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp index 4b4351dd..11f2cd60 100644 --- a/xo-procedure2/include/xo/procedure2/detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IProcedure_DPrimitive_gco_2_gco_gco.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -57,7 +57,7 @@ namespace xo { // non-const methods /** invoke procedure; assume arguments satisfy type system **/ - static obj apply_nocheck(DPrimitive_gco_2_gco_gco & self, const DArray * args); + static obj apply_nocheck(DPrimitive_gco_2_gco_gco & self, obj rcx, const DArray * args); ///@} }; diff --git a/xo-procedure2/include/xo/procedure2/detail/IProcedure_Xfer.hpp b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Xfer.hpp index adf4995d..4f84652e 100644 --- a/xo-procedure2/include/xo/procedure2/detail/IProcedure_Xfer.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Xfer.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/Procedure.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -50,8 +50,8 @@ namespace scm { } // non-const methods - obj apply_nocheck(Opaque data, const DArray * args) override { - return I::apply_nocheck(_dcast(data), args); + obj apply_nocheck(Opaque data, obj rcx, const DArray * args) override { + return I::apply_nocheck(_dcast(data), rcx, args); } ///@} diff --git a/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Any.hpp b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Any.hpp index 419d45cc..1e5f97c0 100644 --- a/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Any.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Any.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/RuntimeContext.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Xfer.hpp b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Xfer.hpp index e9f5512e..cd71b73e 100644 --- a/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Xfer.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Xfer.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/RuntimeContext.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-procedure2/include/xo/procedure2/detail/RProcedure.hpp b/xo-procedure2/include/xo/procedure2/detail/RProcedure.hpp index 9fff0c6c..93599ae3 100644 --- a/xo-procedure2/include/xo/procedure2/detail/RProcedure.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/RProcedure.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/Procedure.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -56,8 +56,8 @@ public: } // non-const methods (still const in router!) - obj apply_nocheck(const DArray * args) { - return O::iface()->apply_nocheck(O::data(), args); + obj apply_nocheck(obj rcx, const DArray * args) { + return O::iface()->apply_nocheck(O::data(), rcx, args); } ///@} diff --git a/xo-procedure2/include/xo/procedure2/detail/RRuntimeContext.hpp b/xo-procedure2/include/xo/procedure2/detail/RRuntimeContext.hpp index 06b093de..b06227c8 100644 --- a/xo-procedure2/include/xo/procedure2/detail/RRuntimeContext.hpp +++ b/xo-procedure2/include/xo/procedure2/detail/RRuntimeContext.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/RuntimeContext.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-procedure2/src/procedure2/IProcedure_Any.cpp b/xo-procedure2/src/procedure2/IProcedure_Any.cpp index 79b3b778..d28d98ee 100644 --- a/xo-procedure2/src/procedure2/IProcedure_Any.cpp +++ b/xo-procedure2/src/procedure2/IProcedure_Any.cpp @@ -35,7 +35,7 @@ IProcedure_Any::_valid // nonconst methods auto -IProcedure_Any::apply_nocheck(Opaque, const DArray *) -> obj +IProcedure_Any::apply_nocheck(Opaque, obj, const DArray *) -> obj { _fatal(); } diff --git a/xo-procedure2/src/procedure2/IProcedure_DPrimitive_gco_2_gco_gco.cpp b/xo-procedure2/src/procedure2/IProcedure_DPrimitive_gco_2_gco_gco.cpp index 5266477c..67e73c97 100644 --- a/xo-procedure2/src/procedure2/IProcedure_DPrimitive_gco_2_gco_gco.cpp +++ b/xo-procedure2/src/procedure2/IProcedure_DPrimitive_gco_2_gco_gco.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] * arguments: * --input [idl/IProcedure_DPrimitive_gco_2_gco_gco.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -28,9 +28,9 @@ namespace xo { } auto - IProcedure_DPrimitive_gco_2_gco_gco::apply_nocheck(DPrimitive_gco_2_gco_gco & self, const DArray * args) -> obj + IProcedure_DPrimitive_gco_2_gco_gco::apply_nocheck(DPrimitive_gco_2_gco_gco & self, obj rcx, const DArray * args) -> obj { - return self.apply_nocheck(args); + return self.apply_nocheck(rcx, args); } } /*namespace scm*/ diff --git a/xo-reader2/include/xo/reader2/DProgressSsm.hpp b/xo-reader2/include/xo/reader2/DProgressSsm.hpp index 7258731c..31b3a55d 100644 --- a/xo-reader2/include/xo/reader2/DProgressSsm.hpp +++ b/xo-reader2/include/xo/reader2/DProgressSsm.hpp @@ -100,14 +100,12 @@ namespace xo { optype op); static void start(DArena & parser_mm, - obj valex, + obj lhs, ParserStateMachine * p_psm); - -#ifdef NOT_YET - static void start(rp valex, + static void start(DArena & parsermm, + obj lhs, optype optype, - parserstatemachine * p_psm); -#endif + ParserStateMachine * p_psm); syntaxstatetype ssm_type() const noexcept; @@ -147,6 +145,8 @@ namespace xo { ParserStateMachine * p_psm); void on_singleassign_token(const Token & tk, ParserStateMachine * p_psm); + void on_operator_token(const Token & tk, + ParserStateMachine * p_psm); void on_string_token(const Token & tk, ParserStateMachine * p_psm); void on_f64_token(const Token & tk, @@ -207,17 +207,6 @@ namespace xo { void print(std::ostream & os) const override; - - private: - /** assemble expression representing - * value of - * @code - * f(lhs_, rhs_) - * @endcode - * - * where f determined by @ref op_type_ - **/ - obj assemble_expr(ParserStateMachine * p_psm); #endif private: @@ -227,7 +216,14 @@ namespace xo { /** infix operator, if supplied **/ optype op_type_ = optype::invalid; - /** populate an expression here, following infix operator */ + /** populate an expression here, that follows an infix operator. + * + * Note this may not resolve immediately. + * Consider input + * 5 + 6 + * Need to know if following token is * + * before deciding if 6 belongs to addition 5 + 6 + **/ obj rhs_; }; } /*namespace scm*/ diff --git a/xo-reader2/src/reader2/DExpectExprSsm.cpp b/xo-reader2/src/reader2/DExpectExprSsm.cpp index fc5dbe08..49e95296 100644 --- a/xo-reader2/src/reader2/DExpectExprSsm.cpp +++ b/xo-reader2/src/reader2/DExpectExprSsm.cpp @@ -180,12 +180,11 @@ namespace xo { case tokentype::tk_in: case tokentype::tk_end: case tokentype::N: + p_psm->illegal_input_on_token("DExpectExprSsm::on_token", + tk, + this->get_expect_str()); break; } - - p_psm->illegal_input_on_token("DExpectExprSsm::on_token", - tk, - this->get_expect_str()); } void diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index 85f7b1d3..830dd30e 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -5,6 +5,15 @@ #include "DProgressSsm.hpp" #include "ssm/ISyntaxStateMachine_DProgressSsm.hpp" + +#include "DExpectExprSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectExprSsm.hpp" + +#ifdef NOT_YET +#include "DApplySsm.hpp" +#include "ssm/ISyntaxStateMachine_DApplySsm.hpp" +#endif + #include #include #include @@ -67,6 +76,7 @@ namespace xo { return "???"; } + /** higher-precedence operators bind before lower-preference operators **/ int precedence(optype x) { switch (x) { @@ -97,6 +107,40 @@ namespace xo { return 0; } + namespace { + optype + tk2op(const tokentype & tktype) { + switch (tktype) { + case tokentype::tk_assign: + return optype::op_assign; + case tokentype::tk_plus: + return optype::op_add; + case tokentype::tk_minus: + return optype::op_subtract; + case tokentype::tk_star: + return optype::op_multiply; + case tokentype::tk_slash: + return optype::op_divide; + case tokentype::tk_cmpeq: + return optype::op_equal; + case tokentype::tk_cmpne: + return optype::op_not_equal; + case tokentype::tk_leftangle: + return optype::op_less; + case tokentype::tk_lessequal: + return optype::op_less_equal; + case tokentype::tk_rightangle: + return optype::op_great; + case tokentype::tk_greatequal: + return optype::op_great_equal; + default: + assert(false); + return optype::invalid; + } + return optype::invalid; + } + } + DProgressSsm * DProgressSsm::make(DArena & mm, obj lhs, @@ -112,26 +156,26 @@ namespace xo { void DProgressSsm::start(DArena & parser_mm, - obj valex, + obj lhs, + optype op, ParserStateMachine * p_psm) { DProgressSsm * progress_ssm - = DProgressSsm::make(parser_mm, valex, optype::invalid); + = DProgressSsm::make(parser_mm, lhs, op); - obj ssm - = with_facet::mkobj(progress_ssm); + obj ssm(progress_ssm); p_psm->push_ssm(ssm); } -#ifdef NOT_YET void - progress_xs::start(rp valex, optype op, parserstatemachine * p_psm) { - p_psm->push_exprstate(progress_xs::make(valex, op)); + DProgressSsm::start(DArena & parser_mm, + obj lhs, + ParserStateMachine * p_psm) + { + start(parser_mm, lhs, optype::invalid, p_psm); } -#endif - DProgressSsm::DProgressSsm(obj valex, optype op) : lhs_{valex}, @@ -225,12 +269,11 @@ namespace xo { case tokentype::tk_plus: case tokentype::tk_minus: break; + case tokentype::tk_star: -#ifdef NOT_YET this->on_operator_token(tk, p_psm); return; -#endif - break; + case tokentype::tk_slash: case tokentype::tk_cmpeq: case tokentype::tk_cmpne: @@ -295,6 +338,75 @@ namespace xo { this->get_expect_str()); } + void + DProgressSsm::on_operator_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (op_type_ == optype::invalid) { + // tk is the operator this instance was waiting for + this->op_type_ = tk2op(tk.tk_type()); + + DExpectExprSsm::start(p_psm->parser_alloc(), p_psm); + return; + } else if (rhs_) { + optype op_type2 = tk2op(tk.tk_type()); + + /* already have {lhs_, op_type_, rhs_}, + * with incoming op_type2 operator decides whether to parse like + * (lhs_, op_type_, rhs_) op_type2 ... + * or + * (lhs_, op_type_, (rhs_ op_type2 ...)) + */ + + if (precedence(op_type_) >= precedence(op_type2)) { + /* associate to the left + * + * parse like + * a + b - ... (a + b) - ... + * a * b - ... (a * b) - ... + */ + + auto lhs2 = this->assemble_expr(p_psm); + + p_psm->pop_ssm(); + + DProgressSsm::start(p_psm->parser_alloc(), + lhs2, + op_type2, + p_psm); + return; + } else { + /* associate to the right + * + * parse like + * a + b * ... (a + (b * ...)) + */ + + p_psm->pop_ssm(); + + /* (a + ..) */ + DProgressSsm::start(p_psm->parser_alloc(), + lhs_, + op_type_, + p_psm); + DExpectExprSsm::start(p_psm->parser_alloc(), + p_psm); + /* (b * ..) */ + DProgressSsm::start(p_psm->parser_alloc(), + rhs_, + op_type2, + p_psm); + DExpectExprSsm::start(p_psm->parser_alloc(), + p_psm); + return; + } + } + + p_psm->illegal_input_on_token("DProgressSsm::on_operator_token", + tk, + this->get_expect_str()); + } + void DProgressSsm::on_string_token(const Token & tk, ParserStateMachine * p_psm) @@ -905,112 +1017,10 @@ namespace xo { * { n * n } */ } +#endif - namespace { - optype - tk2op(const tokentype & tktype) { - switch (tktype) { - case tokentype::tk_assign: - return optype::op_assign; - case tokentype::tk_plus: - return optype::op_add; - case tokentype::tk_minus: - return optype::op_subtract; - case tokentype::tk_star: - return optype::op_multiply; - case tokentype::tk_slash: - return optype::op_divide; - case tokentype::tk_cmpeq: - return optype::op_equal; - case tokentype::tk_cmpne: - return optype::op_not_equal; - case tokentype::tk_leftangle: - return optype::op_less; - case tokentype::tk_lessequal: - return optype::op_less_equal; - case tokentype::tk_rightangle: - return optype::op_great; - case tokentype::tk_greatequal: - return optype::op_great_equal; - default: - assert(false); - return optype::invalid; - } - return optype::invalid; - } - } - - void - progress_xs::on_operator_token(const token_type & tk, - parserstatemachine * p_psm) - { - scope log(XO_DEBUG(p_psm->debug_flag())); - - constexpr const char * c_self_name = "progress_xs::on_operator_token"; - - if (op_type_ == optype::invalid) { - this->op_type_ = tk2op(tk.tk_type()); - - /* infix operator must be followed by non-empty expression */ - expect_expr_xs::start(p_psm); - } else if (rhs_) { - /* already have complete expression stashed. - * behavior depends on operator precedence for tk with stored operator - * this->op_type_ - */ - optype op2 = tk2op(tk.tk_type()); - - if (precedence(op2) <= precedence(this->op_type_)) { - /* e.g. - * 6.2 * 4.9 + ... - * - * in stack: - * 1. progress_xs lhs=6.2, op=*, rhs=4.9 - * - * out stack - * 1. progress_xs lhs=apply(*,6.2,4.9), op=+ - */ - - /* 1. instantiate expression for *this */ - auto expr = this->assemble_expr(p_psm); - - /* 2. remove from stack */ - std::unique_ptr self = p_psm->pop_exprstate(); - - /* 3. replace with new progress_xs: */ - progress_xs::start(expr, op2, p_psm); - - /* infix operator must be followed by non-empty expression */ - expect_expr_xs::start(p_psm); - } else { - /* e.g. - * 6.2 + 4.9 * ... - * - * in stack: - * 1. progress_xs lhs=6.2, op=+, rhs=4.9 - * - * out stack: - * 1. progress_xs lhs=6.2, op=+ - * 2. expect_rhs_expression - * 3. progress_xs lhs=4.9, op=* - * 4. expect_rhs_expression - */ - - std::unique_ptr self = p_psm->pop_exprstate(); - - /* 1. replace with nested incomplete infix exprs */ - progress_xs::start(lhs_, op_type_, p_psm); - expect_expr_xs::start(p_psm); - progress_xs::start(rhs_, op2, p_psm); - expect_expr_xs::start(p_psm); - } - - } else { - throw std::runtime_error(tostr(c_self_name, - ": expected expression following operator", - xtag("tk", tk))); - } - } +#ifdef OBSOLETE + //void progress_xs::on_operator_token(const token_type & tk, parserstatemachine * p_psm) void progress_xs::on_bool_token(const token_type & tk, @@ -1163,7 +1173,25 @@ namespace xo { case optype::op_great_equal: case optype::op_add: case optype::op_subtract: + break; + case optype::op_multiply: +#ifdef NOT_YET + { + /* 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. + */ + + DApplyExpr::make2(); + } +#endif + + break; case optype::op_divide: // TODO: implement binary operator expression assembly break;