Invocation: tricky pipeline to unfold the repetition-abbreviation

This is a nice little goodie: allow to write repeated arguments with the
shorthand notation known from lisp and logic programming. For multi-channel media,
structurally similar wirings for each channel will be quite common....
This commit is contained in:
Fischlurch 2025-02-02 03:49:13 +01:00
parent 5c2b6b69f6
commit f6a2a641df
5 changed files with 221 additions and 79 deletions

View file

@ -1885,7 +1885,7 @@ namespace lib {
* - it is bound to play well with the other layers; especially it needs to be aware of `expandChildren()` calls,
* which for the consumer side behave like `iterNext()` calls. If a layer needs to do something special for
* `iterNext()`, it needs to perform a similar action for `expandChildren()`.
* - it must be behave like a default-constructible, copyable value object
* - it must allow to be handled as default-constructible, copyable value object
* @return augmented IterExplorer, incorporating and adapting the injected layer
*/
template<template<class> class LAY>

View file

@ -783,14 +783,18 @@ namespace lib {
void
probeMoveCapability()
{
if (not (is_same_v<TY,E> or is_trivially_copyable_v<TY>))
using TVal = typename lib::meta::Strip<TY>::TypeReferred;
using EVal = typename lib::meta::Strip<E>::TypeReferred;
if (not (is_same_v<TVal,EVal> or is_trivially_copyable_v<TVal>))
lock_move = true;
}
bool
canWildMove()
{
return is_trivially_copyable_v<E> and not lock_move;
using EVal = typename lib::meta::Strip<E>::TypeReferred;
return is_trivially_copyable_v<EVal> and not lock_move;
}
bool

View file

@ -63,6 +63,7 @@ namespace engine {
using util::parse::accept_repeated;
using util::parse::expectResult;
using lib::meta::NullType;
using std::regex_match;
using std::regex;
const regex SPEC_CONTENT{R"_([^,\\\(\)\[\]{}<>"]+)_", regex::optimize};
@ -103,6 +104,70 @@ namespace engine {
)
.bindMatch();
const regex REPEAT_SPEC {R"_(^(.+)\s*/(\d+)\s*$)_", regex::optimize};
/**
* Helper to expand an abbreviated repetition of arguments.
* Implemented as custom-processing layer for IterExplorer,
* by adapting the »State Core« interface
* @remark Repetition is indicated by a trailing "/NUM"
*/
template<class IT>
struct RepetitionExpander
: lib::IterStateCore<IT>
{
using Core = lib::IterStateCore<IT>;
mutable uint repeat_{0};
mutable std::smatch mat_;
StrView
yield() const
{
if (not repeat_)
{ // check if the next string ends with repetition marker /NUM
if (not regex_match (*Core::srcIter(), mat_, REPEAT_SPEC))
return *Core::srcIter(); // no repetition -> pass through
// setup repetition by extracting the repetition count
repeat_ = boost::lexical_cast<uint>(mat_.str(2));
}
return StrView(& *mat_[1].first, mat_[1].length());
} // several repetitions created from same source
void
iterNext()
{ // hold iteration until all repetitions were delivered
if (repeat_)
--repeat_;
if (not repeat_)
++ Core::srcIter();
}
using Core::Core;
};
/** Argument-Spec processing pipeline;
* possibly expands repetition abbreviation,
* collects all argument strings into a lib::Several
*/
lib::Several<const string>
evaluateArgSeq (std::vector<string>& parsedArgTerms)
{
auto several = lib::makeSeveral<const string>();
lib::explore (parsedArgTerms)
.processingLayer<RepetitionExpander>()
.foreach([&](StrView s){ several.emplace<string>(s); });
return several.build();
}
auto
emptyArgSeq()
{
return lib::Several<const string>();
}
} // (END) Details...
@ -262,18 +327,11 @@ namespace engine {
.opt(argListSyntax)
.bind([](auto model) -> ProcID::ArgModel
{
auto packageAsSeveral = [](std::vector<string>& parsedTerms)
{
return lib::makeSeveral<const string>()
.appendAll(parsedTerms);
};
auto [list1,list2] = model;
auto elms1 = packageAsSeveral(list1);
auto elms2 = list2? packageAsSeveral(*list2)
: lib::makeSeveral<const string>();
return ProcID::ArgModel{elms1.build(), elms2.build()};
if (list2)
return {evaluateArgSeq(list1), evaluateArgSeq(*list2)};
else
return {emptyArgSeq(), evaluateArgSeq(list1)};
});
argSpecSyntax.parse (argLists_);

View file

@ -88,6 +88,12 @@ 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");
}

View file

@ -105473,7 +105473,8 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1738347634026" ID="ID_891035798" MODIFIED="1738383492570" TEXT="ArgumentModel anlegen">
<node COLOR="#338800" CREATED="1738347634026" ID="ID_891035798" MODIFIED="1738449453574" TEXT="ArgumentModel anlegen">
<linktarget COLOR="#578494" DESTINATION="ID_891035798" ENDARROW="Default" ENDINCLINATION="46;331;" ID="Arrow_ID_982442559" SOURCE="ID_1594772328" STARTARROW="None" STARTINCLINATION="13;-499;"/>
<icon BUILTIN="button_ok"/>
<node COLOR="#5b280f" CREATED="1738347643696" ID="ID_522386929" MODIFIED="1738347656236" TEXT="vector-Storage">
<icon BUILTIN="button_cancel"/>
@ -105582,35 +105583,80 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<icon BUILTIN="ksmiletris"/>
<node CREATED="1738383281669" ID="ID_586712898" MODIFIED="1738383485792">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
da schreibt man so eine <font size="5">Monster-Syntax</font>&#160;einfach hin
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#dee8ae" COLOR="#116b3a" CREATED="1738383295667" ID="ID_1926681347" MODIFIED="1738383374590" STYLE="fork">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
und der Parser funktioniert <font size="6">auf Anhieb</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
<font NAME="SansSerif" SIZE="16"/>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1736633780461" ID="ID_182647940" MODIFIED="1738463484410" TEXT="Repetitions-Spec /# ausfalten">
<icon BUILTIN="button_ok"/>
<node CREATED="1738462844433" ID="ID_1445421658" MODIFIED="1738462904758" TEXT="nur sinnvoll mit &#xbb;schleppendem State&#xab; &#x27f9; Pipeline">
<linktarget COLOR="#fbfac5" DESTINATION="ID_1445421658" ENDARROW="Default" ENDINCLINATION="-169;10;" ID="Arrow_ID_1592587071" SOURCE="ID_364619333" STARTARROW="None" STARTINCLINATION="135;14;"/>
</node>
<node CREATED="1738462919279" ID="ID_789268471" MODIFIED="1738462939560" TEXT="Processing-Layer auf IterStateCore aufsetzen">
<node CREATED="1738463556328" ID="ID_531009155" MODIFIED="1738463571327" TEXT="macht bei jedem neuen String einen RegExp-Match"/>
<node CREATED="1738463574408" ID="ID_791728952" MODIFIED="1738463588360" TEXT="speichert sich dann ggfs. einen Count-down-Z&#xe4;hler"/>
<node CREATED="1738463494776" ID="ID_348332051" MODIFIED="1738463651081" TEXT="wegen Verzeweigung &#x27f9; mu&#xdf; yield-per-value">
<arrowlink COLOR="#57697e" DESTINATION="ID_263830289" ENDARROW="Default" ENDINCLINATION="31;-43;" ID="Arrow_ID_217184317" STARTARROW="None" STARTINCLINATION="-88;6;"/>
</node>
</node>
<node CREATED="1738463595299" ID="ID_263830289" MODIFIED="1738463651081" TEXT="sinnvollerweise String-View zur&#xfc;ckgeben">
<linktarget COLOR="#57697e" DESTINATION="ID_263830289" ENDARROW="Default" ENDINCLINATION="31;-43;" ID="Arrow_ID_217184317" SOURCE="ID_348332051" STARTARROW="None" STARTINCLINATION="-88;6;"/>
<node CREATED="1738463661274" ID="ID_1456272070" MODIFIED="1738463676497" TEXT="Move ist nicht m&#xf6;glich wegen Match-substring"/>
<node CREATED="1738463677719" ID="ID_1707959463" MODIFIED="1738463745026" TEXT="so kann man wenigstens shared-repetitions durchreichen"/>
<node CREATED="1738463750974" ID="ID_1581438036" MODIFIED="1738463972665" TEXT="Alternative w&#xe4;re jeweils String und dann move">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...wenn man's genau bedenkt: w&#228;re praktisch &#228;quivalent
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1738463780753" ID="ID_202887229" MODIFIED="1738463807594" TEXT="w&#xe4;re nur sinnvoll wenn auch die String-Daten selber im Several liegen"/>
<node COLOR="#5b280f" CREATED="1738463809678" ID="ID_1945186564" MODIFIED="1738463827762" TEXT="hier aber Several nur wegen dem API verwendet">
<icon BUILTIN="stop-sign"/>
</node>
<node CREATED="1738463833525" ID="ID_929197172" MODIFIED="1738463849556" TEXT="keine &#xfc;ber-Optimierung!"/>
</node>
<node COLOR="#9f7025" CREATED="1738464052644" ID="ID_1574950416" MODIFIED="1738464162238" TEXT="w&#xe4;&#xe4;&#xe4; ... furchbar technisch"/>
</node>
<node COLOR="#338800" CREATED="1738449391554" ID="ID_405611509" MODIFIED="1738462838583" TEXT="Argumentlisten korrekt zuordnen">
<icon BUILTIN="button_ok"/>
<node CREATED="1738450680611" ID="ID_732017891" MODIFIED="1738450694686" TEXT="nur eine Liste &#x27f9; das ist der Output"/>
<node CREATED="1738450698945" ID="ID_1474764729" MODIFIED="1738450720298" TEXT="zwei Listen &#x27f9; Input zuerst"/>
<node CREATED="1738450728229" ID="ID_1478813672" MODIFIED="1738450791890" TEXT="bedingt durch die Struktur der Syntax tauschen sich die Stellen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
in einer LL-Syntax kann man nicht mit einer optionalen Struktur beginnen, die sich erst im R&#252;ckblick auf die ganze Zeile aufkl&#228;rt
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1736632908578" ID="ID_1359149203" MODIFIED="1736633401873" TEXT="Token-Sequenz generieren">
@ -105659,55 +105705,8 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</html></richcontent>
</node>
</node>
<node CREATED="1738280786811" ID="ID_1355841919" MODIFIED="1738280796189" TEXT="also dann doch richtig parsen">
<node CREATED="1738281073002" ID="ID_537165384" MODIFIED="1738281158036" TEXT="schon beim Zerlegen in Input/Output bin ich auf diese Probleme gesto&#xdf;en &#x2014;">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
....und jetzt hab ich einen echten LL-Parser, der diese Aufgabe direkt und ohne Implementierungstricks handhaben kann
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1738281326205" ID="ID_1746479195" MODIFIED="1738281816880" TEXT="per Parse kann man aber auch gleich ein Modell erzeugen">
<node CREATED="1738281820274" ID="ID_1616091691" MODIFIED="1738281831902" TEXT="ist die Frage ob das hier sinnvoll ist"/>
<node CREATED="1738281832897" ID="ID_1679825734" MODIFIED="1738281848598" TEXT="alternativ k&#xf6;nnte man auch x-mal immer wieder parsen"/>
<node COLOR="#435e98" CREATED="1738282103267" ID="ID_981290324" MODIFIED="1738288404860" TEXT="was f&#xfc;r Zugriffe w&#xe4;ren denn regelm&#xe4;&#xdf;ig zu erwarten">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1736633797874" ID="ID_266262938" MODIFIED="1738449408813" TEXT="Token-Pipeline aufbauen">
<icon BUILTIN="help"/>
<node CREATED="1738282122522" ID="ID_1638205904" MODIFIED="1738282141735" TEXT="(also nicht im Test, sondern beim Rendern)">
<font NAME="SansSerif" SIZE="10"/>
</node>
<node CREATED="1738287496191" ID="ID_603773549" MODIFIED="1738287513728" TEXT="Proc-ID-Hash &#x27fc; Cache-Key">
<node CREATED="1738287635731" ID="ID_1544335110" MODIFIED="1738287651757" TEXT="lie&#xdf;e sich durch Hashing gespeicherter ID-Bestandteile realisieren"/>
<node CREATED="1738287652784" ID="ID_437630211" MODIFIED="1738287666843" TEXT="insofern ist nur die Aufbereitung (beim Build) relevant"/>
</node>
<node CREATED="1738288309624" ID="ID_203838981" MODIFIED="1738288402151" TEXT="Instrumentierung w&#xfc;rde sich wohl v.A. auf Node-Connectivity abst&#xfc;tzen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...deshalb habe ich ja auch die Node-Connectivity beibehalten (obwohl zum Rendern nur die Port-Connectivity gebraucht wird). Zus&#228;tzlich k&#246;nnten noch Attribute in der ProcID eine Rolle spielen. Also insgesamt ehr kein separates Parsing
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1738288408915" ID="ID_1594772328" MODIFIED="1738288439248">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
&#10233; also so implementieren wie's <i>am einfachsten</i>&#160;geht
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1736633780461" ID="ID_182647940" MODIFIED="1736633788547" TEXT="Repetitions-Spec /#"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1736633797874" ID="ID_266262938" MODIFIED="1738288459135" TEXT="Token-Pipeline aufbauen">
<icon BUILTIN="hourglass"/>
<node COLOR="#5b280f" CREATED="1736633850189" ID="ID_187292513" MODIFIED="1736633861182" TEXT="k&#xf6;nnte ein Expander sein">
<icon BUILTIN="stop-sign"/>
<node COLOR="#5b280f" CREATED="1736633863015" ID="ID_1166752601" MODIFIED="1736633908235" TEXT="unn&#xf6;tig komplex">
@ -105744,6 +105743,84 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<node CREATED="1738288462715" ID="ID_721467849" MODIFIED="1738288475560" TEXT="sehe jetzt (1/25) keine direkte Notwendigkeit"/>
<node CREATED="1738288476858" ID="ID_1430760953" MODIFIED="1738288501992" TEXT="und aus einem tempor&#xe4;r erzeugten Proc-Argument-Model lie&#xdf;e sich sowas leicht erzeugen"/>
</node>
<node CREATED="1738448973685" ID="ID_364619333" MODIFIED="1738462911406">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
doch! jetzt bietet sich tats&#228;chlich eine
</p>
<p>
Pipeline zum Aufbereiten der Argumente an
</p>
</body>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
und zwar zum Ausfalten der Abk&#252;rzungs-Syntax /#
</p>
<p>
</p>
<p>
Aber trotzdem immer noch nicht der leiseste Hauch von Erinnerung, was ich damals gemeint habe....
</p>
</body>
</html>
</richcontent>
<arrowlink COLOR="#fbfac5" DESTINATION="ID_1445421658" ENDARROW="Default" ENDINCLINATION="-169;10;" ID="Arrow_ID_1592587071" STARTARROW="None" STARTINCLINATION="135;14;"/>
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1738280786811" ID="ID_1355841919" MODIFIED="1738280796189" TEXT="also dann doch richtig parsen">
<node CREATED="1738281073002" ID="ID_537165384" MODIFIED="1738281158036" TEXT="schon beim Zerlegen in Input/Output bin ich auf diese Probleme gesto&#xdf;en &#x2014;">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
....und jetzt hab ich einen echten LL-Parser, der diese Aufgabe direkt und ohne Implementierungstricks handhaben kann
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1738281326205" ID="ID_1746479195" MODIFIED="1738281816880" TEXT="per Parse kann man aber auch gleich ein Modell erzeugen">
<node CREATED="1738281820274" ID="ID_1616091691" MODIFIED="1738281831902" TEXT="ist die Frage ob das hier sinnvoll ist"/>
<node CREATED="1738281832897" ID="ID_1679825734" MODIFIED="1738281848598" TEXT="alternativ k&#xf6;nnte man auch x-mal immer wieder parsen"/>
<node COLOR="#435e98" CREATED="1738282103267" ID="ID_981290324" MODIFIED="1738288404860" TEXT="was f&#xfc;r Zugriffe w&#xe4;ren denn regelm&#xe4;&#xdf;ig zu erwarten">
<icon BUILTIN="help"/>
<node CREATED="1738282122522" ID="ID_1638205904" MODIFIED="1738282141735" TEXT="(also nicht im Test, sondern beim Rendern)">
<font NAME="SansSerif" SIZE="10"/>
</node>
<node CREATED="1738287496191" ID="ID_603773549" MODIFIED="1738287513728" TEXT="Proc-ID-Hash &#x27fc; Cache-Key">
<node CREATED="1738287635731" ID="ID_1544335110" MODIFIED="1738287651757" TEXT="lie&#xdf;e sich durch Hashing gespeicherter ID-Bestandteile realisieren"/>
<node CREATED="1738287652784" ID="ID_437630211" MODIFIED="1738287666843" TEXT="insofern ist nur die Aufbereitung (beim Build) relevant"/>
</node>
<node CREATED="1738288309624" ID="ID_203838981" MODIFIED="1738288402151" TEXT="Instrumentierung w&#xfc;rde sich wohl v.A. auf Node-Connectivity abst&#xfc;tzen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...deshalb habe ich ja auch die Node-Connectivity beibehalten (obwohl zum Rendern nur die Port-Connectivity gebraucht wird). Zus&#228;tzlich k&#246;nnten noch Attribute in der ProcID eine Rolle spielen. Also insgesamt ehr kein separates Parsing
</p>
</body>
</html></richcontent>
</node>
</node>
<node CREATED="1738288408915" ID="ID_1594772328" MODIFIED="1738449463581">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
&#10233; also so implementieren wie's <i>am einfachsten</i>&#160;geht
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#578494" DESTINATION="ID_891035798" ENDARROW="Default" ENDINCLINATION="46;331;" ID="Arrow_ID_982442559" STARTARROW="None" STARTINCLINATION="13;-499;"/>
</node>
</node>
</node>
</node>
<node COLOR="#5b280f" CREATED="1736632937502" ID="ID_461312539" MODIFIED="1736632988969" TEXT="Reduktion machen wir nicht">
@ -107336,16 +107413,13 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<node CREATED="1738381499662" ID="ID_583260551" MODIFIED="1738381510369" TEXT="f&#xfc;r das dynamische Wachstum von Vectoren"/>
<node BACKGROUND_COLOR="#e9a695" COLOR="#a50125" CREATED="1738381511432" ID="ID_53988543" MODIFIED="1738381635805" TEXT="f&#xfc;r die Maximal-Zahl eines lib::Several">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
weil dies auf einem Array beruht, also im Speicher kompakt liegen mu&#223;
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<arrowlink COLOR="#f20033" DESTINATION="ID_1142487945" ENDARROW="Default" ENDINCLINATION="243;-7;" ID="Arrow_ID_1622467293" STARTARROW="None" STARTINCLINATION="153;154;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
@ -107538,8 +107612,8 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<icon BUILTIN="help"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1738381598307" ID="ID_1142487945" MODIFIED="1738381906605" TEXT="kommen wir mit der Kachel-Beschr&#xe4;nkung im Basis-Allokator klar?">
<linktarget COLOR="#f20033" DESTINATION="ID_1142487945" ENDARROW="Default" ENDINCLINATION="243;-7;" ID="Arrow_ID_1622467293" SOURCE="ID_53988543" STARTARROW="None" STARTINCLINATION="153;154;"/>
<linktarget COLOR="#fe4663" DESTINATION="ID_1142487945" ENDARROW="Default" ENDINCLINATION="-862;38;" ID="Arrow_ID_778302658" SOURCE="ID_1808793696" STARTARROW="None" STARTINCLINATION="-918;43;"/>
<linktarget COLOR="#f20033" DESTINATION="ID_1142487945" ENDARROW="Default" ENDINCLINATION="243;-7;" ID="Arrow_ID_1622467293" SOURCE="ID_53988543" STARTARROW="None" STARTINCLINATION="153;154;"/>
<linktarget COLOR="#fe4663" DESTINATION="ID_1142487945" ENDARROW="Default" ENDINCLINATION="-609;26;" ID="Arrow_ID_1973425820" SOURCE="ID_333614315" STARTARROW="None" STARTINCLINATION="174;8;"/>
<icon BUILTIN="help"/>
</node>