diff --git a/mps/code/cbs.c b/mps/code/cbs.c index d4363f44475..45fd4aaa665 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -667,8 +667,8 @@ void CBSIterate(CBS cbs, CBSIterateMethod iterate, closure.iterate = iterate; closure.closureP = closureP; closure.closureS = closureS; - TreeTraverse(SplayTreeRoot(tree), tree->compare, tree->nodeKey, - CBSIterateVisit, &closure, 0); + (void)TreeTraverse(SplayTreeRoot(tree), tree->compare, tree->nodeKey, + CBSIterateVisit, &closure, 0); cbsLeave(cbs); return; diff --git a/mps/code/tree.c b/mps/code/tree.c index 277dbaf3772..59d492987ac 100644 --- a/mps/code/tree.c +++ b/mps/code/tree.c @@ -155,13 +155,16 @@ Bool TreeInsert(Tree *treeReturn, Tree root, Tree node, * * * The tree may not be modified during the traversal, and the traversal - * must complete. TODO: Is there a way to abort early? + * must complete. + * + * TreeTraverse is generally superior if comparisons are cheap. */ -void TreeTraverseMorris(Tree tree, TreeVisitor visit, +Bool TreeTraverseMorris(Tree tree, TreeVisitor visit, void *closureP, Size closureS) { Tree node; + Bool visiting = TRUE; AVER(TreeCheck(tree)); AVER(FUNCHECK(visit)); @@ -170,7 +173,8 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit, node = tree; while (node != TreeEMPTY) { if (node->left == TreeEMPTY) { - (void)visit(node, closureP, closureS); + if (visiting) + visiting = visit(node, closureP, closureS); node = node->right; } else { Tree pre = node->left; @@ -182,7 +186,10 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit, } if (pre->right == node) { pre->right = TreeEMPTY; - (void)visit(node, closureP, closureS); + if (visiting) + visiting = visit(node, closureP, closureS); + else if (node == tree) + return FALSE; node = node->right; break; } @@ -190,6 +197,8 @@ void TreeTraverseMorris(Tree tree, TreeVisitor visit, } } } + + return visiting; } @@ -231,7 +240,7 @@ static Tree stepUpLeft(Tree node, Tree *parentIO) return parent; } -void TreeTraverse(Tree tree, +Bool TreeTraverse(Tree tree, TreeCompare compare, TreeKeyMethod key, TreeVisitor visit, void *closureP, Size closureS) @@ -246,7 +255,7 @@ void TreeTraverse(Tree tree, node = tree; if (node == TreeEMPTY) - return; + return TRUE; down: if (TreeHasLeft(node)) { @@ -264,7 +273,7 @@ down: up: if (parent == TreeEMPTY) - return; + return TRUE; if (compare(parent, key(node)) != CompareLESS) { node = stepUpLeft(node, &parent); goto up; @@ -279,7 +288,7 @@ up: abort: if (parent == TreeEMPTY) - return; + return FALSE; if (compare(parent, key(node)) != CompareLESS) node = stepUpLeft(node, &parent); else diff --git a/mps/code/tree.h b/mps/code/tree.h index eaa917dca67..42aa135054c 100644 --- a/mps/code/tree.h +++ b/mps/code/tree.h @@ -2,6 +2,8 @@ * * $Id$ * Copyright (C) 2014 Ravenbrook Limited. See end of file for license. + * + * Simple binary trees, for use as building blocks. */ #ifndef tree_h @@ -77,11 +79,11 @@ extern Bool TreeInsert(Tree *treeReturn, Tree root, Tree node, TreeKey key, TreeCompare compare); typedef Bool TreeVisitor(Tree tree, void *closureP, Size closureS); -extern void TreeTraverse(Tree tree, +extern Bool TreeTraverse(Tree tree, TreeCompare compare, TreeKeyMethod key, TreeVisitor visit, void *closureP, Size closureS); -extern void TreeTraverseMorris(Tree tree, TreeVisitor visit, +extern Bool TreeTraverseMorris(Tree tree, TreeVisitor visit, void *closureP, Size closureS); extern void TreeRotateLeft(Tree *nodeIO);