Skip to content

Commit

Permalink
Seek interface now scans only descriptor
Browse files Browse the repository at this point in the history
  • Loading branch information
Epixu committed Mar 9, 2024
1 parent 426e88d commit 70b9ae1
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 79 deletions.
176 changes: 119 additions & 57 deletions source/Hierarchy-Seek.inl
Original file line number Diff line number Diff line change
Expand Up @@ -287,28 +287,57 @@ namespace Langulus::Entity
/// @return the unit if found, or nullptr otherwise
template<Seek SEEK> LANGULUS(INLINED)
Unit* Hierarchy::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) {
const Unit* result {};

// Scan descriptor even if hierarchy is empty
Unit* result {};
aux.ForEachDeep([&](const Unit* unit) {
if (unit->CastsTo(meta)) {
// Found match
if (offset == 0) {
// We're done
result = const_cast<Unit*>(unit);
return Loop::Break;
if constexpr (SEEK & Seek::Here) {
aux.ForEachDeep([&](const Unit* unit) {
if (unit->CastsTo(meta)) {
// Found match
if (offset == 0) {
// We're done
result = unit;
return Loop::Break;
}
else --offset;
}
else --offset;
}

return Loop::Continue;
});

if (result)
return result;
return Loop::Continue;
});

if (result)
return const_cast<Unit*>(result);
}

// If reached, then no unit was found in the descriptor
// Let's delve into the hierarchy
return SeekUnit<SEEK>(meta, offset);
// Let's delve into the hierarchy, by scanning for Traits::Parent
// and Traits::Child inside the 'aux'
//return SeekValue<SEEK>(meta, output, offset);
if constexpr (SEEK & Seek::Above) {
aux.ForEachTrait([&](const Traits::Parent& trait) -> LoopControl {
trait.ForEach([&](const Thing& parent) {
if (nullptr != (result = parent.SeekUnit<Seek::HereAndAbove>(meta, offset)))
// Value was found
return Loop::Break;
return Loop::Continue;
});
return result == nullptr;
});
}

if constexpr (SEEK & Seek::Below) {
aux.ForEachTrait([&](const Traits::Child& trait) -> LoopControl {
trait.ForEach([&](const Thing& child) {
if (nullptr != (result = child.SeekUnit<Seek::HereAndBelow>(meta, offset)))
// Value was found
return Loop::Break;
return Loop::Continue;
});
return result == nullptr;
});
}

return const_cast<Unit*>(result);
}

/// Seek a unit with specific properties
Expand Down Expand Up @@ -462,65 +491,98 @@ namespace Langulus::Entity
}

// Scan descriptor
bool done = false;
if (meta) {
aux.ForEachDeep([&](const Trait& trait) -> LoopControl {
if (trait.IsTrait(meta)) {
// Found match
if constexpr (SEEK & Seek::Here) {
bool done = false;
if (meta) {
aux.ForEachTrait([&](const Trait& trait) -> LoopControl {
if (trait.IsTrait(meta)) {
// Found match
try {
if constexpr (CT::DescriptorMakable<D>)
output = D {Describe(static_cast<const Any&>(trait))};
else if constexpr (CT::Pinnable<D>)
output = trait.template AsCast<TypeOf<D>>();
else
output = trait.template AsCast<D>();

// Didn't throw, but we're done only if offset
// matches
done = offset == 0;
--offset;
return not done;
}
catch (...) {}
}

return Loop::Continue;
});
}
else {
aux.ForEachDeep([&](const Block& group) -> LoopControl {
try {
// Found match if these don't throw
if constexpr (CT::DescriptorMakable<D>)
output = D {Describe(static_cast<const Any&>(trait))};
output = D {Describe(group)};
else if constexpr (CT::Pinnable<D>)
output = trait.template AsCast<TypeOf<D>>();
output = group.template AsCast<TypeOf<D>>();
else
output = trait.template AsCast<D>();
output = group.template AsCast<D>();

// Didn't throw, but we're done only if offset matches
done = offset == 0;
--offset;
return not done;
}
catch (...) {}
}

return Loop::Continue;
});
return Loop::Continue;
});
}

if (done) {
// Trait was found in the descriptor, which means our intent
// is to set it to a custom value - pin it, so it doesn't
// get overwritten on update/refresh
if constexpr (CT::Pinnable<D>)
output.mLocked = true;
return true;
}
}
else {
aux.ForEachDeep([&](const Block& group) -> LoopControl {
try {
// Found match if these don't throw
if constexpr (CT::DescriptorMakable<D>)
output = D {Describe(group)};
else if constexpr (CT::Pinnable<D>)
output = group.template AsCast<TypeOf<D>>();
else
output = group.template AsCast<D>();

// Didn't throw, but we're done only if offset matches
done = offset == 0;
--offset;
return not done;
}
catch (...) { }

return Loop::Continue;
// If reached, then no trait was found in the descriptor
// Let's delve into the hierarchy, by scanning for Traits::Parent
// and Traits::Child inside the 'aux'
//return SeekValue<SEEK>(meta, output, offset);
bool done = false;
if constexpr (SEEK & Seek::Above) {
aux.ForEachTrait([&](const Traits::Parent& trait) -> LoopControl {
trait.ForEach([&](const Thing& parent) {
if (parent.SeekValue<Seek::HereAndAbove>(meta, output, offset)) {
// Value was found
done = true;
return Loop::Break;
}
return Loop::Continue;
});
return not done;
});
}

if (done) {
// Trait was found in the descriptor
if constexpr (CT::Pinnable<D>) {
// Make sure to pin the pinnable value
output.mLocked = true;
}

return true;
if constexpr (SEEK & Seek::Below) {
aux.ForEachTrait([&](const Traits::Child& trait) -> LoopControl {
trait.ForEach([&](const Thing& child) {
if (child.SeekValue<Seek::HereAndBelow>(meta, output, offset)) {
// Value was found
done = true;
return Loop::Break;
}
return Loop::Continue;
});
return not done;
});
}

// If reached, then no trait was found in the descriptor
// Let's delve into the hierarchy
return SeekValue<SEEK>(meta, output, offset);
return done;
}

} // namespace Langulus::Entity
4 changes: 2 additions & 2 deletions source/Hierarchy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Langulus::Anyness

/// Execute a verb for all elements inside a type-erased constant block
/// @param verb - the verb to execute
template<CT::Data T>
/*template<CT::Data T>
Flow::Verb& TAny<T>::Run(Flow::Verb& verb) const {
Flow::DispatchDeep(*this, verb);
return verb;
Expand All @@ -29,7 +29,7 @@ namespace Langulus::Anyness
Flow::Verb& TAny<T>::Run(Flow::Verb& verb) {
Flow::DispatchDeep(*this, verb);
return verb;
}
}*/

} // namespace Langulus::Anyness

Expand Down
13 changes: 1 addition & 12 deletions source/Thing-Verbs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,7 @@ namespace Langulus::Entity
/// units, so the custom dispatcher forwards verbs to these units
/// @param verb - any verb
void Thing::Do(Verb& verb) {
// Dispatch to entity first, using reflected and default verbs,
// but disallowing custom dispatch, because we're currently in it
// and there's a potential for infinite regress
if (Resolvable::Run<false>(verb).IsDone())
return;

// If verb is still not satisfied, dispatch to ALL units
for (auto& unit : mUnitsList) {
Verb local {verb};
local.ShortCircuit(false);
verb << Abandon(unit->Run(local));
}
Run(verb);
}

/// Create/Destroy stuff inside entity's context
Expand Down
2 changes: 2 additions & 0 deletions source/Thing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ namespace Langulus::Entity

template<Seek = Seek::HereAndAbove, CT::VerbBased V>
V& RunIn(V&);
template<CT::VerbBased V>
V& Run(V&);

LANGULUS_API(ENTITY) Any Run(const Lingua&);

Expand Down
37 changes: 29 additions & 8 deletions source/Thing.inl
Original file line number Diff line number Diff line change
Expand Up @@ -186,31 +186,50 @@ namespace Langulus::Entity
V& Thing::RunIn(V& verb) {
if constexpr (SEEK & Seek::Here) {
// Execute here
Do(verb);
if (verb.IsDone())
if (Run(verb).IsDone())
return verb;
}

if constexpr (SEEK & Seek::Above) {
// Execute in parents up to root, if requested
if (mOwner) {
if (mOwner->template RunIn<Seek::HereAndAbove>(verb).IsDone())
return verb;
}
if (mOwner and mOwner->template
RunIn<Seek::HereAndAbove>(verb).IsDone())
return verb;
}

if constexpr (SEEK & Seek::Below) {
// Execute in children, if requested
for (auto& child : mChildren) {
V local = verb;
local.ShortCircuit(false);
verb << Abandon(
child->template RunIn<Seek::HereAndBelow>(local).GetOutput());
verb << Abandon(child->template
RunIn<Seek::HereAndBelow>(local).GetOutput());
}
}

return verb;
}

/// Execute verb in this thing only, scanning units for required verbs
/// @param verb - the verb to execute
/// @return verb output
template<CT::VerbBased V>
V& Thing::Run(V& verb) {
// Dispatch to entity first, using reflected and default verbs,
// but disallowing custom dispatch, because we're currently in it
// and there's a potential for infinite regress
if (Resolvable::Run<false>(verb).IsDone())
return verb;

// If verb is still not satisfied, dispatch to ALL units
for (auto& unit : mUnitsList) {
V local = verb;
local.ShortCircuit(false);
verb << Abandon(unit->Run(local).GetOutput());
}

return verb;
}

/// Register unit by all its bases in mUnitsAmbiguous
/// @param unit - the unit instance to register
Expand All @@ -225,6 +244,7 @@ namespace Langulus::Entity
for (auto& base : type->mBases) {
if (base.mType->IsExact<Unit>())
break;

AddUnitBases(unit, base.mType);
}
}
Expand All @@ -243,6 +263,7 @@ namespace Langulus::Entity
for (auto& base : type->mBases) {
if (base.mType->IsExact<Unit>())
break;

RemoveUnitBases(unit, base.mType);
}
}
Expand Down

0 comments on commit 70b9ae1

Please sign in to comment.