Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree,
                   SplayTestNodeMethod testNode,
                   SplayTestTreeMethod testTree,
                   void *closureP, unsigned long closureS)
{
    SplayNode node;
    SplayFindClosureStruct closureStruct;

    AVER(nodeReturn != NULL);
    AVERT(SplayTree, tree);
    AVER(FUNCHECK(testNode));
    AVER(FUNCHECK(testTree));

    node = SplayTreeRoot(tree);

    if (node == NULL || !(*testTree)(tree, node, closureP, closureS))
        return FALSE; /* no suitable nodes in tree */

    closureStruct.p = closureP;
    closureStruct.s = closureS;
    closureStruct.testNode = testNode;
    closureStruct.testTree = testTree;
    closureStruct.tree = tree;

    if (SplaySplay(&node, tree, (void *)&closureStruct,
                   &SplayFindLastCompare)) {
        *nodeReturn = node;
        return TRUE;
    } else {
        return FALSE;
    }
}
示例#2
0
Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay,
                    SplayTestNodeFunction testNode,
                    SplayTestTreeFunction testTree,
                    void *closureP, Size closureS)
{
  SplayFindClosureStruct closureStruct;
  Bool found;

  AVER(nodeReturn != NULL);
  AVERT(SplayTree, splay);
  AVER(FUNCHECK(testNode));
  AVER(FUNCHECK(testTree));

  if (SplayTreeIsEmpty(splay) ||
      !testTree(splay, SplayTreeRoot(splay), closureP, closureS))
    return FALSE; /* no suitable nodes in tree */

  closureStruct.p = closureP;
  closureStruct.s = closureS;
  closureStruct.testNode = testNode;
  closureStruct.testTree = testTree;
  closureStruct.splay = splay;
  closureStruct.found = FALSE;

  found = SplaySplay(splay, &closureStruct,
                     SplayFindFirstCompare) == CompareEQUAL &&
          closureStruct.found;

  while (!found) {
    Tree oldRoot, newRoot;
    
    /* FIXME: Rename to "seen" and "not yet seen" or something. */
    oldRoot = SplayTreeRoot(splay);
    newRoot = TreeRight(oldRoot);

    if (newRoot == TreeEMPTY || !(*testTree)(splay, newRoot, closureP, closureS))
      return FALSE; /* no suitable nodes in the rest of the tree */
  
    /* Temporarily chop off the left half-tree, inclusive of root,
       so that the search excludes any nodes we've seen already. */
    SplayTreeSetRoot(splay, newRoot);
    TreeSetRight(oldRoot, TreeEMPTY);

    found = SplaySplay(splay, &closureStruct,
                       SplayFindFirstCompare) == CompareEQUAL &&
            closureStruct.found;

    /* Restore the left tree, then rotate left so that the node we
       just splayed is at the root.  Update both. */
    newRoot = SplayTreeRoot(splay);
    TreeSetRight(oldRoot, newRoot);
    SplayTreeSetRoot(splay, oldRoot);
    TreeRotateLeft(&splay->root);
    splay->updateNode(splay, oldRoot);
    splay->updateNode(splay, newRoot);
  }

  *nodeReturn = SplayTreeRoot(splay);
  return TRUE;
}
Bool SplayTreeCheck(SplayTree tree)
{
    UNUSED(tree);
    CHECKL(tree != NULL);
    CHECKL(FUNCHECK(tree->compare));
    CHECKL(tree->updateNode == NULL || FUNCHECK(tree->updateNode));
    return TRUE;
}
示例#4
0
文件: splay.c 项目: Ravenbrook/mps
Bool SplayFindLast(Tree *nodeReturn, SplayTree splay,
                   SplayTestNodeFunction testNode,
                   SplayTestTreeFunction testTree,
                   void *testClosure)
{
  SplayFindClosureStruct closureStruct;
  Bool found;

  AVER_CRITICAL(nodeReturn != NULL);
  AVERT_CRITICAL(SplayTree, splay);
  AVER_CRITICAL(FUNCHECK(testNode));
  AVER_CRITICAL(FUNCHECK(testTree));

  if (SplayTreeIsEmpty(splay) ||
      !testTree(splay, SplayTreeRoot(splay), testClosure))
    return FALSE; /* no suitable nodes in tree */

  closureStruct.testClosure = testClosure;
  closureStruct.testNode = testNode;
  closureStruct.testTree = testTree;
  closureStruct.splay = splay;

  found = SplaySplay(splay, &closureStruct,
                     SplayFindLastCompare) == CompareEQUAL &&
          closureStruct.found;

  while (!found) {
    Tree oldRoot, newRoot;
    
    oldRoot = SplayTreeRoot(splay);
    newRoot = TreeLeft(oldRoot);

    if (newRoot == TreeEMPTY || !(*testTree)(splay, newRoot, testClosure))
      return FALSE; /* no suitable nodes in the rest of the tree */
  
    /* Temporarily chop off the right half-tree, inclusive of root,
       so that the search excludes any nodes we've seen already. */
    SplayTreeSetRoot(splay, newRoot);
    TreeSetLeft(oldRoot, TreeEMPTY);

    found = SplaySplay(splay, &closureStruct,
                       SplayFindLastCompare) == CompareEQUAL &&
            closureStruct.found;

    /* Restore the right tree, then rotate right so that the node we
       just splayed is at the root.  Update both. */
    newRoot = SplayTreeRoot(splay);
    TreeSetLeft(oldRoot, newRoot);
    SplayTreeSetRoot(splay, oldRoot);
    TreeRotateRight(&splay->root);
    splay->updateNode(splay, oldRoot);
    splay->updateNode(splay, newRoot);
  }

  *nodeReturn = SplayTreeRoot(splay);
  return TRUE;
}
示例#5
0
Bool SplayTreeCheck(SplayTree splay)
{
  UNUSED(splay);
  CHECKS(SplayTree, splay);
  CHECKL(FUNCHECK(splay->compare));
  CHECKL(FUNCHECK(splay->nodeKey));
  CHECKL(FUNCHECK(splay->updateNode));
  /* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */
  CHECKL(TreeCheck(splay->root));
  return TRUE;
}
void SplayTreeInit(SplayTree tree, SplayCompareMethod compare,
                   SplayUpdateNodeMethod updateNode)
{
    AVER(tree != NULL);
    AVER(FUNCHECK(compare));
    AVER(updateNode == NULL || FUNCHECK(updateNode));

    tree->compare = compare;
    tree->updateNode = updateNode;
    SplayTreeSetRoot(tree, NULL);

    AVERT(SplayTree, tree);
}
示例#7
0
static Bool FormattedObjectsStepClosureCheck(FormattedObjectsStepClosure c)
{
  CHECKS(FormattedObjectsStepClosure, c);
  CHECKL(FUNCHECK(c->f));
  /* p and s fields are arbitrary closures which cannot be checked */
  return TRUE;
}
示例#8
0
Compare TreeFind(Tree *treeReturn, Tree root, TreeKey key, TreeCompare compare)
{
  Tree node, parent;
  Compare cmp = CompareEQUAL;
  
  AVERT(Tree, root);
  AVER(treeReturn != NULL);
  AVER(FUNCHECK(compare));
  /* key is arbitrary */

  parent = NULL;
  node = root;
  while (node != TreeEMPTY) {
    parent = node;
    cmp = compare(node, key);
    switch (cmp) {
    case CompareLESS:
      node = node->left;
      break;
    case CompareEQUAL:
      *treeReturn = node;
      return cmp;
    case CompareGREATER:
      node = node->right;
      break;
    default:
      NOTREACHED;
      *treeReturn = NULL;
      return cmp;
    }
  }
  
  *treeReturn = parent;
  return cmp;
}
示例#9
0
Bool KeyCheck(Key key)
{
  CHECKS(Key, key);
  CHECKL(key->name != NULL);
  CHECKL(FUNCHECK(key->check));
  return TRUE;
}
示例#10
0
文件: tree.c 项目: CarterTsai/clasp
/* TreeTraverseAndDelete -- traverse a tree while deleting nodes 
 *
 * The visitor function must return TRUE to delete the current node,
 * or FALSE to keep it.
 *
 * See <design/arena/#chunk.delete.tricky>.
 */
void TreeTraverseAndDelete(Tree *treeIO, TreeVisitor visitor,
                           void *closureP, Size closureS)
{
  Tree *treeref = treeIO;

  AVER(treeIO != NULL);
  AVERT(Tree, *treeIO);
  AVER(FUNCHECK(visitor));
  /* closureP and closureS are arbitrary */

  TreeToVine(treeIO);

  while (*treeref != TreeEMPTY) {
    Tree tree = *treeref;         /* Current node. */
    Tree *nextref = &tree->right; /* Location of pointer to next node. */
    Tree next = *nextref;         /* Next node. */
    if ((*visitor)(tree, closureP, closureS)) {
      /* Delete current node. */
      *treeref = next;
    } else {
      /* Keep current node. */
      treeref = nextref;
    }
  }
  TreeBalance(treeIO);
}
示例#11
0
文件: tree.c 项目: CarterTsai/clasp
Bool TreeFindNext(Tree *treeReturn, Tree root, TreeKey key, TreeCompare compare)
{
  Tree node, best = NULL;
  Bool result = FALSE;

  AVERT(Tree, root);
  AVER(treeReturn != NULL);
  AVER(FUNCHECK(compare));
  /* key is arbitrary */

  node = root;
  while (node != TreeEMPTY) {
    Compare cmp = compare(node, key);
    switch (cmp) {
    case CompareLESS:
      best = node;
      result = TRUE;
      node = node->left;
      break;
    case CompareEQUAL:
    case CompareGREATER:
      node = node->right;
      break;
    default:
      NOTREACHED;
      return FALSE;
    }
  }
  
  *treeReturn = best;
  return result;
}
示例#12
0
static void ArenaFormattedObjectsWalk(Arena arena, FormattedObjectsStepMethod f,
                                      void *p, size_t s)
{
  Seg seg;
  FormattedObjectsStepClosure c;

  AVERT(Arena, arena);
  AVER(FUNCHECK(f));
  AVER(f == ArenaFormattedObjectsStep);
  /* p and s are arbitrary closures. */
  /* Know that p is a FormattedObjectsStepClosure  */
  /* Know that s is 0 */
  AVER(p != NULL);
  AVER(s == 0);

  c = p;
  AVERT(FormattedObjectsStepClosure, c);

  if (SegFirst(&seg, arena)) {
    do {
      Pool pool;
      pool = SegPool(seg);
      if (PoolHasAttr(pool, AttrFMT)) {
        ShieldExpose(arena, seg);
        PoolWalk(pool, seg, f, p, s);
        ShieldCover(arena, seg);
      }
    } while(SegNext(&seg, arena, seg));
  }
}
示例#13
0
文件: pool.c 项目: bhanug/mps
void PoolFreeWalk(Pool pool, FreeBlockVisitor f, void *p)
{
  AVERT(Pool, pool);
  AVER(FUNCHECK(f));
  /* p is arbitrary, hence can't be checked. */

  Method(Pool, pool, freewalk)(pool, f, p);
}
示例#14
0
文件: protocol.c 项目: Ravenbrook/mps
Bool InstClassCheck(InstClass klass)
{
  ClassLevel i;
  CHECKS(InstClass, klass);
  CHECKL(klass->name != NULL);
  CHECKL(klass->level < ClassDEPTH);
  for (i = 0; i <= klass->level; ++i) {
    CHECKL(klass->display[i] != NULL);
  }
  for (i = klass->level + 1; i < ClassDEPTH; ++i) {
    CHECKL(klass->display[i] == NULL);
  }
  CHECKL(FUNCHECK(klass->describe));
  CHECKL(FUNCHECK(klass->finish));
  CHECKL(FUNCHECK(klass->init));
  return TRUE;
}
示例#15
0
文件: pool.c 项目: bhanug/mps
void PoolWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, void *p, size_t s)
{
  AVERT(Pool, pool);
  AVERT(Seg, seg);
  AVER(FUNCHECK(f));
  /* p and s are arbitrary values, hence can't be checked. */

  Method(Pool, pool, walk)(pool, seg, f, p, s);
}
示例#16
0
void ProtTramp(void **rReturn, void *(*f)(void *p, size_t s),
               void *p, size_t s)
{
  AVER(rReturn != NULL);
  AVER(FUNCHECK(f));
  /* Can't check p and s as they are interpreted by the client */

  *(rReturn) = (*(f))(p, s);
}
示例#17
0
void SplayTreeInit(SplayTree splay,
                   TreeCompareFunction compare,
                   TreeKeyFunction nodeKey,
                   SplayUpdateNodeFunction updateNode)
{
  AVER(splay != NULL);
  AVER(FUNCHECK(compare));
  AVER(FUNCHECK(nodeKey));
  AVER(FUNCHECK(updateNode));

  splay->compare = compare;
  splay->nodeKey = nodeKey;
  splay->updateNode = updateNode;
  SplayTreeSetRoot(splay, TreeEMPTY);
  splay->sig = SplayTreeSig;

  AVERT(SplayTree, splay);
}
示例#18
0
Bool TreeTraverse(Tree tree,
                  TreeCompare compare,
                  TreeKeyMethod key,
                  TreeVisitor visit, void *closureP, Size closureS)
{
  Tree parent, node;
  
  AVERT(Tree, tree);
  AVER(FUNCHECK(visit));
  /* closureP, closureS arbitrary */

  parent = TreeEMPTY;
  node = tree;
  
  if (node == TreeEMPTY)
    return TRUE;

down:
  if (TreeHasLeft(node)) {
    node = stepDownLeft(node, &parent);
    AVER(compare(parent, key(node)) == CompareLESS);
    goto down;
  }
  if (!visit(node, closureP, closureS))
    goto abort;
  if (TreeHasRight(node)) {
    node = stepDownRight(node, &parent);
    AVER(compare(parent, key(node)) != CompareLESS);
    goto down;
  }

up:
  if (parent == TreeEMPTY)
    return TRUE;
  if (compare(parent, key(node)) != CompareLESS) {
    node = stepUpLeft(node, &parent);
    goto up;
  }
  node = stepUpRight(node, &parent);
  if (!visit(node, closureP, closureS))
    goto abort;
  if (!TreeHasRight(node))
    goto up;
  node = stepDownRight(node, &parent);
  goto down;

abort:
  if (parent == TreeEMPTY)
    return FALSE;
  if (compare(parent, key(node)) != CompareLESS)
    node = stepUpLeft(node, &parent);
  else
    node = stepUpRight(node, &parent);
  goto abort;
}
示例#19
0
Bool FormatCheck(Format format)
{
  CHECKS(Format, format);
  CHECKU(Arena, format->arena);
  CHECKL(format->serial < format->arena->formatSerial);
  CHECKD_NOSIG(Ring, &format->arenaRing);
  CHECKL(AlignCheck(format->alignment));
  /* TODO: Define the concept of the maximum alignment it is possible to
     request from the MPS, document and provide an interface to it, and then
     check that this alignment is not greater than that, as well as all other
     alignments. */
  CHECKL(FUNCHECK(format->scan));
  CHECKL(FUNCHECK(format->skip));
  CHECKL(FUNCHECK(format->move));
  CHECKL(FUNCHECK(format->isMoved));
  CHECKL(FUNCHECK(format->pad));
  CHECKL(FUNCHECK(format->class));

  return TRUE;
}
示例#20
0
static Bool rootsStepClosureCheck(rootsStepClosure rsc)
{
  CHECKS(rootsStepClosure, rsc);
  CHECKD(ScanState, &rsc->ssStruct);
  CHECKL(FUNCHECK(rsc->f));
  /* p and s fields are arbitrary closures which cannot be checked */
  if (rsc->root != NULL) {
    CHECKD_NOSIG(Root, rsc->root); /* <design/check/#.hidden-type> */
  }
  return TRUE;
}
示例#21
0
文件: dbgpool.c 项目: Ravenbrook/mps
Bool PoolDebugMixinCheck(PoolDebugMixin debug)
{
  /* Nothing to check about fenceTemplate */
  /* Nothing to check about fenceSize */
  /* Nothing to check about freeTemplate */
  /* Nothing to check about freeSize */
  if (debug->tagInit != NULL) {
    CHECKL(FUNCHECK(debug->tagInit));
    /* Nothing to check about tagSize */
    CHECKD(Pool, debug->tagPool);
    CHECKL(COMPATTYPE(Addr, void*)); /* tagPool relies on this */
    /* Nothing to check about missingTags */
    CHECKD(SplayTree, &debug->index);
  }
  UNUSED(debug); /* see <code/mpm.c#check.unused> */
  return TRUE;
}
示例#22
0
void mps_arena_roots_walk(mps_arena_t mps_arena, mps_roots_stepper_t f,
                          void *p, size_t s)
{
  Arena arena = (Arena)mps_arena;
  Res res;

  ArenaEnter(arena);
  AVER(FUNCHECK(f));
  /* p and s are arbitrary closures, hence can't be checked */

  AVER(ArenaGlobals(arena)->clamped);          /* .assume.parked */
  AVER(arena->busyTraces == TraceSetEMPTY);    /* .assume.parked */

  res = ArenaRootsWalk(ArenaGlobals(arena), f, p, s);
  AVER(res == ResOK);
  ArenaLeave(arena);
}
示例#23
0
文件: thxc.c 项目: Ravenbrook/mps
static void mapThreadRing(Ring threadRing, Ring deadRing, Bool (*func)(Thread))
{
  Ring node, next;

  AVERT(Ring, threadRing);
  AVERT(Ring, deadRing);
  AVER(FUNCHECK(func));

  RING_FOR(node, threadRing, next) {
    Thread thread = RING_ELT(Thread, arenaRing, node);
    AVERT(Thread, thread);
    AVER(thread->alive);
    if (!(*func)(thread)) {
      thread->alive = FALSE;
      RingRemove(&thread->arenaRing);
      RingAppend(deadRing, &thread->arenaRing);
    }
  }
示例#24
0
void mps_arena_formatted_objects_walk(mps_arena_t mps_arena,
                                      mps_formatted_objects_stepper_t f,
                                      void *p, size_t s)
{
  Arena arena = (Arena)mps_arena;
  FormattedObjectsStepClosureStruct c;

  ArenaEnter(arena);
  AVERT(Arena, arena);
  AVER(FUNCHECK(f));
  /* p and s are arbitrary closures, hence can't be checked */
  c.sig = FormattedObjectsStepClosureSig;
  c.f = f;
  c.p = p;
  c.s = s;
  ArenaFormattedObjectsWalk(arena, ArenaFormattedObjectsStep, &c, 0);
  ArenaLeave(arena);
}
示例#25
0
文件: buffer.c 项目: Ravenbrook/mps
Bool BufferClassCheck(BufferClass klass)
{
  CHECKD(InstClass, &klass->instClassStruct);
  CHECKL(klass->size >= sizeof(BufferStruct));
  CHECKL(FUNCHECK(klass->varargs));
  CHECKL(FUNCHECK(klass->init));
  CHECKL(FUNCHECK(klass->attach));
  CHECKL(FUNCHECK(klass->detach));
  CHECKL(FUNCHECK(klass->seg));
  CHECKL(FUNCHECK(klass->rankSet));
  CHECKL(FUNCHECK(klass->setRankSet));
  CHECKL(FUNCHECK(klass->reassignSeg));

  /* Check that buffer classes override sets of related methods. */
  CHECKL((klass->init == BufferAbsInit)
         == (klass->instClassStruct.finish == BufferAbsFinish));
  CHECKL((klass->attach == bufferTrivAttach)
         == (klass->detach == bufferTrivDetach));

  CHECKS(BufferClass, klass);
  return TRUE;
}
示例#26
0
Bool TreeTraverseMorris(Tree tree, TreeVisitor visit,
                        void *closureP, Size closureS)
{
  Tree node;
  Bool visiting = TRUE;
  
  AVERT(Tree, tree);
  AVER(FUNCHECK(visit));
  /* closureP, closureS arbitrary */
  
  node = tree;
  while (node != TreeEMPTY) {
    if (node->left == TreeEMPTY) {
      if (visiting)
        visiting = visit(node, closureP, closureS);
      node = node->right;
    } else {
      Tree pre = node->left;
      for (;;) {
        if (pre->right == TreeEMPTY) {
          pre->right = node;
          node = node->left;
          break;
        }
        if (pre->right == node) {
          pre->right = TreeEMPTY;
          if (visiting)
            visiting = visit(node, closureP, closureS);
          else if (node == tree)
            return FALSE;
          node = node->right;
          break;
        }
        pre = pre->right;
      }
    }
  }

  return visiting;
}
示例#27
0
文件: thix.c 项目: Ravenbrook/mps
static void mapThreadRing(Ring threadRing, Ring deadRing, Bool (*func)(Thread))
{
    Ring node, next;
    pthread_t self;

    AVERT(Ring, threadRing);
    AVERT(Ring, deadRing);
    AVER(FUNCHECK(func));

    self = pthread_self();
    RING_FOR(node, threadRing, next) {
        Thread thread = RING_ELT(Thread, arenaRing, node);
        AVERT(Thread, thread);
        AVER(thread->alive);
        if (!pthread_equal(self, thread->id) /* .thread.id */
                && !(*func)(thread))
        {
            thread->alive = FALSE;
            RingRemove(&thread->arenaRing);
            RingAppend(deadRing, &thread->arenaRing);
        }
    }
示例#28
0
Bool TreeInsert(Tree *treeReturn, Tree root, Tree node,
                TreeKey key, TreeCompare compare)
{
  Tree parent;
  Compare cmp;
  
  AVER(treeReturn != NULL);
  AVER(Tree, root);
  AVER(TreeCheckLeaf(node));
  AVER(FUNCHECK(compare));
  /* key is arbitrary */

  cmp = TreeFind(&parent, root, key, compare);
  switch (cmp) {
  case CompareLESS:
    parent->left = node;
    break;
  case CompareEQUAL:
    if (parent != NULL) {
      *treeReturn = parent;
      return FALSE;
    }
    AVER(root == TreeEMPTY);
    root = node;
    break;
  case CompareGREATER:
    parent->right = node;
    break;
  default:
    NOTREACHED;
    *treeReturn = NULL;
    return FALSE;
  }
  
  *treeReturn = root;
  return TRUE;
}
Res SplayTreeDescribe(SplayTree tree, mps_lib_FILE *stream,
                      SplayNodeDescribeMethod nodeDescribe) {
    Res res;

#if defined(AVER_AND_CHECK)
    if (!SplayTreeCheck(tree)) return ResFAIL;
    if (stream == NULL) return ResFAIL;
    if (!FUNCHECK(nodeDescribe)) return ResFAIL;
#endif

    res = WriteF(stream,
                 "Splay $P {\n", (WriteFP)tree,
                 "  compare $F\n", (WriteFF)tree->compare,
                 NULL);
    if (res != ResOK) return res;

    if (SplayTreeRoot(tree) != NULL) {
        res = SplayNodeDescribe(SplayTreeRoot(tree), stream, nodeDescribe);
        if (res != ResOK) return res;
    }

    res = WriteF(stream, "\n}\n", NULL);
    return res;
}
示例#30
0
static Compare SplaySplitRev(SplayStateStruct *stateReturn,
                             SplayTree splay, TreeKey key,
                             TreeCompareFunction compare)
{
  Tree middle, leftLast, rightFirst;
  Compare cmp;

  AVERT(SplayTree, splay);
  AVER(FUNCHECK(compare));
  AVER(!SplayTreeIsEmpty(splay));
  
  leftLast = TreeEMPTY;
  rightFirst = TreeEMPTY;
  middle = SplayTreeRoot(splay);
  for (;;) {
    cmp = compare(middle, key);
    switch(cmp) {
    default:
      NOTREACHED;
      /* defensive fall-through */
    case CompareEQUAL:
      goto stop;

    case CompareLESS:
      if (!TreeHasLeft(middle))
        goto stop;
      middle = SplayZigRev(middle, &rightFirst);
      cmp = compare(middle, key);
      switch(cmp) {
      default:
        NOTREACHED;
        /* defensive fall-through */
      case CompareEQUAL:
        goto stop;
      case CompareLESS:
        if (!TreeHasLeft(middle))
          goto stop;
        middle = SplayZigZigRev(middle, &rightFirst);
        splay->updateNode(splay, TreeRight(rightFirst));
        break;
      case CompareGREATER:
        if (!TreeHasRight(middle))
          goto stop;
        middle = SplayZagRev(middle, &leftLast);
        break;
      }
      break;

    case CompareGREATER:
      if (!TreeHasRight(middle))
        goto stop;
      middle = SplayZagRev(middle, &leftLast);
      cmp = compare(middle, key);
      switch(cmp) {
      default:
        NOTREACHED;
        /* defensive fall-through */
      case CompareEQUAL:
        goto stop;
      case CompareGREATER:
        if (!TreeHasRight(middle))
          goto stop;
        middle = SplayZagZagRev(middle, &leftLast);
        splay->updateNode(splay, TreeLeft(leftLast));
        break;
      case CompareLESS:
        if (!TreeHasLeft(middle))
          goto stop;
        middle = SplayZigRev(middle, &rightFirst);
        break;
      }
      break;
    }
  }

stop:
  stateReturn->middle = middle;
  stateReturn->leftLast = leftLast;
  stateReturn->rightFirst = rightFirst;
  return cmp;
}