diff --git a/CMakeLists.txt b/CMakeLists.txt index 259c3f03..25d8cd0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,20 @@ xo_add_genfacetimpl( # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-procedure-closure + FACET_PKG xo_procedure2 + FACET Printable + REPR DClosure + INPUT idl/IProcedure_DClosure.json5 + OUTPUT_HPP_DIR include/xo/interpreter2 + OUTPUT_IMPL_SUBDIR detail + OUTPUT_CPP_DIR src/interpreter2 +) + +# ---------------------------------------------------------------- + xo_add_genfacet_all(xo-interpreter2-genfacet-all) # ---------------------------------------------------------------- diff --git a/idl/IProcedure_DClosure.json5 b/idl/IProcedure_DClosure.json5 new file mode 100644 index 00000000..d503f5c6 --- /dev/null +++ b/idl/IProcedure_DClosure.json5 @@ -0,0 +1,17 @@ +{ + mode: "implementation", + includes: [ + "", + "", + "", + "", + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Procedure.json5", + brief: "provide AProcedure interface for DClosure", + using_doxygen: true, + repr: "DClosure", + doc: [ "implement AProcedure for DClosure" ], +} diff --git a/include/xo/interpreter2/Closure.hpp b/include/xo/interpreter2/Closure.hpp new file mode 100644 index 00000000..f352e7f0 --- /dev/null +++ b/include/xo/interpreter2/Closure.hpp @@ -0,0 +1,11 @@ +/** @file Closure.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DClosure.hpp" +#include "detail/IProcedure_DClosure.hpp" + +/* end Closure.hpp */ diff --git a/include/xo/interpreter2/DClosure.hpp b/include/xo/interpreter2/DClosure.hpp index 09966038..bcf85c97 100644 --- a/include/xo/interpreter2/DClosure.hpp +++ b/include/xo/interpreter2/DClosure.hpp @@ -3,8 +3,11 @@ * @author Roland Conybeare, Feb 2026 **/ +#pragma once + #include "LocalEnv.hpp" #include +#include namespace xo { namespace scm { @@ -15,7 +18,10 @@ namespace xo { **/ class DClosure { public: + using ARuntimeContext = xo::scm::ARuntimeContext; using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; using size_type = std::int32_t; public: @@ -29,11 +35,35 @@ namespace xo { const DLambdaExpr * lm, const DLocalEnv * env); + /** @defgroup scm-closure-general-methods **/ + ///@{ + + const DLambdaExpr * lambda() const noexcept { return lambda_; } + const DLocalEnv * env() const noexcept { return env_; } + + ///@} + /** @defgroup scm-closure-procedure-facet **/ + ///@{ + /** for now, support just fixed-arity procedures **/ bool is_nary() const noexcept { return false; } /** number of arguments expected by this procedure (-1 if nary) **/ size_type n_args() const noexcept { return lambda_->n_args(); } + obj apply_nocheck(obj rcx, const DArray * args); + + ///@} + /** @defgroup scm-closure-gcobject-facet **/ + ///@{ + + ///@} + /** @defgroup scm-closure-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + private: /** lambda expression **/ const DLambdaExpr * lambda_ = nullptr; diff --git a/include/xo/interpreter2/detail/IProcedure_DClosure.hpp b/include/xo/interpreter2/detail/IProcedure_DClosure.hpp new file mode 100644 index 00000000..2c966a50 --- /dev/null +++ b/include/xo/interpreter2/detail/IProcedure_DClosure.hpp @@ -0,0 +1,67 @@ +/** @file IProcedure_DClosure.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IProcedure_DClosure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IProcedure_DClosure.json5] + **/ + +#pragma once + +#include "Procedure.hpp" +#include +#include +#include +#include +#include "DClosure.hpp" + +namespace xo { namespace scm { class IProcedure_DClosure; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IProcedure_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IProcedure_DClosure + **/ + class IProcedure_DClosure { + public: + /** @defgroup scm-procedure-dclosure-type-traits **/ + ///@{ + using AGCObject = xo::scm::AProcedure::AGCObject; + using Copaque = xo::scm::AProcedure::Copaque; + using Opaque = xo::scm::AProcedure::Opaque; + ///@} + /** @defgroup scm-procedure-dclosure-methods **/ + ///@{ + // const methods + /** true iff procedure takes n arguments **/ + static bool is_nary(const DClosure & self) noexcept; + /** number of arguments. -1 for n-ary **/ + static std::int32_t n_args(const DClosure & self) noexcept; + + // non-const methods + /** invoke procedure; assume arguments satisfy type system **/ + static obj apply_nocheck(DClosure & self, obj rcx, const DArray * args); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/src/interpreter2/CMakeLists.txt b/src/interpreter2/CMakeLists.txt index e0903be8..b47ea31d 100644 --- a/src/interpreter2/CMakeLists.txt +++ b/src/interpreter2/CMakeLists.txt @@ -16,6 +16,8 @@ set(SELF_SRCS IGCObject_DVsmApplyFrame.cpp IPrintable_DVsmApplyFrame.cpp + IProcedure_DClosure.cpp + VsmInstr.cpp DClosure.cpp diff --git a/src/interpreter2/DClosure.cpp b/src/interpreter2/DClosure.cpp index 6d9bc446..1057a25d 100644 --- a/src/interpreter2/DClosure.cpp +++ b/src/interpreter2/DClosure.cpp @@ -6,6 +6,8 @@ #include "DClosure.hpp" namespace xo { + using xo::mm::AGCObject; + namespace scm { DClosure::DClosure(const DLambdaExpr * lm, @@ -23,6 +25,16 @@ namespace xo { return new (mem) DClosure(lm, env); } + obj + DClosure::apply_nocheck(obj rcx, + const DArray * args) + { + (void)rcx; + (void)args; + + assert(false); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/interpreter2/IProcedure_DClosure.cpp b/src/interpreter2/IProcedure_DClosure.cpp new file mode 100644 index 00000000..b41c7be1 --- /dev/null +++ b/src/interpreter2/IProcedure_DClosure.cpp @@ -0,0 +1,39 @@ +/** @file IProcedure_DClosure.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IProcedure_DClosure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IProcedure_DClosure.json5] +**/ + +#include "detail/IProcedure_DClosure.hpp" + +namespace xo { + namespace scm { + auto + IProcedure_DClosure::is_nary(const DClosure & self) noexcept -> bool + { + return self.is_nary(); + } + + auto + IProcedure_DClosure::n_args(const DClosure & self) noexcept -> std::int32_t + { + return self.n_args(); + } + + auto + IProcedure_DClosure::apply_nocheck(DClosure & self, obj rcx, const DArray * args) -> obj + { + return self.apply_nocheck(rcx, args); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IProcedure_DClosure.cpp */ diff --git a/src/interpreter2/interpreter2_register_facets.cpp b/src/interpreter2/interpreter2_register_facets.cpp index b16d33ef..820dac2c 100644 --- a/src/interpreter2/interpreter2_register_facets.cpp +++ b/src/interpreter2/interpreter2_register_facets.cpp @@ -8,6 +8,8 @@ #include "VsmApplyFrame.hpp" #include "VsmEvalArgsFrame.hpp" +#include "Closure.hpp" + #include #include #include @@ -36,8 +38,15 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + // Procedure + // +- Primitive_gco_2_gco_gco + // \- Closure + + FacetRegistry::register_impl(); + log && log(xtag("DVsmApplyFrame.tseq", typeseq::id())); log && log(xtag("DVsmEvalArgsFrame.tseq", typeseq::id())); + log && log(xtag("DClosure.tseq", typeseq::id())); return true; } diff --git a/utest/VirtualSchematikaMachine.test.cpp b/utest/VirtualSchematikaMachine.test.cpp index 32cf7cab..90805af7 100644 --- a/utest/VirtualSchematikaMachine.test.cpp +++ b/utest/VirtualSchematikaMachine.test.cpp @@ -186,6 +186,43 @@ namespace xo { vsm.visit_pools(visitor); } + TEST_CASE("VirtualSchematikaMachine-lambda1", "[interpreter2][VSM]") + { + scope log(XO_DEBUG(true)); + + VsmConfig cfg; + VirtualSchematikaMachine vsm(cfg); + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("lambda (x : i64) -> i64 { x * x; };"), eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq())); + + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE(x.data()->value() == 1.570796325); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + auto visitor = [&log](const MemorySizeInfo & info) { + log && log(xtag("resource", info.resource_name_), + xtag("used", info.used_), + xtag("alloc", info.allocated_), + xtag("commit", info.committed_), + xtag("resv", info.reserved_)); + }; + + FacetRegistry::instance().visit_pools(visitor); + vsm.visit_pools(visitor); + } + } /*namespace ut*/ } /*namespace xo*/