Skip to content

Commit

Permalink
(Support) Upgrade to latest Sawyer; more tree unit tests
Browse files Browse the repository at this point in the history
Adds Sawyer::Yaml::exists(std::string const&)

since this can modify the node if the node is not const.

  if (node["key"]) ...

RPM-212
  • Loading branch information
matzke1 committed Apr 21, 2023
1 parent 64d63d7 commit 14a69df
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
13 changes: 13 additions & 0 deletions src/util/Sawyer/Tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,12 @@ class Vertex: public std::enable_shared_from_this<Vertex<B>> {
/** Returns a shared pointer to this vertex. */
UserBasePtr pointer();

/** Tests whether this object is a certain type.
*
* Returns a shared pointer to the object if the object is of dynamic type T, otherwise returns a null pointer. */
template<class T>
std::shared_ptr<T> isa();

/** Traverse in reverse direction from children to parents.
*
* The visitor is called for each vertex from the current vertex whose type is @p T until the root of the tree is reached
Expand Down Expand Up @@ -1036,6 +1042,13 @@ Vertex<B>::pointer() {
return retval;
}

template<class B>
template<class T>
std::shared_ptr<T>
Vertex<B>::isa() {
return std::dynamic_pointer_cast<T>(this->shared_from_this());
}

template<class B>
typename Vertex<B>::UserBasePtr
Vertex<B>::child(size_t i) const {
Expand Down
6 changes: 6 additions & 0 deletions src/util/Sawyer/Yaml.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,12 @@ class Node {
Node& operator[](const std::string& key) const;
/** @} */

/** Test whether a map item exists without inserting it. */
bool exists(const std::string &key) const {
// Because of const this, the operator[] does not add the node, it only returns an empty node
return (*this)[key] ? true : false;
}

/** Erase item.
*
* No action if node is not a sequence or map.
Expand Down
43 changes: 37 additions & 6 deletions tests/smoke/unit/Sawyer/treeUnitTests.C
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static void test01() {
ASSERT_always_require(e == nullptr);
}

// instantion can use `auto` and the type is mentioned on the rhs
// instantiation can use `auto` since the type is documented on the rhs
static void test02() {
auto e = BinaryExpression::instance();
ASSERT_always_require(e != nullptr);
Expand Down Expand Up @@ -305,6 +305,7 @@ static void test14() {
#endif
}

// These tests were for features that have since been removed
static void test15() {
}

Expand Down Expand Up @@ -724,7 +725,7 @@ static void test45() {
ASSERT_always_require2(result.x == 911, result.x);
}

// Sawyer::Optional can be used to easily return a value to short circuit.
// Sawyer::Optional can be used to easily return a value and to short circuit.
static void test46() {
auto parent = Multi::instance();
auto a = Multi::instance();
Expand All @@ -738,16 +739,18 @@ static void test46() {

const int x = parent->traverse<Multi>([&b2](const MultiPtr &vertex, Expression::TraversalEvent) {
if (vertex == b2) {
return Sawyer::Optional<int>(911);
return Sawyer::Optional<int>(911); // immediately return this from the traversal
} else {
return Sawyer::Optional<int>();
return Sawyer::Optional<int>(); // continue traversing
}
}).orElse(42);

ASSERT_always_require2(x == 911, x);
}

// A return value can be thrown, although this is not as clean and can be slower, especially if you want the result to be const
// A return value can be thrown, although this is not as clean and can be slower, especially if you want the result to be const.
// The slowness is because C++ `throw` is intended for exceptional situations and the non-throw flow is what is optimized for speed.
// The outer lambda is a C++ idiom for computing a const result, namely `const auto x = [&vars...](){ calculation; }();`.
static void test47() {
auto parent = Multi::instance();
auto a = Multi::instance();
Expand Down Expand Up @@ -789,6 +792,7 @@ static void test48() {
parent->b.push_back(b2);
parent->c = c;

//----------------------------------------------------------------------------------------------------------------------------
// Partial implementation of ROSE's ::AstSimpleTraversal class. Think "SgNode" when you see "Expression" since the root of
// our class hierarchy in this unit test file is "Expression" instead of "SgNode". Also, we're using reference counting pointers
// instead of raw pointers, so you'll see "Ptr" (aliases for std::shared_ptr<T>) instead of "*".
Expand Down Expand Up @@ -826,6 +830,17 @@ static void test48() {
nodeCounter.traverse(parent, preorder);
ASSERT_always_require(nodeCounter.n == 5);

//----------------------------------------------------------------------------------------------------------------------------
// Equivalent more modern code
size_t n = 0;
parent->traverse<Expression>([&n](const ExpressionPtr&, Expression::TraversalEvent event) {
if (Expression::TraversalEvent::ENTER == event)
++n;
return false;
});
ASSERT_always_require(n == 5);

//----------------------------------------------------------------------------------------------------------------------------
// Here's a partial implementation of AstPrePostProcessing.
class AstPrePostProcessing {
public:
Expand Down Expand Up @@ -860,11 +875,27 @@ static void test48() {
}

void postOrderVisit(const ExpressionPtr&) {
ASSERT_forbid(stack.empty());
ASSERT_always_forbid(stack.empty());
stack.pop_back();
}
} check;
check.traverse(parent);
ASSERT_always_require(check.stack.empty());

//----------------------------------------------------------------------------------------------------------------------------
// Same thing without using AstPrePostProcessing
std::vector<ExpressionPtr> stack;
parent->traverse<Expression>([&stack](const ExpressionPtr &node, Expression::TraversalEvent event) {
if (Expression::TraversalEvent::ENTER == event) {
ASSERT_always_require(stack.empty() || node->parent == stack.back());
stack.push_back(node);
} else {
ASSERT_always_forbid(stack.empty());
stack.pop_back();
}
return false;
});
ASSERT_always_require(stack.empty());
}

int main() {
Expand Down

0 comments on commit 14a69df

Please sign in to comment.