diff --git a/src/lib/format-util.hpp b/src/lib/format-util.hpp index f0f48b413..1f0fd8bf8 100644 --- a/src/lib/format-util.hpp +++ b/src/lib/format-util.hpp @@ -188,12 +188,12 @@ namespace util { * absolutely generic (In fact that was the reason why I * gave up and just rolled our own `join` utility) */ - template + template inline string - join (CON&& coll, string const& delim =", ") + join (COLL&& coll, string const& delim =", ") { - using Coll = typename lib::meta::Strip::TypePlain; - _RangeIter range(std::forward(coll)); // copies when CON is reference + using Coll = typename lib::meta::Strip::TypePlain; + _RangeIter range(std::forward(coll)); // copies when CON is reference auto strings = stringify (std::move (range.iter)); if (!strings) return ""; @@ -242,5 +242,22 @@ namespace util { } + + /** one-argument variant that can be forward declared... */ + template + inline string + toStringParen (COLL&& coll) + { + return "("+join (forward (coll))+")"; + } + + template + inline string + toStringBracket (COLL&& coll) + { + return "["+join (forward (coll))+"]"; + } + + } // namespace util #endif /*LIB_FORMAT_UTIL_H*/ diff --git a/src/lib/several.hpp b/src/lib/several.hpp index e9570df6c..10d079dd0 100644 --- a/src/lib/several.hpp +++ b/src/lib/several.hpp @@ -57,6 +57,10 @@ #include #include +namespace util { + template + std::string toStringBracket (COLL&& coll); +} namespace lib { @@ -179,6 +183,9 @@ namespace lib { return *this; } + explicit + operator std::string() const; + size_t size() const { @@ -248,5 +255,13 @@ namespace lib { }; + /** generic string rendering delegated to `util::toString(elm)` */ + template + inline + Several::operator std::string() const + { + return util::toStringBracket (*this); + } + } // namespace lib #endif diff --git a/src/steam/engine/proc-node.cpp b/src/steam/engine/proc-node.cpp index 560c31f4a..32fd8cacc 100644 --- a/src/steam/engine/proc-node.cpp +++ b/src/steam/engine/proc-node.cpp @@ -322,7 +322,7 @@ namespace engine { ProcID::ArgModel ProcID::genArgModel() { - auto argListSyntax = accept_bracket(accept_repeated(COMMA, specTermSyntax)); + auto argListSyntax = accept_bracket(accept_repeated(0,MAX_NODE_ARG, COMMA, specTermSyntax)); auto argSpecSyntax = accept(argListSyntax) .opt(argListSyntax) .bind([](auto model) -> ProcID::ArgModel diff --git a/src/steam/engine/proc-node.hpp b/src/steam/engine/proc-node.hpp index 6436f5b8d..634cd5955 100644 --- a/src/steam/engine/proc-node.hpp +++ b/src/steam/engine/proc-node.hpp @@ -129,6 +129,12 @@ namespace engine { using OptionalBuff = std::optional; + /** arbitrary safety limit on fain-in / fan-out + * @note expect lower limits in practice caused by AllocationCluster */ + const size_t MAX_NODE_ARG = LUMIERA_MAX_ORDINAL_NUMBER / 2; + + + class Port : util::NonCopyable { diff --git a/tests/core/steam/engine/node-meta-test.cpp b/tests/core/steam/engine/node-meta-test.cpp index 11d266695..5b224306d 100644 --- a/tests/core/steam/engine/node-meta-test.cpp +++ b/tests/core/steam/engine/node-meta-test.cpp @@ -34,7 +34,7 @@ namespace engine{ namespace test { using std::abs; - using util::join; +// using util::join; @@ -51,8 +51,8 @@ namespace test { } - /** @test TODO evaluation of processing-spec for a ProcID - * @todo WIP 1/25 🔁 define ⟶ 🔁 implement + /** @test evaluation of processing-spec for a ProcID + * @todo 1/25 ✔ define ⟶ ✔ implement */ void verify_ID_specification() @@ -82,24 +82,34 @@ namespace test { ProcID::ArgModel arg1 = p1.genArgModel(); ProcID::ArgModel arg2 = p2.genArgModel(); ProcID::ArgModel arg3 = p3.genArgModel(); -SHOW_EXPR(join (arg1.iArg)) -SHOW_EXPR(join (arg1.oArg)) -SHOW_EXPR(join (arg2.iArg)) -SHOW_EXPR(join (arg2.oArg)) -SHOW_EXPR(join (arg3.iArg)) -SHOW_EXPR(join (arg3.oArg)) - CHECK (join (arg1.iArg) == ""_expect ); - CHECK (join (arg1.oArg) == "arg"_expect ); // only one argument list -> used for output - CHECK (join (arg2.iArg) == ""_expect ); - CHECK (join (arg2.oArg) == "a1, a2"_expect ); - CHECK (join (arg3.iArg) == "in, in, in"_expect ); // repetition-abbreviation of arguments unfolded - CHECK (join (arg3.oArg) == "o1, o2, o2"_expect ); - UNIMPLEMENTED ("parse and evaluate"); + CHECK (not arg1.hasInArgs()); + CHECK (not arg2.hasInArgs()); + CHECK (arg1.outArity() == 1); + CHECK (arg2.outArity() == 2); + CHECK (arg3.outArity() == 3); + CHECK (arg3.inArity() == 3); + CHECK (arg1.iArg == "[]"_expect ); + CHECK (arg1.oArg == "[arg]"_expect ); // only one argument list -> used for output + CHECK (arg2.iArg == "[]"_expect ); + CHECK (arg2.oArg == "[a1, a2]"_expect ); + CHECK (arg3.iArg == "[in, in, in]"_expect ); // repetition-abbreviation of arguments unfolded + CHECK (arg3.oArg == "[o1, o2, o2]"_expect ); + + // give the spec-parser a rough time.... + string nastySpec = "(\":-)\"/2,std::tuple/3,{oh,RLY?}/2,\\\")"; + auto hairyModel = ProcID::describe("○", nastySpec).genArgModel(); + CHECK (hairyModel.outArity() == 8); + CHECK (hairyModel.inArity() == 0); + CHECK (hairyModel.oArg == "[\":-)\", \":-)\", " + "std::tuple, " + "std::tuple, " + "std::tuple, " + "{oh,RLY?}, {oh,RLY?}, \\\"]"_expect); } /** @test TODO aspects of node definition relevant for the ProcID - * @todo WIP 1/25 🔁 define ⟶ implement + * @todo WIP 2/25 🔁 define ⟶ implement */ void verify_ID_properties() diff --git a/tests/library/several-builder-test.cpp b/tests/library/several-builder-test.cpp index 2ee0bc1a7..9d7aa3986 100644 --- a/tests/library/several-builder-test.cpp +++ b/tests/library/several-builder-test.cpp @@ -36,6 +36,7 @@ using std::array; using lib::explore; using util::isLimited; +using util::toString; using util::isnil; using util::join; @@ -161,6 +162,7 @@ namespace test{ CHECK (elms.back() == 13); CHECK (elms[3] == 3); CHECK (join (elms,"-") == "1-1-2-3-5-8-13"_expect); + CHECK (toString(elms) == "[1, 1, 2, 3, 5, 8, 13]"_expect); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index bf4a8cbdd..281c45724 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -105306,8 +105306,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + @@ -105341,9 +105341,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + - - + + + @@ -105386,6 +105390,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + @@ -105427,9 +105432,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - + + + + @@ -105496,7 +105502,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -105511,8 +105517,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + + + @@ -105539,7 +105547,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + @@ -105563,9 +105573,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + @@ -105606,7 +105616,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -105630,8 +105640,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) ...wenn man's genau bedenkt: wäre praktisch äquivalent

- - +
@@ -105653,15 +105662,14 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) in einer LL-Syntax kann man nicht mit einer optionalen Struktur beginnen, die sich erst im Rückblick auf die ganze Zeile aufklärt

- - +
- - - + + + @@ -105705,8 +105713,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -105754,8 +105763,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Pipeline zum Aufbereiten der Argumente an

- - + @@ -105769,13 +105777,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Aber trotzdem immer noch nicht der leiseste Hauch von Erinnerung, was ich damals gemeint habe....

- -
+
- + + @@ -105785,11 +105793,14 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)

+
- + + - + + @@ -105821,6 +105832,12 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + +