TreeExplorer: reimplementation with simpler design

- always layer the TreeExplorer (builder) on top of the stack
- always intersperse an IterableDecorator in between adjacent layers
- consequently...
  * each layer implementation is now a "state core"
  * and the source is now always a Lumiera Iterator

This greatly simplifies all the type rebindings and avoids the
ambiguities in argument converison. Basically now we can always convert
down, and we just need to pick the result type of the bound functor.

Downside is we have now always an adaptation wrapper in between,
but we can assume the compiler is able to optimise such inline
accessors away without overhead.
This commit is contained in:
Fischlurch 2017-12-03 04:24:02 +01:00
parent e58e4553f4
commit b5453cc429
5 changed files with 86 additions and 118 deletions

View file

@ -362,7 +362,7 @@ namespace diff{
{
binding_.inject (move(*found));
}
return found;
return bool(found);
}
else
return PAR::findSrc (refSpec);

View file

@ -164,7 +164,7 @@ namespace lib {
IterableDecorator& operator= (IterableDecorator&&) =default;
IterableDecorator& operator= (IterableDecorator const&) =default;
operator bool() const { return isValid(); }
explicit operator bool() const { return isValid(); }
/* === lumiera forward iterator concept === */
@ -225,49 +225,6 @@ namespace lib {
}
};
/** @todo WIP 11/17 */
template<class IT>
class WrappedIteratorCore
: public IT
{
public:
template<typename...ARGS>
WrappedIteratorCore (ARGS&& ...init)
: IT(std::forward<ARGS>(init)...)
{ }
WrappedIteratorCore() =default;
WrappedIteratorCore (WrappedIteratorCore&&) =default;
WrappedIteratorCore (WrappedIteratorCore const&) =default;
WrappedIteratorCore& operator= (WrappedIteratorCore&&) =default;
WrappedIteratorCore& operator= (WrappedIteratorCore const&) =default;
protected: /* === Iteration control API for IterableDecorator === */
friend bool
checkPoint (WrappedIteratorCore const& core)
{
return core.isValid();
}
friend typename IT::reference
yield (WrappedIteratorCore const& core)
{
return *core;
}
friend void
iterNext (WrappedIteratorCore & core)
{
++core;
}
};
}//(End) namespace iter_explorer : predefined policies and configurations
@ -343,14 +300,12 @@ namespace lib {
{
using SrcVal = typename CoreYield<SRC>::value_type;
using SrcIter = iter_explorer::IterableDecorator<SrcVal, SRC>;
using SrcCore = SRC;
};
template<class SRC>
struct _DecoratorTraits<SRC, enable_if<shall_use_Lumiera_Iter<SRC>>>
{
using SrcIter = remove_reference_t<SRC>;
using SrcCore = iter_explorer::WrappedIteratorCore<SRC>;
using SrcVal = typename SrcIter::value_type;
};
@ -360,7 +315,6 @@ namespace lib {
static_assert (not std::is_rvalue_reference<SRC>::value,
"container needs to exist elsewhere during the lifetime of the iteration");
using SrcIter = iter_explorer::StlRange<SRC>;
using SrcCore = iter_explorer::WrappedIteratorCore<SrcIter>;
using SrcVal = typename SrcIter::value_type;
};
@ -422,36 +376,17 @@ namespace lib {
using FunArgType = remove_reference_t<Arg>;
static_assert (std::is_convertible<ARG, FunArgType>::value,
"the expansion functor must accept the source iterator or state core as parameter");
test::TypeDebugger<FunArgType> guggi;
static auto build() { return [](ARG& arg) -> ARG& { return arg; }; }
};
/** adapt to a functor, which accepts the value type of the source sequence ("monadic" usage pattern) */
template<class IT>
struct ArgAccessor<IT, enable_if<__and_<shall_use_Lumiera_Iter<IT>
,is_convertible<typename IT::value_type, Arg>>>>
struct ArgAccessor<IT, enable_if<is_convertible<typename IT::value_type, Arg>>>
{
static auto build() { return [](auto& iter) { return *iter; }; }
};
/** in a similar way, adapt when the passed source argument is a "state core" ("monadic" usage pattern) */
template<class COR>
struct ArgAccessor<COR, enable_if<__and_<is_StateCore<COR>
,is_convertible<typename CoreYield<COR>::value_type, Arg>>>>
{
// test::TypeDebugger<COR> buggi;
static auto build() { return [](COR const& core) { return yield(core); }; }
};
template<class COR>
struct ArgAccessor<COR, enable_if<__and_<is_StateCore<COR>
,std::is_same<SRC&, Arg>>>>
{
// test::TypeDebugger<COR> muggi;
static auto build() { return [](COR& core) ->SRC& { return static_cast<SRC&> (core); }; }
};
/** holder for the suitably adapted _expansion functor_ */
struct Functor
@ -501,8 +436,8 @@ namespace lib {
class Expander
: public SRC
{
using SrcIter = typename SRC::SrcIter;
using _Traits = _ExpansionTraits<FUN,SrcIter>;
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
using _Traits = _ExpansionTraits<FUN,SRC>;
using ExpandFunctor = typename _Traits::Functor;
using ResIter = typename _DecoratorTraits<typename _Traits::Res>::SrcIter;
@ -517,7 +452,7 @@ namespace lib {
// inherited default copy operations
Expander (SRC&& parentExplorer, FUN&& expandFunctor)
: SRC{move (parentExplorer)}
: SRC{move (parentExplorer)} // NOTE: slicing move to strip TreeExplorer (Builder)
, expandChildren_{forward<FUN> (expandFunctor)}
, expansions_{}
{ }
@ -525,7 +460,7 @@ namespace lib {
/** core operation: expand current head element */
Expander&
expand()
expandChildren()
{
REQUIRE (checkPoint(*this), "attempt to expand an empty explorer");
@ -581,14 +516,12 @@ namespace lib {
/**
*
*/
template<class COR, class FUN>
template<class SRC, class FUN>
class Transformer
: public COR
: public SRC
{
using SrcIter = typename _DecoratorTraits<COR>::SrcIter;
using _Traits = _ExpansionTraits<FUN,SrcIter>;
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
using _Traits = _ExpansionTraits<FUN,SRC>;
using Res = typename _Traits::Res;
using TransformFunctor = typename _Traits::Functor;
@ -606,8 +539,8 @@ namespace lib {
Transformer() =default;
// inherited default copy operations
Transformer (COR&& parentCore, FUN&& transformFunctor)
: COR{move (parentCore)}
Transformer (SRC&& dataSrc, FUN&& transformFunctor)
: SRC{move (dataSrc)}
, trafo_{forward<FUN> (transformFunctor)}
{ }
@ -617,7 +550,7 @@ namespace lib {
friend bool
checkPoint (Transformer const& tx)
{
return checkPoint (tx.core());
return bool(tx.srcIter());
}
friend reference
@ -629,13 +562,13 @@ namespace lib {
friend void
iterNext (Transformer & tx)
{
iterNext (tx.core());
++ tx.srcIter();
tx.treated_.reset();
}
private:
COR&
core() const
SRC&
srcIter() const
{
return unConst(*this);
}
@ -643,8 +576,8 @@ namespace lib {
reference
invokeTransformation ()
{
if (not treated_)
treated_ = trafo_(core());
if (not treated_) // invoke transform function once per src item
treated_ = trafo_(srcIter());
return *treated_;
}
};
@ -665,13 +598,13 @@ namespace lib {
class TreeExplorer
: public SRC
{
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
public:
using SrcIter = SRC;
using value_type = typename SrcIter::value_type;
using reference = typename SrcIter::reference;
using pointer = typename SrcIter::pointer;
using value_type = typename meta::TypeBinding<SRC>::value_type;
using reference = typename meta::TypeBinding<SRC>::reference;
using pointer = typename meta::TypeBinding<SRC>::pointer;
/** by default create an empty iterator */
@ -731,14 +664,10 @@ namespace lib {
auto
expand (FUN&& expandFunctor)
{
using This = typename meta::Strip<decltype(*this)>::TypeReferred;
using SrcIter = typename _DecoratorTraits<This>::SrcIter;
using Value = typename SrcIter::value_type;
using Core = iter_explorer::Expander<SrcIter, FUN>;
using ResCore = iter_explorer::Expander<SRC, FUN>;
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
using ExpandableExplorer = iter_explorer::IterableDecorator<Value, Core>;
return ExpandableExplorer{move(*this), forward<FUN>(expandFunctor)};
return TreeExplorer<ResIter> (ResCore {move(*this), forward<FUN>(expandFunctor)});
}
@ -748,14 +677,10 @@ namespace lib {
auto
transform (FUN&& transformFunctor)
{
using This = typename meta::Strip<decltype(*this)>::TypeReferred;
using SrcCore = typename _DecoratorTraits<This>::SrcCore;
using ResCore = iter_explorer::Transformer<SrcCore, FUN>;
using Value = typename ResCore::value_type;
using ResCore = iter_explorer::Transformer<SRC, FUN>;
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
using TransformedExplorer = iter_explorer::IterableDecorator<Value, ResCore>;
return TransformedExplorer{move(*this), forward<FUN>(transformFunctor)};
return TreeExplorer<ResIter> (ResCore {move(*this), forward<FUN>(transformFunctor)});
}
private:

View file

@ -435,7 +435,7 @@ namespace meta {
META_DETECT_OPERATOR_INC();
public:
enum{ value = std::is_convertible<Type, bool>::value
enum{ value = std::is_constructible<bool, Type>::value
&& HasNested_value_type<Type>::value
&& HasOperator_deref<Type>::value
&& HasOperator_inc<Type>::value

View file

@ -337,7 +337,6 @@ namespace test{
.expand([](uint j){ return CountDown{j-1}; }) // expand-functor: Val > StateCore
);
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888
verify_treeExpandingIterator(
treeExplore(CountDown{5})
.expand([](uint j){ return NumberSequence{j-1}; }) // expand-functor: Val > Iter
@ -361,7 +360,6 @@ namespace test{
// test routine called the expansion functor five times
CHECK (5 == childBuffer.size());
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888
@ -372,13 +370,12 @@ namespace test{
.expand([](CountDown const& core){ return CountDown{ yield(core) - 1}; }) // expand-functor: StateCore const& -> StateCore
);
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888
verify_treeExpandingIterator(
treeExplore(CountDown{5})
.expand([](CountDown core){ return NumberSequence{ yield(core) - 1}; }) // expand-functor: StateCore -> Iter
);
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1118 : GDB Segfault on loading the inferior
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1118 : Generated code works just fine and passes Test though
verify_treeExpandingIterator(
treeExplore(CountDown{5})
@ -389,7 +386,6 @@ namespace test{
treeExplore(CountDown{5})
.expand([](auto it){ return decltype(it){ *it - 1}; }) // generic Lambda: Iter -> Iter
);
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1118 : GDB Segfault on loading the inferior
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1118 : GDB Segfault on loading the inferior
}
@ -404,13 +400,13 @@ namespace test{
CHECK (4 == *ii);
CHECK (0 == ii.depth());
ii.expand();
ii.expandChildren();
CHECK (3 == *ii);
CHECK (1 == ii.depth());
++ii;
CHECK (2 == *ii);
CHECK (1 == ii.depth());
ii.expand();
ii.expandChildren();
CHECK (1 == *ii);
CHECK (2 == ii.depth());
++ii;
@ -420,20 +416,20 @@ namespace test{
CHECK (3 == *ii);
CHECK (0 == ii.depth());
CHECK (materialise(ii) == "3-2-1");
ii.expand();
ii.expandChildren();
CHECK (1 == ii.depth());
CHECK (materialise(ii) == "2-1-2-1");
++++ii;
CHECK (0 == ii.depth());
CHECK (materialise(ii) == "2-1");
ii.expand();
ii.expandChildren();
CHECK (1 == ii.depth());
CHECK (materialise(ii) == "1-1");
++ii;
CHECK (0 == ii.depth());
CHECK (1 == *ii);
CHECK (materialise(ii) == "1");
ii.expand();
ii.expandChildren();
CHECK (isnil (ii));
VERIFY_ERROR (ITER_EXHAUST, *ii );
VERIFY_ERROR (ITER_EXHAUST, ++ii );
@ -452,6 +448,7 @@ namespace test{
void
verify_transformOperation()
{
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888
auto multiply = [](int v){ return 2*v; };
_Fmt embrace{"≺%s≻"};
@ -524,7 +521,6 @@ namespace test{
++jj;
CHECK (fact == 2*23);
CHECK (isnil (jj));
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888
}

View file

@ -5344,7 +5344,12 @@
</node>
<node CREATED="1511831658137" ID="ID_295934398" MODIFIED="1511831665696" TEXT="Dekorator-Ansatz">
<icon BUILTIN="forward"/>
<node CREATED="1511831681334" ID="ID_1182010965" MODIFIED="1511831699199" TEXT="Unterscheidung nach Parent (per Trait)"/>
<node CREATED="1512262147649" ID="ID_1592901896" MODIFIED="1512262272749" TEXT="Dekorator auf Core">
<icon BUILTIN="button_cancel"/>
<node CREATED="1512262162366" ID="ID_1471773970" MODIFIED="1512262276131" TEXT="kann direkt Core -&gt; Core verarbeiten">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1511831681334" ID="ID_1182010965" MODIFIED="1511831699199" TEXT="Unterscheidung nach Parent (per Trait)">
<node CREATED="1511831718105" ID="ID_758057732" MODIFIED="1511831729507" TEXT="Parent == state-core">
<node CREATED="1511831731159" ID="ID_1581545445" MODIFIED="1511831735258" TEXT="direkt verwenden"/>
<node CREATED="1511831735870" ID="ID_461566244" MODIFIED="1511831743057" TEXT="bietet bereits die Extension points"/>
@ -5366,6 +5371,43 @@
</node>
</node>
</node>
<node CREATED="1512262200009" ID="ID_1921211925" MODIFIED="1512262243802" TEXT="f&#xfc;hrt zu unn&#xf6;tig komplexem Design">
<icon BUILTIN="button_cancel"/>
<node CREATED="1512262213016" ID="ID_1547313420" MODIFIED="1512262221626" TEXT="wir haben jetzt &quot;zwei Schienen&quot;"/>
<node CREATED="1512262222470" ID="ID_589647672" MODIFIED="1512262236880" TEXT="und es ist nicht mehr klar, was die Quelle ist"/>
</node>
</node>
<node CREATED="1512262251706" ID="ID_1480384220" MODIFIED="1512262256926" TEXT="Dekorator auf Iterator">
<node CREATED="1512262291085" ID="ID_1532344112" MODIFIED="1512262295993" TEXT="f&#xfc;r jeden Layer">
<node CREATED="1512262299476" ID="ID_102544445" MODIFIED="1512262325001">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
TreeExplorer per <i>slicing move</i>&#160;entfernen
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1512262331008" ID="ID_287760536" MODIFIED="1512262346625" TEXT="enthaltenen SrcIter dekorieren -&gt; Core"/>
<node CREATED="1512262347637" ID="ID_1683477051" MODIFIED="1512262371854" TEXT="erneut einen TreeExplorer dar&#xfc;ber adaptieren"/>
</node>
<node CREATED="1512262480339" ID="ID_62641165" MODIFIED="1512262489398" TEXT="Problem: Parent-Auswahl">
<node CREATED="1512262491362" ID="ID_1646804403" MODIFIED="1512262505036" TEXT="wir k&#xf6;nnen beliebig verschachteln"/>
<node CREATED="1512262505760" ID="ID_534073442" MODIFIED="1512262514890" TEXT="der Trait k&#xf6;nnte eine tiefere Schicht greifen"/>
<node CREATED="1512262516143" ID="ID_1514197178" MODIFIED="1512262520193" TEXT="L&#xf6;sung">
<node CREATED="1512262521070" ID="ID_1457239407" MODIFIED="1512262528041" TEXT="geht nur in diesem limitierten Kontext"/>
<node CREATED="1512262528836" ID="ID_879672594" MODIFIED="1512262550733" TEXT="Core bekommt Vorfahrt"/>
<node CREATED="1512262584301" ID="ID_387075989" MODIFIED="1512262598534" TEXT="Folge: Alle Layer m&#xfc;ssen neue Core produzieren">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1511918986936" ID="ID_667088953" MODIFIED="1511918989357" TEXT="Konstrukt">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1511919003054" ID="ID_1728459315" MODIFIED="1511919013829" TEXT="Aufsetz-Punkt">
<icon BUILTIN="flag-yellow"/>
@ -5550,7 +5592,8 @@
</html></richcontent>
</node>
</node>
<node CREATED="1512250977247" ID="ID_363861413" MODIFIED="1512251011054" TEXT="letztlich egal, also automatisch Konverter einf&#xfc;gen">
<node CREATED="1512250977247" ID="ID_363861413" MODIFIED="1512262612978" TEXT="letztlich egal, also automatisch Konverter einf&#xfc;gen">
<icon BUILTIN="button_cancel"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1512259544994" ID="ID_702123443" MODIFIED="1512259564650" TEXT="Problem: mu&#xdf; auf Iterator hochkasten">
<icon BUILTIN="clanbomber"/>
</node>
@ -5563,6 +5606,10 @@
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1512262620480" ID="ID_967757075" MODIFIED="1512262626861" TEXT="Design aufgegeben">
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1512183706657" ID="ID_1135345978" MODIFIED="1512183725664" TEXT="oder: dritter Zweig in ArgAcessor?">