Library: try out building a variant-model on top
* the implementation of this ''Sum Type'' got quite technical and complicated; thus better to be extracted as separate library component * use this as base for the `AltModel` * make a usage sketch, invoking only the model interactions required
This commit is contained in:
parent
8c046ee2ea
commit
d052edf91d
6 changed files with 949 additions and 204 deletions
566
src/lib/branch-case.hpp
Normal file
566
src/lib/branch-case.hpp
Normal file
|
|
@ -0,0 +1,566 @@
|
||||||
|
/*
|
||||||
|
BRANCH-CASE.hpp - helpers for parsing textual specifications
|
||||||
|
|
||||||
|
Copyright (C)
|
||||||
|
2024, Hermann Vosseler <Ichthyostega@web.de>
|
||||||
|
|
||||||
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
option) any later version. See the file COPYING for further details.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @file branch-case.hpp
|
||||||
|
** Convenience wrappers and definitions for parsing structured definitions.
|
||||||
|
** Whenever a specification syntax entails nested structures, extracting contents
|
||||||
|
** with regular expressions alone becomes tricky. Without much sophistication, a
|
||||||
|
** directly implemented simple recursive descent parser is often less brittle and
|
||||||
|
** easier to understand and maintain. With some helper abbreviations, notably
|
||||||
|
** a combinator scheme to work from building blocks, a hand-written solution
|
||||||
|
** can benefit from taking short-cuts, especially related to result bindings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LIB_BRANCH_CASE_H
|
||||||
|
#define LIB_BRANCH_CASE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "lib/iter-adapter.hpp"
|
||||||
|
#include "lib/meta/function.hpp"
|
||||||
|
#include "lib/meta/trait.hpp"
|
||||||
|
#include "lib/regex.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <tuple>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
namespace parse {
|
||||||
|
|
||||||
|
using std::move;
|
||||||
|
using std::forward;
|
||||||
|
using std::optional;
|
||||||
|
using lib::meta::_Fun;
|
||||||
|
using lib::meta::has_Sig;
|
||||||
|
using lib::meta::NullType;
|
||||||
|
using std::decay_t;
|
||||||
|
using std::tuple;
|
||||||
|
using std::array;
|
||||||
|
|
||||||
|
using StrView = std::string_view;
|
||||||
|
|
||||||
|
template<typename...TYPES>
|
||||||
|
struct _MaxBufSiz;
|
||||||
|
template<>
|
||||||
|
struct _MaxBufSiz<>
|
||||||
|
{
|
||||||
|
static constexpr size_t siz = 0;
|
||||||
|
};
|
||||||
|
template<typename T, typename...TYPES>
|
||||||
|
struct _MaxBufSiz<T,TYPES...>
|
||||||
|
{
|
||||||
|
static constexpr size_t siz = std::max (sizeof(T)
|
||||||
|
,_MaxBufSiz<TYPES...>::siz);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename...TYPES>
|
||||||
|
class BranchCase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto TOP = sizeof...(TYPES) -1;
|
||||||
|
static constexpr auto SIZ = _MaxBufSiz<TYPES...>::siz;
|
||||||
|
|
||||||
|
template<size_t idx>
|
||||||
|
using SlotType = std::tuple_element_t<idx, tuple<TYPES...>>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** @internal default-created state is **invalid** */
|
||||||
|
BranchCase() = default;
|
||||||
|
|
||||||
|
|
||||||
|
size_t branch_{0};
|
||||||
|
|
||||||
|
alignas(int64_t)
|
||||||
|
std::byte buffer_[SIZ];
|
||||||
|
|
||||||
|
template<typename TX, typename...INITS>
|
||||||
|
TX&
|
||||||
|
emplace (INITS&&...inits)
|
||||||
|
{
|
||||||
|
return * new(&buffer_) TX(forward<INITS> (inits)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TX>
|
||||||
|
TX&
|
||||||
|
access ()
|
||||||
|
{
|
||||||
|
return * std::launder (reinterpret_cast<TX*> (&buffer_[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** apply generic functor to the currently selected branch */
|
||||||
|
template<size_t idx, class FUN>
|
||||||
|
auto
|
||||||
|
selectBranch (FUN&& fun)
|
||||||
|
{
|
||||||
|
if constexpr (0 < idx)
|
||||||
|
if (branch_ < idx)
|
||||||
|
return selectBranch<idx-1> (forward<FUN>(fun));
|
||||||
|
return fun (get<idx>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<class FUN>
|
||||||
|
auto
|
||||||
|
apply (FUN&& fun)
|
||||||
|
{
|
||||||
|
return selectBranch<TOP> (forward<FUN> (fun));
|
||||||
|
}
|
||||||
|
|
||||||
|
~BranchCase()
|
||||||
|
{
|
||||||
|
apply ([this](auto& it)
|
||||||
|
{ using Elm = decay_t<decltype(it)>;
|
||||||
|
access<Elm>().~Elm();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...INITS>
|
||||||
|
BranchCase (size_t idx, INITS&& ...inits)
|
||||||
|
: branch_{idx}
|
||||||
|
{
|
||||||
|
apply ([&,this](auto& it)
|
||||||
|
{ using Elm = decay_t<decltype(it)>;
|
||||||
|
if constexpr (std::is_constructible_v<Elm,INITS...>)
|
||||||
|
this->emplace<Elm> (forward<INITS> (inits)...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchCase (BranchCase const& o)
|
||||||
|
{
|
||||||
|
branch_ = o.branch_;
|
||||||
|
BranchCase& unConst = const_cast<BranchCase&> (o);
|
||||||
|
unConst.apply ([this](auto& it)
|
||||||
|
{ using Elm = decay_t<decltype(it)>;
|
||||||
|
this->emplace<Elm> (it);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchCase (BranchCase && ro)
|
||||||
|
{
|
||||||
|
branch_ = ro.branch_;
|
||||||
|
ro.apply ([this](auto& it)
|
||||||
|
{ using Elm = decay_t<decltype(it)>;
|
||||||
|
this->emplace<Elm> (move (it));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void
|
||||||
|
swap (BranchCase& o1, BranchCase o2)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
BranchCase tmp;
|
||||||
|
o1.apply ([&](auto& it)
|
||||||
|
{ using Elm = decay_t<decltype(it)>;
|
||||||
|
tmp.emplace<Elm> (move (o1.access<Elm>()));
|
||||||
|
});
|
||||||
|
swap (o1.branch_,o2.branch_);
|
||||||
|
o1.apply ([&](auto& it)
|
||||||
|
{ using Elm = decay_t<decltype(it)>;
|
||||||
|
o1.emplace<Elm> (move (o2.access<Elm>()));
|
||||||
|
});
|
||||||
|
o2.apply ([&](auto& it)
|
||||||
|
{ using Elm = decay_t<decltype(it)>;
|
||||||
|
o2.emplace<Elm> (move (tmp.access<Elm>()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchCase&
|
||||||
|
operator= (BranchCase ref)
|
||||||
|
{
|
||||||
|
swap (*this, ref);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...MORE>
|
||||||
|
auto
|
||||||
|
moveExtended()
|
||||||
|
{
|
||||||
|
using Extended = BranchCase<TYPES...,MORE...>;
|
||||||
|
Extended& upFaked = reinterpret_cast<Extended&> (*this);
|
||||||
|
return Extended (move (upFaked));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
selected() const
|
||||||
|
{
|
||||||
|
return branch_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t idx>
|
||||||
|
SlotType<idx>&
|
||||||
|
get()
|
||||||
|
{
|
||||||
|
return access<SlotType<idx>>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if false ///////////////////////////////////////////////////////////////////////////////TODO accommodate
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
template<class RES>
|
||||||
|
struct Eval
|
||||||
|
{
|
||||||
|
using Result = RES;
|
||||||
|
optional<RES> result;
|
||||||
|
size_t consumed{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class FUN>
|
||||||
|
struct Connex
|
||||||
|
: util::NonAssign
|
||||||
|
{
|
||||||
|
using PFun = FUN;
|
||||||
|
PFun parse;
|
||||||
|
|
||||||
|
using Result = typename _Fun<PFun>::Ret::Result;
|
||||||
|
|
||||||
|
Connex (FUN&& pFun)
|
||||||
|
: parse{move(pFun)}
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
auto
|
||||||
|
buildConnex(NullType)
|
||||||
|
{
|
||||||
|
return Connex{[](StrView) -> Eval<NullType>
|
||||||
|
{
|
||||||
|
return {NullType{}};
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
using NulP = decltype(buildConnex (NullType()));
|
||||||
|
|
||||||
|
auto
|
||||||
|
buildConnex (regex rex)
|
||||||
|
{
|
||||||
|
return Connex{[regEx = move(rex)]
|
||||||
|
(StrView toParse) -> Eval<smatch>
|
||||||
|
{ // skip leading whitespace...
|
||||||
|
size_t pre = leadingWhitespace (toParse);
|
||||||
|
toParse = toParse.substr(pre);
|
||||||
|
auto result{matchAtStart (toParse,regEx)};
|
||||||
|
size_t consumed = result? pre+result->length() : 0;
|
||||||
|
return {move(result), consumed};
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
using Term = decltype(buildConnex (std::declval<regex>()));
|
||||||
|
|
||||||
|
Term
|
||||||
|
buildConnex (string const& rexDef)
|
||||||
|
{
|
||||||
|
return buildConnex (regex{rexDef});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FUN>
|
||||||
|
auto
|
||||||
|
buildConnex (Connex<FUN> const& anchor)
|
||||||
|
{
|
||||||
|
return Connex{anchor};
|
||||||
|
}
|
||||||
|
template<class FUN>
|
||||||
|
auto
|
||||||
|
buildConnex (Connex<FUN> && anchor)
|
||||||
|
{
|
||||||
|
return Connex{move(anchor)};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CON, class BIND>
|
||||||
|
auto
|
||||||
|
adaptConnex (CON&& connex, BIND&& modelBinding)
|
||||||
|
{
|
||||||
|
using RX = typename CON::Result;
|
||||||
|
using Arg = lib::meta::_FunArg<BIND>;
|
||||||
|
static_assert (std::is_constructible_v<Arg,RX>,
|
||||||
|
"Model binding must accept preceding model result.");
|
||||||
|
using AdaptedRes = typename _Fun<BIND>::Ret;
|
||||||
|
return Connex{[origConnex = forward<CON>(connex)
|
||||||
|
,binding = forward<BIND>(modelBinding)
|
||||||
|
]
|
||||||
|
(StrView toParse) -> Eval<AdaptedRes>
|
||||||
|
{
|
||||||
|
auto eval = origConnex.parse (toParse);
|
||||||
|
if (eval.result)
|
||||||
|
return {binding (move (*eval.result))};
|
||||||
|
else
|
||||||
|
return {std::nullopt};
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ===== building structured models ===== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Product Model : results from a conjunction of parsing clauses,
|
||||||
|
* which are to be accepted in sequence, one after the other.
|
||||||
|
*/
|
||||||
|
template<typename...RESULTS>
|
||||||
|
struct SeqModel
|
||||||
|
: tuple<RESULTS...>
|
||||||
|
{
|
||||||
|
static constexpr size_t SIZ = sizeof...(RESULTS);
|
||||||
|
using Seq = lib::meta::TySeq<RESULTS...>;
|
||||||
|
using Tup = std::tuple<RESULTS...>;
|
||||||
|
|
||||||
|
SeqModel() = default;
|
||||||
|
|
||||||
|
template<typename...XS, typename XX>
|
||||||
|
SeqModel (SeqModel<XS...>&& seq, XX&& extraElm)
|
||||||
|
: Tup{std::tuple_cat (seq.extractTuple()
|
||||||
|
,make_tuple (forward<XX> (extraElm)) )}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template<typename X1, typename X2>
|
||||||
|
SeqModel (X1&& res1, X2&& res2)
|
||||||
|
: Tup{move(res1), move(res2)}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Tup&& extractTuple() { return move(*this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sum Model : results from a disjunction of parsing clauses,
|
||||||
|
* which are are tested and accepted as alternatives, one at least.
|
||||||
|
*/
|
||||||
|
template<typename...CASES>
|
||||||
|
struct AltModel
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Special case Product Model to represent iterative sequence */
|
||||||
|
template<typename RES>
|
||||||
|
struct IterModel
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Marker-Tag for the result from a sub-expression, not to be joined */
|
||||||
|
template<typename RES>
|
||||||
|
struct SubModel
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Standard case : combinator of two model branches */
|
||||||
|
template<template<class...> class TAG, class R1, class R2 =void>
|
||||||
|
struct _Join
|
||||||
|
{
|
||||||
|
using Result = TAG<R1,R2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Generic case : extend a structured model by further branch */
|
||||||
|
template<template<class...> class TAG, class...RS, class R2>
|
||||||
|
struct _Join<TAG,TAG<RS...>,R2>
|
||||||
|
{
|
||||||
|
using Result = TAG<RS...,R2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Special Case : absorb sub-expression without flattening */
|
||||||
|
template<template<class...> class TAG, class R1, class R2>
|
||||||
|
struct _Join<TAG,SubModel<R1>,R2>
|
||||||
|
{
|
||||||
|
using Result = TAG<R1,R2>;
|
||||||
|
};
|
||||||
|
template<template<class...> class TAG, class R1, class R2>
|
||||||
|
struct _Join<TAG,R1, SubModel<R2>>
|
||||||
|
{
|
||||||
|
using Result = TAG<R1,R2>;
|
||||||
|
};
|
||||||
|
template<template<class...> class TAG, class R1, class R2>
|
||||||
|
struct _Join<TAG,SubModel<R1>,SubModel<R2>>
|
||||||
|
{
|
||||||
|
using Result = TAG<R1,R2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Special Case : absorb further similar elements into IterModel */
|
||||||
|
template<class RES>
|
||||||
|
struct _Join<IterModel, IterModel<RES>, RES>
|
||||||
|
{
|
||||||
|
using Result = IterModel<RES>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** accept sequence of two parse functions */
|
||||||
|
template<class C1, class C2>
|
||||||
|
auto
|
||||||
|
sequenceConnex (C1&& connex1, C2&& connex2)
|
||||||
|
{
|
||||||
|
using R1 = typename decay_t<C1>::Result;
|
||||||
|
using R2 = typename decay_t<C2>::Result;
|
||||||
|
using ProductResult = typename _Join<SeqModel, R1, R2>::Result;
|
||||||
|
using ProductEval = Eval<ProductResult>;
|
||||||
|
return Connex{[conL = forward<C1>(connex1)
|
||||||
|
,conR = forward<C2>(connex2)
|
||||||
|
]
|
||||||
|
(StrView toParse) -> ProductEval
|
||||||
|
{
|
||||||
|
auto eval1 = conL.parse (toParse);
|
||||||
|
if (eval1.result)
|
||||||
|
{
|
||||||
|
size_t posAfter1 = eval1.consumed;
|
||||||
|
StrView restInput = toParse.substr(posAfter1);
|
||||||
|
auto eval2 = conR.parse (restInput);
|
||||||
|
if (eval2.result)
|
||||||
|
{
|
||||||
|
uint consumedOverall = posAfter1 + eval2.consumed;
|
||||||
|
return ProductEval{ProductResult{move(*eval1.result)
|
||||||
|
,move(*eval2.result)}
|
||||||
|
,consumedOverall
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ProductEval{std::nullopt};
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class PAR>
|
||||||
|
class Syntax;
|
||||||
|
|
||||||
|
|
||||||
|
template<class CON>
|
||||||
|
class Parser
|
||||||
|
: public CON
|
||||||
|
{
|
||||||
|
using PFun = typename CON::PFun;
|
||||||
|
static_assert (_Fun<PFun>(), "Connex must define a parse-function");
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Connex = CON;
|
||||||
|
using Result = typename CON::Result;
|
||||||
|
|
||||||
|
using Sigi = typename _Fun<PFun>::Sig;
|
||||||
|
//lib::test::TypeDebugger<Sigi> buggi;
|
||||||
|
//lib::test::TypeDebugger<Result> guggi;
|
||||||
|
|
||||||
|
static_assert (has_Sig<PFun, Eval<Result>(StrView)>()
|
||||||
|
,"Signature of the parse-function not suitable");
|
||||||
|
|
||||||
|
Eval<Result>
|
||||||
|
operator() (StrView toParse)
|
||||||
|
{
|
||||||
|
return CON::parse (toParse);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename SPEC>
|
||||||
|
Parser (SPEC&& spec)
|
||||||
|
: CON{buildConnex (forward<SPEC> (spec))}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
// template<class PAR>
|
||||||
|
// Parser (Syntax<PAR> const& anchor)
|
||||||
|
// : CON{anchor}
|
||||||
|
// { }
|
||||||
|
// template<class PAR>
|
||||||
|
// Parser (CON const& anchor)
|
||||||
|
// : CON{anchor}
|
||||||
|
// { }
|
||||||
|
};
|
||||||
|
|
||||||
|
Parser(NullType) -> Parser<NulP>;
|
||||||
|
Parser(regex &&) -> Parser<Term>;
|
||||||
|
Parser(regex const&) -> Parser<Term>;
|
||||||
|
Parser(string const&) -> Parser<Term>;
|
||||||
|
|
||||||
|
template<class FUN>
|
||||||
|
Parser(Connex<FUN> const&) -> Parser<Connex<FUN>>;
|
||||||
|
//
|
||||||
|
// template<class PAR>
|
||||||
|
// Parser(Syntax<PAR> const&) -> Parser<typename PAR::Connex>;
|
||||||
|
|
||||||
|
|
||||||
|
template<class PAR>
|
||||||
|
class Syntax
|
||||||
|
: public Eval<typename PAR::Result>
|
||||||
|
{
|
||||||
|
PAR parse_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Connex = typename PAR::Connex;
|
||||||
|
using Result = typename PAR::Result;
|
||||||
|
|
||||||
|
bool success() const { return bool(Syntax::result); }
|
||||||
|
bool hasResult() const { return bool(Syntax::result); }
|
||||||
|
Result& getResult() { return * Syntax::result; }
|
||||||
|
Result&& extractResult(){ return move(getResult()); }
|
||||||
|
|
||||||
|
Syntax()
|
||||||
|
: parse_{NullType()}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
explicit
|
||||||
|
Syntax (PAR&& parser)
|
||||||
|
: parse_{move (parser)}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
explicit
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
Syntax&&
|
||||||
|
parse (StrView toParse)
|
||||||
|
{
|
||||||
|
eval() = parse_(toParse);
|
||||||
|
return move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Connex const&
|
||||||
|
getConny() const
|
||||||
|
{
|
||||||
|
return parse_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename SPEC>
|
||||||
|
auto
|
||||||
|
seq (SPEC&& clauseDef)
|
||||||
|
{
|
||||||
|
return accept(
|
||||||
|
sequenceConnex (move(parse_)
|
||||||
|
,Parser{forward<SPEC> (clauseDef)}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Eval<Result>&
|
||||||
|
eval()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename SPEC>
|
||||||
|
auto
|
||||||
|
accept (SPEC&& clauseDef)
|
||||||
|
{
|
||||||
|
return Syntax{Parser{forward<SPEC> (clauseDef)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<class PAR>
|
||||||
|
// Parser(Syntax<PAR> const&) -> Parser<typename PAR::Connex>;
|
||||||
|
|
||||||
|
#endif /////////////////////////////////////////////////////////////////////////////////////TODO accommodate
|
||||||
|
}// namespace parse
|
||||||
|
|
||||||
|
//using parse::accept;
|
||||||
|
}// namespace util
|
||||||
|
|
||||||
|
namespace lib {
|
||||||
|
}// namespace lib
|
||||||
|
#endif/*LIB_BRANCH_CASE_H*/
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
#define LIB_PARSE_H
|
#define LIB_PARSE_H
|
||||||
|
|
||||||
|
|
||||||
#include "lib/iter-adapter.hpp"
|
#include "lib/branch-case.hpp"
|
||||||
#include "lib/meta/function.hpp"
|
#include "lib/meta/function.hpp"
|
||||||
#include "lib/meta/trait.hpp"
|
#include "lib/meta/trait.hpp"
|
||||||
#include "lib/regex.hpp"
|
#include "lib/regex.hpp"
|
||||||
|
|
@ -53,158 +53,6 @@ namespace util {
|
||||||
|
|
||||||
using StrView = std::string_view;
|
using StrView = std::string_view;
|
||||||
|
|
||||||
template<typename...TYPES>
|
|
||||||
struct _MaxBufSiz;
|
|
||||||
template<>
|
|
||||||
struct _MaxBufSiz<>
|
|
||||||
{
|
|
||||||
static constexpr size_t siz = 0;
|
|
||||||
};
|
|
||||||
template<typename T, typename...TYPES>
|
|
||||||
struct _MaxBufSiz<T,TYPES...>
|
|
||||||
{
|
|
||||||
static constexpr size_t siz = std::max (sizeof(T)
|
|
||||||
,_MaxBufSiz<TYPES...>::siz);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename...TYPES>
|
|
||||||
class BranchCase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static constexpr auto TOP = sizeof...(TYPES) -1;
|
|
||||||
static constexpr auto SIZ = _MaxBufSiz<TYPES...>::siz;
|
|
||||||
|
|
||||||
template<size_t idx>
|
|
||||||
using SlotType = std::tuple_element_t<idx, tuple<TYPES...>>;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t branch_{0};
|
|
||||||
|
|
||||||
alignas(int64_t)
|
|
||||||
std::byte buffer_[SIZ];
|
|
||||||
|
|
||||||
template<typename TX, typename...INITS>
|
|
||||||
TX&
|
|
||||||
emplace (INITS&&...inits)
|
|
||||||
{
|
|
||||||
return * new(&buffer_) TX(forward<INITS> (inits)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TX>
|
|
||||||
TX&
|
|
||||||
access ()
|
|
||||||
{
|
|
||||||
return * std::launder (reinterpret_cast<TX*> (&buffer_[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** apply generic functor to the currently selected branch */
|
|
||||||
template<size_t idx, class FUN>
|
|
||||||
auto
|
|
||||||
selectBranch (FUN&& fun)
|
|
||||||
{
|
|
||||||
if constexpr (0 < idx)
|
|
||||||
if (branch_ < idx)
|
|
||||||
return selectBranch<idx-1> (forward<FUN>(fun));
|
|
||||||
return fun (get<idx>());
|
|
||||||
}
|
|
||||||
|
|
||||||
BranchCase() = default;
|
|
||||||
public:
|
|
||||||
template<class FUN>
|
|
||||||
auto
|
|
||||||
apply (FUN&& fun)
|
|
||||||
{
|
|
||||||
return selectBranch<TOP> (forward<FUN> (fun));
|
|
||||||
}
|
|
||||||
|
|
||||||
~BranchCase()
|
|
||||||
{
|
|
||||||
apply ([this](auto& it)
|
|
||||||
{ using Elm = decay_t<decltype(it)>;
|
|
||||||
access<Elm>().~Elm();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename...INITS>
|
|
||||||
BranchCase (size_t idx, INITS&& ...inits)
|
|
||||||
{
|
|
||||||
branch_ = idx;
|
|
||||||
apply ([&,this](auto& it)
|
|
||||||
{ using Elm = decay_t<decltype(it)>;
|
|
||||||
emplace<Elm> (forward<INITS> (inits)...);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
BranchCase (BranchCase const& o)
|
|
||||||
{
|
|
||||||
branch_ = o.branch_;
|
|
||||||
BranchCase& unConst = const_cast<BranchCase&> (o);
|
|
||||||
unConst.apply ([this](auto& it)
|
|
||||||
{ using Elm = decay_t<decltype(it)>;
|
|
||||||
this->emplace<Elm> (it);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
BranchCase (BranchCase && ro)
|
|
||||||
{
|
|
||||||
branch_ = ro.branch_;
|
|
||||||
ro.apply ([this](auto& it)
|
|
||||||
{ using Elm = decay_t<decltype(it)>;
|
|
||||||
this->emplace<Elm> (move (it));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
friend void
|
|
||||||
swap (BranchCase& o1, BranchCase o2)
|
|
||||||
{
|
|
||||||
using std::swap;
|
|
||||||
BranchCase tmp;
|
|
||||||
o1.apply ([&](auto& it)
|
|
||||||
{ using Elm = decay_t<decltype(it)>;
|
|
||||||
tmp.emplace<Elm> (move (o1.access<Elm>()));
|
|
||||||
});
|
|
||||||
swap (o1.branch_,o2.branch_);
|
|
||||||
o1.apply ([&](auto& it)
|
|
||||||
{ using Elm = decay_t<decltype(it)>;
|
|
||||||
o1.emplace<Elm> (move (o2.access<Elm>()));
|
|
||||||
});
|
|
||||||
o2.apply ([&](auto& it)
|
|
||||||
{ using Elm = decay_t<decltype(it)>;
|
|
||||||
o2.emplace<Elm> (move (tmp.access<Elm>()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
BranchCase&
|
|
||||||
operator= (BranchCase ref)
|
|
||||||
{
|
|
||||||
swap (*this, ref);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename...MORE>
|
|
||||||
auto
|
|
||||||
moveExtended()
|
|
||||||
{
|
|
||||||
using Extended = BranchCase<TYPES...,MORE...>;
|
|
||||||
Extended& upFaked = reinterpret_cast<Extended&> (*this);
|
|
||||||
return Extended (move (upFaked));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t
|
|
||||||
selected() const
|
|
||||||
{
|
|
||||||
return branch_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t idx>
|
|
||||||
SlotType<idx>&
|
|
||||||
get()
|
|
||||||
{
|
|
||||||
return access<SlotType<idx>>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
@ -334,8 +182,25 @@ namespace util {
|
||||||
*/
|
*/
|
||||||
template<typename...CASES>
|
template<typename...CASES>
|
||||||
struct AltModel
|
struct AltModel
|
||||||
|
: BranchCase<CASES...>
|
||||||
{
|
{
|
||||||
|
using _Model = BranchCase<CASES...>;
|
||||||
|
|
||||||
|
template<typename EX>
|
||||||
|
using Additionally = AltModel<CASES...,EX>;
|
||||||
|
|
||||||
|
template<typename INIT, typename =lib::meta::disable_if_self<AltModel,INIT>>
|
||||||
|
AltModel (INIT&& init)
|
||||||
|
: _Model{_Model::TOP, forward<INIT> (init)}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template<typename EX>
|
||||||
|
Additionally<EX>
|
||||||
|
addBranch()
|
||||||
|
{
|
||||||
|
Additionally<EX>& upFaked = reinterpret_cast<Additionally<EX>&> (*this);
|
||||||
|
return {move (upFaked)};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,12 @@ return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
||||||
TEST "CmdlineWrapper_test" CmdlineWrapper_test <<END
|
TEST "Package result alternatives" BranchCase_test <<END
|
||||||
|
return: 0
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
TEST "passing the commandline" CmdlineWrapper_test <<END
|
||||||
out-lit: wrapping cmdline:...
|
out-lit: wrapping cmdline:...
|
||||||
out-lit: -->
|
out-lit: -->
|
||||||
out-lit: wrapping cmdline:
|
out-lit: wrapping cmdline:
|
||||||
|
|
@ -43,7 +48,7 @@ return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
||||||
TEST "CustomSharedPtr_test" CustomSharedPtr_test <<END
|
TEST "Adapted shared pointer" CustomSharedPtr_test <<END
|
||||||
return: 0
|
return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
|
||||||
251
tests/library/branch-case-test.cpp
Normal file
251
tests/library/branch-case-test.cpp
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
BranchCase(Test) - verify parsing textual specifications
|
||||||
|
|
||||||
|
Copyright (C)
|
||||||
|
2024, Hermann Vosseler <Ichthyostega@web.de>
|
||||||
|
|
||||||
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
option) any later version. See the file COPYING for further details.
|
||||||
|
|
||||||
|
* *****************************************************************/
|
||||||
|
|
||||||
|
/** @file branch-case-test.cpp
|
||||||
|
** unit test \ref BranchCase_test
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "lib/test/run.hpp"
|
||||||
|
#include "lib/test/test-helper.hpp"
|
||||||
|
#include "lib/branch-case.hpp"
|
||||||
|
//#include "lib/iter-explorer.hpp"
|
||||||
|
//#include "lib/format-util.hpp"
|
||||||
|
#include "lib/meta/tuple-helper.hpp"
|
||||||
|
#include "lib/test/diagnostic-output.hpp"//////////////////TODO
|
||||||
|
//#include "lib/util.hpp"
|
||||||
|
|
||||||
|
//#include <vector>
|
||||||
|
//#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
namespace parse{
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
using lib::meta::is_Tuple;
|
||||||
|
using std::get;
|
||||||
|
// using util::join;
|
||||||
|
// using util::isnil;
|
||||||
|
// using std::vector;
|
||||||
|
// using std::shared_ptr;
|
||||||
|
// using std::make_shared;
|
||||||
|
|
||||||
|
// using LERR_(ITER_EXHAUST);
|
||||||
|
// using LERR_(INDEX_BOUNDS);
|
||||||
|
|
||||||
|
|
||||||
|
namespace { // test fixture
|
||||||
|
|
||||||
|
// const uint NUM_ELMS = 10;
|
||||||
|
|
||||||
|
// using Numz = vector<uint>;
|
||||||
|
|
||||||
|
} // (END)fixture
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************//**
|
||||||
|
* @test verify helpers and shortcuts for simple recursive descent parsing
|
||||||
|
* of structured data and specifications.
|
||||||
|
*
|
||||||
|
* @see parse.hpp
|
||||||
|
* @see proc-node.cpp "usage example"
|
||||||
|
*/
|
||||||
|
class BranchCase_test : public Test
|
||||||
|
{
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
run (Arg)
|
||||||
|
{
|
||||||
|
simpleBlah();
|
||||||
|
acceptAlternatives();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @test TODO just blah. */
|
||||||
|
void
|
||||||
|
simpleBlah ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if false ////////////////////////////////////////////////////////////////////////////TODO accommodate
|
||||||
|
/** @test define a terminal symbol to match by parse. */
|
||||||
|
void
|
||||||
|
acceptTerminal()
|
||||||
|
{
|
||||||
|
// set up a parser function to accept some token as terminal
|
||||||
|
auto parse = Parser{"hello (\\w+) world"};
|
||||||
|
string toParse{"hello vile world of power"};
|
||||||
|
auto eval = parse (toParse);
|
||||||
|
CHECK (eval.result);
|
||||||
|
auto res = *eval.result; // ◁——————————— the »result model« of a terminal parse is the RegExp-Matcher
|
||||||
|
CHECK (res.ready() and not res.empty());
|
||||||
|
CHECK (res.size() == "2"_expect );
|
||||||
|
CHECK (res.position() == "0"_expect );
|
||||||
|
CHECK (res.str() == "hello vile world"_expect );
|
||||||
|
CHECK (res[1] == "vile"_expect );
|
||||||
|
CHECK (res.suffix() == " of power"_expect );
|
||||||
|
|
||||||
|
auto syntax = Syntax{move (parse)}; // Build a syntax clause from the simple terminal symbol parser
|
||||||
|
CHECK (not syntax.hasResult());
|
||||||
|
syntax.parse (toParse);
|
||||||
|
CHECK (syntax.success()); // Syntax clause holds an implicit state from the last parse
|
||||||
|
CHECK (syntax.getResult()[1] == "vile"_expect);
|
||||||
|
|
||||||
|
// shorthand notation to start building a syntax
|
||||||
|
auto syntax2 = accept ("(\\w+) world");
|
||||||
|
CHECK (not syntax2.hasResult());
|
||||||
|
syntax2.parse (toParse);
|
||||||
|
CHECK (not syntax2.success());
|
||||||
|
string bye{"cruel world"};
|
||||||
|
syntax2.parse (bye);
|
||||||
|
CHECK (syntax2.success());
|
||||||
|
CHECK (syntax2.getResult()[1] == "cruel"_expect);
|
||||||
|
|
||||||
|
// going full circle: extract parser def from syntax
|
||||||
|
// using Conn = decltype(syntax2)::Connex;
|
||||||
|
// Conn conny{syntax2};
|
||||||
|
// auto parse2 = Parser{conny};
|
||||||
|
auto parse2 = Parser{syntax2.getConny()};
|
||||||
|
CHECK (eval.result->str(1) == "vile");
|
||||||
|
eval = parse2 (toParse);
|
||||||
|
CHECK (not eval.result);
|
||||||
|
eval = parse2 (bye);
|
||||||
|
CHECK (eval.result->str(1) == "cruel");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @test define a sequence of syntax structures to match by parse. */
|
||||||
|
void
|
||||||
|
acceptSequential()
|
||||||
|
{
|
||||||
|
// Demonstration: how sequence combinator works....
|
||||||
|
auto term1 = buildConnex ("hello");
|
||||||
|
auto term2 = buildConnex ("world");
|
||||||
|
auto parseSeq = [&](StrView toParse)
|
||||||
|
{
|
||||||
|
using R1 = decltype(term1)::Result;
|
||||||
|
using R2 = decltype(term2)::Result;
|
||||||
|
using ProductResult = std::tuple<R1,R2>;
|
||||||
|
using ProductEval = Eval<ProductResult>;
|
||||||
|
auto eval1 = term1.parse (toParse);
|
||||||
|
if (eval1.result)
|
||||||
|
{
|
||||||
|
uint end1 = eval1.consumed;
|
||||||
|
StrView restInput = toParse.substr(end1);
|
||||||
|
auto eval2 = term2.parse (restInput);
|
||||||
|
if (eval2.result)
|
||||||
|
{
|
||||||
|
uint consumedOverall = end1 + eval2.consumed;
|
||||||
|
return ProductEval{ProductResult{move(*eval1.result)
|
||||||
|
,move(*eval2.result)}
|
||||||
|
,consumedOverall
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ProductEval{std::nullopt};
|
||||||
|
};
|
||||||
|
string s1{"hello millions"};
|
||||||
|
string s2{"hello world"};
|
||||||
|
string s3{" hello world trade "};
|
||||||
|
|
||||||
|
auto e1 = parseSeq(s1);
|
||||||
|
CHECK (not e1.result); // Syntax 'hello'>>'world' does not accept "hello millions"
|
||||||
|
auto e2 = parseSeq(s2);
|
||||||
|
CHECK ( e2.result);
|
||||||
|
|
||||||
|
using SeqRes = std::decay_t<decltype(*e2.result)>; // Note: the result type depends on the actual syntax construction
|
||||||
|
CHECK (is_Tuple<SeqRes>()); // Result model from sequence is the tuple of terminal results
|
||||||
|
auto& [r1,r2] = *e2.result;
|
||||||
|
CHECK (r1.str() == "hello"_expect);
|
||||||
|
CHECK (r2.str() == "world"_expect);
|
||||||
|
|
||||||
|
CHECK (term2.parse(" world").result); // Note: leading whitespace skipped by the basic terminal parsers
|
||||||
|
CHECK (term2.parse("\n \t world ").result);
|
||||||
|
CHECK (not term2.parse(" old ").result);
|
||||||
|
|
||||||
|
|
||||||
|
// DSL parse clause builder: a sequence of terminals...
|
||||||
|
auto syntax = accept("hello").seq("world");
|
||||||
|
|
||||||
|
// Perform the same parse as demonstrated above....
|
||||||
|
CHECK (not syntax.hasResult());
|
||||||
|
syntax.parse(s1);
|
||||||
|
CHECK (not syntax.success());
|
||||||
|
syntax.parse(s2);
|
||||||
|
CHECK (syntax);
|
||||||
|
SeqRes seqModel = syntax.getResult();
|
||||||
|
CHECK (get<0>(seqModel).str() == "hello"_expect);
|
||||||
|
CHECK (get<1>(seqModel).str() == "world"_expect);
|
||||||
|
|
||||||
|
|
||||||
|
// can build extended clause from existing one
|
||||||
|
auto syntax2 = syntax.seq("trade");
|
||||||
|
CHECK (not syntax2.hasResult());
|
||||||
|
syntax2.parse(s2);
|
||||||
|
CHECK (not syntax2.success());
|
||||||
|
syntax2.parse(s3);
|
||||||
|
CHECK (syntax2.success());
|
||||||
|
auto seqModel2 = syntax2.getResult(); // Note: model of consecutive sequence is flattened into a single tuple
|
||||||
|
CHECK (get<0>(seqModel2).str() == "hello"_expect);
|
||||||
|
CHECK (get<1>(seqModel2).str() == "world"_expect);
|
||||||
|
CHECK (get<2>(seqModel2).str() == "trade"_expect);
|
||||||
|
}
|
||||||
|
#endif /////////////////////////////////////////////////////////////////////////////////////TODO accommodate
|
||||||
|
|
||||||
|
/** @test TODO define alternative syntax structures to match by parse. */
|
||||||
|
void
|
||||||
|
acceptAlternatives()
|
||||||
|
{
|
||||||
|
using Branch = BranchCase<char,ushort>;
|
||||||
|
SHOW_EXPR(sizeof(Branch));
|
||||||
|
Branch b1{1, 42};
|
||||||
|
SHOW_EXPR(b1.selected());
|
||||||
|
SHOW_EXPR(b1.SIZ);
|
||||||
|
SHOW_EXPR(b1.TOP);
|
||||||
|
SHOW_EXPR(b1.get<1>());
|
||||||
|
SHOW_EXPR(b1.get<0>());
|
||||||
|
Branch b2{0,'x'};
|
||||||
|
SHOW_EXPR(b2.selected());
|
||||||
|
SHOW_EXPR(b2.get<1>());
|
||||||
|
SHOW_EXPR(b2.get<0>());
|
||||||
|
Branch b3{b1};
|
||||||
|
SHOW_EXPR(b3.selected());
|
||||||
|
SHOW_EXPR(b3.get<1>());
|
||||||
|
SHOW_EXPR(b3.get<0>());
|
||||||
|
b3 = b2;
|
||||||
|
SHOW_EXPR(b3.selected());
|
||||||
|
SHOW_EXPR(b3.get<1>());
|
||||||
|
SHOW_EXPR(b3.get<0>());
|
||||||
|
auto bx = b1.moveExtended<string>();
|
||||||
|
SHOW_EXPR(sizeof(bx))
|
||||||
|
SHOW_EXPR(bx.SIZ);
|
||||||
|
SHOW_EXPR(bx.TOP);
|
||||||
|
SHOW_EXPR(bx.selected());
|
||||||
|
SHOW_EXPR(bx.get<1>());
|
||||||
|
SHOW_EXPR(bx.get<0>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LAUNCHER (BranchCase_test, "unit common");
|
||||||
|
|
||||||
|
|
||||||
|
}}} // namespace util::parse::test
|
||||||
|
|
||||||
|
|
@ -216,33 +216,32 @@ namespace test {
|
||||||
void
|
void
|
||||||
acceptAlternatives()
|
acceptAlternatives()
|
||||||
{
|
{
|
||||||
using Branch = BranchCase<char,ushort>;
|
using R1 = char;
|
||||||
SHOW_EXPR(sizeof(Branch));
|
using R2 = string;
|
||||||
Branch b1{1, 42};
|
using R3 = double;
|
||||||
SHOW_EXPR(b1.selected());
|
|
||||||
SHOW_EXPR(b1.SIZ);
|
using A1 = AltModel<R1>;
|
||||||
SHOW_EXPR(b1.TOP);
|
string s{"second"};
|
||||||
SHOW_EXPR(b1.get<1>());
|
using A2 = A1::Additionally<R2>;
|
||||||
SHOW_EXPR(b1.get<0>());
|
A2 model2{s};
|
||||||
Branch b2{0,'x'};
|
SHOW_EXPR(sizeof(A2));
|
||||||
SHOW_EXPR(b2.selected());
|
SHOW_EXPR(model2.SIZ);
|
||||||
SHOW_EXPR(b2.get<1>());
|
SHOW_EXPR(model2.TOP);
|
||||||
SHOW_EXPR(b2.get<0>());
|
SHOW_EXPR(model2.selected())
|
||||||
Branch b3{b1};
|
SHOW_EXPR(model2.get<1>())
|
||||||
SHOW_EXPR(b3.selected());
|
using A3 = A2::Additionally<R3>;
|
||||||
SHOW_EXPR(b3.get<1>());
|
A3 model3{model2.addBranch<R3>()};
|
||||||
SHOW_EXPR(b3.get<0>());
|
SHOW_TYPE(A3)
|
||||||
b3 = b2;
|
SHOW_EXPR(sizeof(A3));
|
||||||
SHOW_EXPR(b3.selected());
|
SHOW_EXPR(model3.SIZ);
|
||||||
SHOW_EXPR(b3.get<1>());
|
SHOW_EXPR(model3.TOP);
|
||||||
SHOW_EXPR(b3.get<0>());
|
SHOW_EXPR(model3.selected())
|
||||||
auto bx = b1.moveExtended<string>();
|
SHOW_EXPR(model3.get<1>())
|
||||||
SHOW_EXPR(sizeof(bx))
|
auto res = move(model3);
|
||||||
SHOW_EXPR(bx.SIZ);
|
SHOW_TYPE(decltype(res))
|
||||||
SHOW_EXPR(bx.TOP);
|
SHOW_EXPR(sizeof(res))
|
||||||
SHOW_EXPR(bx.selected());
|
SHOW_EXPR(res.selected())
|
||||||
SHOW_EXPR(bx.get<1>());
|
SHOW_EXPR(res.get<1>())
|
||||||
SHOW_EXPR(bx.get<0>());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55960,19 +55960,21 @@
|
||||||
<node CREATED="1737238022259" ID="ID_508598643" MODIFIED="1737238026071" TEXT="up-Copy">
|
<node CREATED="1737238022259" ID="ID_508598643" MODIFIED="1737238026071" TEXT="up-Copy">
|
||||||
<node CREATED="1737238037257" ID="ID_1788967087" MODIFIED="1737238050739" TEXT="gegeben: AltModel<N>"/>
|
<node CREATED="1737238037257" ID="ID_1788967087" MODIFIED="1737238050739" TEXT="gegeben: AltModel<N>"/>
|
||||||
<node CREATED="1737238051966" ID="ID_384770143" MODIFIED="1737238076015" TEXT="zu bauen: AltModel<N+1> mit kopierten Daten und gleichem Selektor"/>
|
<node CREATED="1737238051966" ID="ID_384770143" MODIFIED="1737238076015" TEXT="zu bauen: AltModel<N+1> mit kopierten Daten und gleichem Selektor"/>
|
||||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1737238094329" ID="ID_1160578555" MODIFIED="1737238106552" TEXT="braucht Trampolin für konkrete Kopie">
|
<node COLOR="#5b280f" CREATED="1737238094329" FOLDED="true" ID="ID_1160578555" MODIFIED="1737417012015" TEXT="braucht Trampolin für konkrete Kopie">
|
||||||
<icon BUILTIN="messagebox_warning"/>
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
|
<icon BUILTIN="button_cancel"/>
|
||||||
<node CREATED="1737238147756" ID="ID_1597388632" MODIFIED="1737238159884" TEXT="statisches Array von Funktionspointern"/>
|
<node CREATED="1737238147756" ID="ID_1597388632" MODIFIED="1737238159884" TEXT="statisches Array von Funktionspointern"/>
|
||||||
<node CREATED="1737238206786" ID="ID_784811" MODIFIED="1737238220532" TEXT="generische Signatur void(void*,void*)"/>
|
<node CREATED="1737238206786" ID="ID_784811" MODIFIED="1737238220532" TEXT="generische Signatur void(void*,void*)"/>
|
||||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1737238386277" ID="ID_499140874" MODIFIED="1737238392082" TEXT="ineffizient">
|
<node BACKGROUND_COLOR="#dfd986" COLOR="#ad014c" CREATED="1737238386277" ID="ID_499140874" MODIFIED="1737416856790" TEXT="ineffizient">
|
||||||
<icon BUILTIN="broken-line"/>
|
<icon BUILTIN="broken-line"/>
|
||||||
<node CREATED="1737238394241" ID="ID_1786923431" MODIFIED="1737238413594" TEXT="entweder haben wir N Teil-Arrays (Speicherverschwendung)"/>
|
<node CREATED="1737238394241" ID="ID_1786923431" MODIFIED="1737238413594" TEXT="entweder haben wir N Teil-Arrays (Speicherverschwendung)"/>
|
||||||
<node CREATED="1737238414398" ID="ID_1897860224" MODIFIED="1737238431951" TEXT="oder eine verkettete Liste von Closures (Laufzeitverschwendung)"/>
|
<node CREATED="1737238414398" ID="ID_1897860224" MODIFIED="1737238431951" TEXT="oder eine verkettete Liste von Closures (Laufzeitverschwendung)"/>
|
||||||
<node CREATED="1737238441426" ID="ID_896531017" MODIFIED="1737238466027" TEXT="und im schlimmsten Fall auch noch N consecutive copies"/>
|
<node CREATED="1737238441426" ID="ID_896531017" MODIFIED="1737238466027" TEXT="und im schlimmsten Fall auch noch N consecutive copies"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1737238578224" ID="ID_524632421" MODIFIED="1737238587563" TEXT="zu optimieren">
|
<node COLOR="#5b280f" CREATED="1737238578224" FOLDED="true" ID="ID_524632421" MODIFIED="1737417010319" TEXT="zu optimieren">
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
|
<icon BUILTIN="button_cancel"/>
|
||||||
<node CREATED="1737238589671" ID="ID_1560551329" MODIFIED="1737238601745" TEXT="Idee: Model-Binding in zwei Schritten">
|
<node CREATED="1737238589671" ID="ID_1560551329" MODIFIED="1737238601745" TEXT="Idee: Model-Binding in zwei Schritten">
|
||||||
<icon BUILTIN="idea"/>
|
<icon BUILTIN="idea"/>
|
||||||
<node CREATED="1737238606619" ID="ID_1441095840" MODIFIED="1737238917781" TEXT="Teilergebnis + Selektor-Nr durchreichen">
|
<node CREATED="1737238606619" ID="ID_1441095840" MODIFIED="1737238917781" TEXT="Teilergebnis + Selektor-Nr durchreichen">
|
||||||
|
|
@ -55990,7 +55992,7 @@
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1737242122676" ID="ID_486125380" MODIFIED="1737242129558" TEXT="es ist nicht so einfach">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737242122676" ID="ID_486125380" MODIFIED="1737416836436" TEXT="es ist nicht so einfach">
|
||||||
<icon BUILTIN="messagebox_warning"/>
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
<node CREATED="1737242181419" ID="ID_699910063" MODIFIED="1737242197252" TEXT="wir geben nun mal über eine Kette verschachtelter Funktoren zurück"/>
|
<node CREATED="1737242181419" ID="ID_699910063" MODIFIED="1737242197252" TEXT="wir geben nun mal über eine Kette verschachtelter Funktoren zurück"/>
|
||||||
<node CREATED="1737242567334" ID="ID_1304062723" MODIFIED="1737242586617" TEXT="sobald der erzeugende Scope verlassen wird, ist nur noch ein Summen-Typ bekannt"/>
|
<node CREATED="1737242567334" ID="ID_1304062723" MODIFIED="1737242586617" TEXT="sobald der erzeugende Scope verlassen wird, ist nur noch ein Summen-Typ bekannt"/>
|
||||||
|
|
@ -56024,14 +56026,15 @@
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1737244421643" ID="ID_1284583110" MODIFIED="1737245500026" TEXT="intermediärer Ergebnis-Typ: BranchResultClosure">
|
<node COLOR="#5b280f" CREATED="1737244421643" ID="ID_1284583110" MODIFIED="1737416868792" TEXT="intermediärer Ergebnis-Typ: BranchResultClosure">
|
||||||
<icon BUILTIN="help"/>
|
<icon BUILTIN="help"/>
|
||||||
|
<icon BUILTIN="button_cancel"/>
|
||||||
<node CREATED="1737245502249" ID="ID_1174923923" MODIFIED="1737245508829" TEXT="noch nicht klar ob notwendig">
|
<node CREATED="1737245502249" ID="ID_1174923923" MODIFIED="1737245508829" TEXT="noch nicht klar ob notwendig">
|
||||||
<node CREATED="1737308551745" ID="ID_1909384704" MODIFIED="1737308569043" TEXT="denn Closure ≙ dynamischer Dispatch"/>
|
<node CREATED="1737308551745" ID="ID_1909384704" MODIFIED="1737308569043" TEXT="denn Closure ≙ dynamischer Dispatch"/>
|
||||||
<node CREATED="1737308586765" ID="ID_1360651233" MODIFIED="1737308606555" TEXT="die ganze sonstiger »Parser-Code-Insel« ist rein-statitsch typisiert"/>
|
<node CREATED="1737308586765" ID="ID_1360651233" MODIFIED="1737308606555" TEXT="die ganze sonstiger »Parser-Code-Insel« ist rein-statitsch typisiert"/>
|
||||||
<node CREATED="1737308671866" ID="ID_1034537096" MODIFIED="1737308702736" TEXT="Zahl der Branches klein ⟹ statische Impl im Vorteil"/>
|
<node CREATED="1737308671866" ID="ID_1034537096" MODIFIED="1737308702736" TEXT="Zahl der Branches klein ⟹ statische Impl im Vorteil"/>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1737245511448" ID="ID_396620339" MODIFIED="1737245792925" TEXT="Alternativ: Rückübersetzung Selector ⟼ Typ-Kontext durch rekursive Funktionen">
|
<node CREATED="1737245511448" ID="ID_396620339" MODIFIED="1737416947927" TEXT="Alternativ: Rückübersetzung Selector ⟼ Typ-Kontext durch rekursive Funktionen">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -56040,21 +56043,29 @@
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
|
<arrowlink COLOR="#5c6ba3" DESTINATION="ID_724398426" ENDARROW="Default" ENDINCLINATION="134;0;" ID="Arrow_ID_961310703" STARTARROW="None" STARTINCLINATION="-244;9;"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
<node COLOR="#435e98" CREATED="1737416878486" ID="ID_724398426" MODIFIED="1737417001411" TEXT="versuche Zugang zum aktiven Zweig via rekursive Funktion">
|
||||||
|
<arrowlink COLOR="#3dad9b" DESTINATION="ID_1738176168" ENDARROW="Default" ENDINCLINATION="-15;-187;" ID="Arrow_ID_387275034" STARTARROW="None" STARTINCLINATION="-287;14;"/>
|
||||||
|
<linktarget COLOR="#5c6ba3" DESTINATION="ID_724398426" ENDARROW="Default" ENDINCLINATION="134;0;" ID="Arrow_ID_961310703" SOURCE="ID_396620339" STARTARROW="None" STARTINCLINATION="-244;9;"/>
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737245801576" ID="ID_1738176168" MODIFIED="1737400259658" TEXT="Skizze Datentyp">
|
</node>
|
||||||
<icon BUILTIN="pencil"/>
|
<node COLOR="#338800" CREATED="1737245801576" ID="ID_1738176168" MODIFIED="1737416989050" TEXT="Skizze Datentyp">
|
||||||
<node CREATED="1737308328478" ID="ID_993665414" MODIFIED="1737308352116" TEXT="erst mal einen uninitialised byte-Puffer in Basisklasse"/>
|
<linktarget COLOR="#3dad9b" DESTINATION="ID_1738176168" ENDARROW="Default" ENDINCLINATION="-15;-187;" ID="Arrow_ID_387275034" SOURCE="ID_724398426" STARTARROW="None" STARTINCLINATION="-287;14;"/>
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node CREATED="1737308328478" ID="ID_993665414" MODIFIED="1737358352116" TEXT="erst mal einen uninitialised byte-Puffer in Basisklasse"/>
|
||||||
<node CREATED="1737308370978" ID="ID_1202779435" MODIFIED="1737308383699" TEXT="typisierter Summentyp darübergelegt"/>
|
<node CREATED="1737308370978" ID="ID_1202779435" MODIFIED="1737308383699" TEXT="typisierter Summentyp darübergelegt"/>
|
||||||
<node CREATED="1737308384535" ID="ID_1448196900" MODIFIED="1737308394626" TEXT="Anordnung der Typ-Parameter: Rückwärts gehend">
|
<node CREATED="1737308384535" ID="ID_1448196900" MODIFIED="1737308394626" TEXT="Anordnung der Typ-Parameter: Rückwärts gehend">
|
||||||
<node CREATED="1737308397038" ID="ID_977244135" MODIFIED="1737308410928" TEXT="also der letzte / höchste Zweig zuerst"/>
|
<node CREATED="1737308397038" ID="ID_977244135" MODIFIED="1737308410928" TEXT="also der letzte / höchste Zweig zuerst"/>
|
||||||
<node CREATED="1737308411588" ID="ID_1539400054" MODIFIED="1737308423294" TEXT="damit rekursiv-delegierende Implementierung möglich"/>
|
<node CREATED="1737308411588" ID="ID_1539400054" MODIFIED="1737308423294" TEXT="damit rekursiv-delegierende Implementierung möglich"/>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1737309034680" ID="ID_1283731567" MODIFIED="1737309052170" TEXT="Code-Struktur überlegen">
|
<node COLOR="#338800" CREATED="1737309034680" ID="ID_1283731567" MODIFIED="1737416599812" TEXT="Code-Struktur überlegen">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
<node CREATED="1737309053966" ID="ID_1359722232" MODIFIED="1737309190105" TEXT="Destuktor aufrufen ?">
|
<node CREATED="1737309053966" ID="ID_1359722232" MODIFIED="1737309190105" TEXT="Destuktor aufrufen ?">
|
||||||
<node BACKGROUND_COLOR="#fefc4e" COLOR="#351d75" CREATED="1737309093248" ID="ID_321904108" MODIFIED="1737309152195" TEXT="�� Invariante: stets ein Zweig belegt">
|
<node BACKGROUND_COLOR="#fefc4e" COLOR="#351d75" CREATED="1737309093248" ID="ID_321904108" MODIFIED="1737309152195" TEXT="�� Invariante: stets ein Zweig belegt">
|
||||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||||
|
|
@ -56065,7 +56076,7 @@
|
||||||
<node CREATED="1737309245044" ID="ID_1229816718" MODIFIED="1737309255638" TEXT="er müßte nämlich den Typ im Buffer kennen"/>
|
<node CREATED="1737309245044" ID="ID_1229816718" MODIFIED="1737309255638" TEXT="er müßte nämlich den Typ im Buffer kennen"/>
|
||||||
<node CREATED="1737309258330" ID="ID_414435446" MODIFIED="1737309277292" TEXT="sonst ist es mehr wie eine Member-Komponente"/>
|
<node CREATED="1737309258330" ID="ID_414435446" MODIFIED="1737309277292" TEXT="sonst ist es mehr wie eine Member-Komponente"/>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1737309306808" ID="ID_1247810717" MODIFIED="1737309311710" TEXT="zwei Alternativen...">
|
<node COLOR="#435e98" CREATED="1737309306808" FOLDED="true" ID="ID_1247810717" MODIFIED="1737416659077" TEXT="zwei Alternativen...">
|
||||||
<node CREATED="1737309312755" ID="ID_1765693019" MODIFIED="1737323819640" TEXT="inkrementeller Dekorator">
|
<node CREATED="1737309312755" ID="ID_1765693019" MODIFIED="1737323819640" TEXT="inkrementeller Dekorator">
|
||||||
<icon BUILTIN="full-1"/>
|
<icon BUILTIN="full-1"/>
|
||||||
<node CREATED="1737309344095" ID="ID_1218238487" MODIFIED="1737309351610" TEXT="Buffer ist tatsächlich Basis"/>
|
<node CREATED="1737309344095" ID="ID_1218238487" MODIFIED="1737309351610" TEXT="Buffer ist tatsächlich Basis"/>
|
||||||
|
|
@ -56086,8 +56097,8 @@
|
||||||
<icon BUILTIN="full-2"/>
|
<icon BUILTIN="full-2"/>
|
||||||
<node CREATED="1737309866960" ID="ID_1933240925" MODIFIED="1737309878323" TEXT="es gibt nur ein Objekt, das den Buffer direkt (private) hält"/>
|
<node CREATED="1737309866960" ID="ID_1933240925" MODIFIED="1737309878323" TEXT="es gibt nur ein Objekt, das den Buffer direkt (private) hält"/>
|
||||||
<node CREATED="1737309879188" ID="ID_1269779979" MODIFIED="1737309905040" TEXT="für jeden Aufruf wird rekursiv eine Typ-Projektion darübergelegt für die Zugriffe"/>
|
<node CREATED="1737309879188" ID="ID_1269779979" MODIFIED="1737309905040" TEXT="für jeden Aufruf wird rekursiv eine Typ-Projektion darübergelegt für die Zugriffe"/>
|
||||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737309983889" ID="ID_217989124" MODIFIED="1737309993912" TEXT="Machbarkeit nicht klar ⟹ Prototyping">
|
<node COLOR="#435e98" CREATED="1737309983889" ID="ID_217989124" MODIFIED="1737416577611" TEXT="Machbarkeit nicht klar ⟹ Prototyping">
|
||||||
<icon BUILTIN="pencil"/>
|
<icon BUILTIN="yes"/>
|
||||||
<node CREATED="1737309995672" ID="ID_317094642" MODIFIED="1737310007874" TEXT="brauche rekursiv getypte Hilfsfunktionen">
|
<node CREATED="1737309995672" ID="ID_317094642" MODIFIED="1737310007874" TEXT="brauche rekursiv getypte Hilfsfunktionen">
|
||||||
<node CREATED="1737310409584" ID="ID_1587656830" MODIFIED="1737310412828" TEXT="emplace"/>
|
<node CREATED="1737310409584" ID="ID_1587656830" MODIFIED="1737310412828" TEXT="emplace"/>
|
||||||
<node CREATED="1737310413472" ID="ID_190878994" MODIFIED="1737310416083" TEXT="destroy"/>
|
<node CREATED="1737310413472" ID="ID_190878994" MODIFIED="1737310416083" TEXT="destroy"/>
|
||||||
|
|
@ -56137,19 +56148,20 @@
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
<icon BUILTIN="forward"/>
|
<icon BUILTIN="forward"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1737317456624" ID="ID_846126551" MODIFIED="1737317483349" TEXT="grundsätzliches Problem: Variant-Returntype nicht möglich">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737317456624" ID="ID_846126551" MODIFIED="1737416545012" TEXT="grundsätzliches Problem: Variant-Returntype nicht möglich">
|
||||||
<icon BUILTIN="messagebox_warning"/>
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
<node COLOR="#5b280f" CREATED="1737317489124" ID="ID_233312745" MODIFIED="1737317528208" TEXT="Funktion kann keinen vom Parameter abhängigen Rückgabetyp haben">
|
<node COLOR="#5b280f" CREATED="1737317489124" ID="ID_233312745" MODIFIED="1737317528208" TEXT="Funktion kann keinen vom Parameter abhängigen Rückgabetyp haben">
|
||||||
<icon BUILTIN="closed"/>
|
<icon BUILTIN="closed"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1737317639568" ID="ID_526309958" MODIFIED="1737317717888" TEXT="diese Einschränkung betrifft jedes Konstrukt für einen Summen-Typ (in C++)">
|
<node BACKGROUND_COLOR="#e6ce96" COLOR="#fa002a" CREATED="1737317639568" ID="ID_526309958" MODIFIED="1737416557265" TEXT="diese Einschränkung betrifft jedes Konstrukt für einen Summen-Typ (in C++)">
|
||||||
<arrowlink COLOR="#d2005b" DESTINATION="ID_1314826159" ENDARROW="Default" ENDINCLINATION="58;-95;" ID="Arrow_ID_1280018433" STARTARROW="None" STARTINCLINATION="-542;20;"/>
|
<arrowlink COLOR="#d2005b" DESTINATION="ID_1314826159" ENDARROW="Default" ENDINCLINATION="58;-95;" ID="Arrow_ID_1280018433" STARTARROW="None" STARTINCLINATION="-542;20;"/>
|
||||||
<icon BUILTIN="clanbomber"/>
|
<icon BUILTIN="clanbomber"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1737323796942" ID="ID_1671873045" MODIFIED="1737323808699" TEXT="Diskussion">
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1737323796942" ID="ID_1671873045" MODIFIED="1737416667635" TEXT="Diskussion">
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
<node CREATED="1737323821990" ID="ID_1562513052" MODIFIED="1737323951827" TEXT="die Variante-2 erschien mir zunächst attraktiver">
|
<node CREATED="1737323821990" ID="ID_1562513052" MODIFIED="1737323951827" TEXT="die Variante-2 erschien mir zunächst attraktiver">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
|
@ -56190,8 +56202,7 @@
|
||||||
...weil praktisch alle Kern-Methoden nun in zweifacher Ausfertigung gecodet werden müssen: einmal rekursiv, und einmal für den Abschluß
|
...weil praktisch alle Kern-Methoden nun in zweifacher Ausfertigung gecodet werden müssen: einmal rekursiv, und einmal für den Abschluß
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html></richcontent>
|
||||||
</richcontent>
|
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1737392934472" ID="ID_642107000" MODIFIED="1737393084265" TEXT="zudem erzwingt Variante-1 eine umgekehrte Ordnung der Typ-Parameter">
|
<node CREATED="1737392934472" ID="ID_642107000" MODIFIED="1737393084265" TEXT="zudem erzwingt Variante-1 eine umgekehrte Ordnung der Typ-Parameter">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
|
@ -56207,8 +56218,7 @@
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737317603366" FOLDED="true" ID="ID_1314826159" MODIFIED="1737416679265" TEXT="grundsätzliche Einschränkung: Zugriff erfordert statisch bekannten Typ">
|
||||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1737317603366" ID="ID_1314826159" MODIFIED="1737317708664" TEXT="grundsätzliche Einschränkung: Zugriff erfordert statisch bekannten Typ">
|
|
||||||
<linktarget COLOR="#d2005b" DESTINATION="ID_1314826159" ENDARROW="Default" ENDINCLINATION="58;-95;" ID="Arrow_ID_1280018433" SOURCE="ID_526309958" STARTARROW="None" STARTINCLINATION="-542;20;"/>
|
<linktarget COLOR="#d2005b" DESTINATION="ID_1314826159" ENDARROW="Default" ENDINCLINATION="58;-95;" ID="Arrow_ID_1280018433" SOURCE="ID_526309958" STARTARROW="None" STARTINCLINATION="-542;20;"/>
|
||||||
<icon BUILTIN="messagebox_warning"/>
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
<node CREATED="1737317726468" ID="ID_1400201299" MODIFIED="1737317872607" TEXT="jeder »Varant«-Type (und auch Union) unterliegt dieser Einschränkung"/>
|
<node CREATED="1737317726468" ID="ID_1400201299" MODIFIED="1737317872607" TEXT="jeder »Varant«-Type (und auch Union) unterliegt dieser Einschränkung"/>
|
||||||
|
|
@ -56341,9 +56351,28 @@
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1737416683769" ID="ID_529397551" MODIFIED="1737416793839" STYLE="fork">
|
||||||
|
<richcontent TYPE="NODE"><html>
|
||||||
|
<head/>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
<b>Fazit</b>: implementierbar mit generischem λ-Visitor
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
<font NAME="SansSerif" SIZE="12"/>
|
||||||
|
<icon BUILTIN="forward"/>
|
||||||
|
<node COLOR="#78442f" CREATED="1737416738497" ID="ID_1423783090" MODIFIED="1737416781408" TEXT="nicht schön">
|
||||||
|
<icon BUILTIN="smiley-oh"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737395464420" ID="ID_1924549712" MODIFIED="1737400254287" STYLE="fork" TEXT="Konstruktor und Zuweisung">
|
<node COLOR="#78442f" CREATED="1737416754887" ID="ID_1690525518" MODIFIED="1737416781408" TEXT="mehr so grade noch die Kurve gekratzt">
|
||||||
<icon BUILTIN="pencil"/>
|
<icon BUILTIN="smiley-oh"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#338800" CREATED="1737395464420" ID="ID_1924549712" MODIFIED="1737416078316" TEXT="Konstruktor und Zuweisung">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
<node COLOR="#338800" CREATED="1737395472148" ID="ID_1934503205" MODIFIED="1737400253142" TEXT="zunächst einmal: Konstruktor immer auf den TOP-Slot">
|
<node COLOR="#338800" CREATED="1737395472148" ID="ID_1934503205" MODIFIED="1737400253142" TEXT="zunächst einmal: Konstruktor immer auf den TOP-Slot">
|
||||||
<icon BUILTIN="button_ok"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
</node>
|
</node>
|
||||||
|
|
@ -56362,10 +56391,40 @@
|
||||||
<node COLOR="#338800" CREATED="1737400227088" ID="ID_389977912" MODIFIED="1737400253142" TEXT="Extension in erweiterten Branch">
|
<node COLOR="#338800" CREATED="1737400227088" ID="ID_389977912" MODIFIED="1737400253142" TEXT="Extension in erweiterten Branch">
|
||||||
<icon BUILTIN="button_ok"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
</node>
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737416084226" ID="ID_485111355" MODIFIED="1737416132543" TEXT="muß Lambda für alle Zweige compilierbar machen">
|
||||||
|
<icon BUILTIN="broken-line"/>
|
||||||
|
<node CREATED="1737416138738" ID="ID_591886707" MODIFIED="1737416157124" TEXT="ärgerlich — stehe mit dem Rücken zur Wand hier"/>
|
||||||
|
<node CREATED="1737416487683" ID="ID_136717181" MODIFIED="1737416503156" TEXT="das Lambda wird für alle Typen instantiiert"/>
|
||||||
|
<node CREATED="1737416505524" ID="ID_456255326" MODIFIED="1737416522220" TEXT="abdichten mit std::is_constructible">
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737417020140" ID="ID_1230396959" MODIFIED="1737417037546" TEXT="sehr komplex ⟹ in Hilfskomponente auslagern">
|
||||||
|
<icon BUILTIN="pencil"/>
|
||||||
|
<node CREATED="1737417038777" ID="ID_158901588" MODIFIED="1737417051363" TEXT="lib/branch-case.hpp"/>
|
||||||
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737417051936" ID="ID_1310118315" MODIFIED="1737417056450" TEXT="BranchCase_test">
|
||||||
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737417060920" ID="ID_644848240" MODIFIED="1737417078580" TEXT="auf dieser Basis das AltModel definieren">
|
||||||
|
<icon BUILTIN="pencil"/>
|
||||||
|
<node COLOR="#338800" CREATED="1737417079594" ID="ID_883955221" MODIFIED="1737417091878" TEXT="erst mal die Einzelschritte durchspielen">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1737417093057" ID="ID_1036480281" MODIFIED="1737417121178" TEXT="Typ konstruieren"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1737417099856" ID="ID_820603798" MODIFIED="1737417121178" TEXT="einen Branch belegen"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1737417104216" ID="ID_188551502" MODIFIED="1737417121178" TEXT="danach noch ein up-Copy"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737417129349" ID="ID_1317057698" MODIFIED="1737417137972" TEXT="Struktur für den Kombinator darstellen">
|
||||||
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737417144217" ID="ID_375516701" MODIFIED="1737417153090" TEXT="in einen Connex-Builder verpacken">
|
||||||
|
<icon BUILTIN="flag-yellow"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
<node CREATED="1737048820482" ID="ID_235554745" MODIFIED="1737048832524" TEXT="generisches Model-Binding"/>
|
<node CREATED="1737048820482" ID="ID_235554745" MODIFIED="1737048832524" TEXT="generisches Model-Binding"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue