ANY AVL_DICTIONARY_NODE AVL_HELPER NONE
class interface AVL_DICTIONARY_NODE[V,K->COMPARABLE]
   --
   -- Auxiliary class to implement AVL_DICTIONARY[E].
   --

creation
   make (i: K)
      require
         i /= Void
      ensure
         key = i

feature(s) from COMPARABLE
   is_equal (other: like Current): BOOLEAN
      -- Is other attached to an object considered equal to
      -- current object ?
      require
         other /= Void
      ensure
         generating_type = other.generating_type implies Result = other.is_equal(Current);
         trichotomy: Result = (not (Current < other) and not (other < Current))

   infix "<" (other: like Current): BOOLEAN
      -- Is Current strictly less than other?
      require
         other_exists: other /= Void
      ensure
         asymmetric: Result implies not (other < Current)

   infix "<=" (other: like Current): BOOLEAN
      -- Is Current less than or equal other?
      require
         other_exists: other /= Void
      ensure
         definition: Result = (Current < other or is_equal(other))

   infix ">" (other: like Current): BOOLEAN
      -- Is Current strictly greater than other?
      require
         other_exists: other /= Void
      ensure
         definition: Result = (other < Current)

   infix ">=" (other: like Current): BOOLEAN
      -- Is Current greater than or equal than other?
      require
         other_exists: other /= Void
      ensure
         definition: Result = (other <= Current)

   in_range (lower, upper: like Current): BOOLEAN
      -- Return True if Current is in range [lower..upper]
      ensure
         Result = (Current >= lower and Current <= upper)

   compare (other: like Current): INTEGER
      -- If current object equal to other, 0
      -- if smaller,  -1; if greater, 1.
      require
         other_exists: other /= Void
      ensure
         equal_zero: Result = 0 = is_equal(other);
         smaller_negative: Result = -1 = (Current < other);
         greater_positive: Result = 1 = (Current > other)

   three_way_comparison (other: like Current): INTEGER
      -- If current object equal to other, 0
      -- if smaller,  -1; if greater, 1.
      require
         other_exists: other /= Void
      ensure
         equal_zero: Result = 0 = is_equal(other);
         smaller_negative: Result = -1 = (Current < other);
         greater_positive: Result = 1 = (Current > other)

   min (other: like Current): like Current
      -- Minimum of Current and other.
      require
         other /= Void
      ensure
         Result <= Current and then Result <= other;
         compare(Result) = 0 or else other.compare(Result) = 0

   max (other: like Current): like Current
      -- Maximum of Current and other.
      require
         other /= Void
      ensure
         Result >= Current and then Result >= other;
         compare(Result) = 0 or else other.compare(Result) = 0

feature(s) from AVL_NODE
   out_in_tagged_out_memory
      -- Append terse printable represention of current object
      -- in tagged_out_memory.
      ensure
         not_cleared: tagged_out_memory.count >= old tagged_out_memory.count;
         append_only: (old tagged_out_memory.twin).is_equal(tagged_out_memory.substring(1,old tagged_out_memory.count))

feature(s) from AVL_NODE
   key: K

   left: like Current

   right: like Current

   count: INTEGER

feature(s) from AVL_NODE
   last_inserted: like Current

   add (i: K): like Current
      -- Returns the root node that should replace this one
      ensure
         last_inserted.key = i;
         Result /= Void

   remove (i: K): like Current
      -- Returns the root node that should replace this one
      ensure
         lost_nodes.count = old lost_nodes.count + 1;
         Result /= Void

   clear_nodes

   set_key (i: K)
      require
         i /= Void
      ensure
         key = i

   map_in (map: COLLECTION[like Current])
      require
         map /= Void
      ensure
         map.count = old map.count + count

feature(s) from AVL_NODE
   balanced: INTEGER

   imbalanced_left: INTEGER

   imbalanced_right: INTEGER

   balance: INTEGER
      -- Balance factor; either balanced (the tree is balanced),
      -- imbalanced_left (the left branch is the longer) or
      -- imbalanced_right (the right branch is the longer)

   set_balance (b: INTEGER)
      ensure
         balance = b

   set_left (l: like Current)
      ensure
         left = l

   set_right (r: like Current)
      ensure
         right = r

feature(s) from AVL_NODE
   -- Insertion:

   do_insert: BOOLEAN
      -- True if some reorganisation may be needed above the current node.

   left_grown: BOOLEAN

   right_grown: BOOLEAN

   insert_right: BOOLEAN

   insert_left: BOOLEAN

feature(s) from AVL_NODE
   -- Removal:

   do_remove: BOOLEAN

   left_shrunk: BOOLEAN

   right_shrunk: BOOLEAN

   find_highest (n: like Current; flags: TUPLE[BOOLEAN, BOOLEAN]): like Current
      -- flags.first is True if the tree must be balanced
      -- flags.second is True if a node was found that is higher that Current

   find_lowest (n: like Current; flags: TUPLE[BOOLEAN, BOOLEAN]): like Current
      -- flags.first is True if the tree must be balanced
      -- flags.second is True if a node was found that is higher that Current

feature(s) from AVL_NODE
   -- Rotations:

   rotate_right: like Current
      -- Proceeds to some reorganisation and returns the upper node.

   rotate_left: like Current
      -- Proceeds to some reorganisation and returns the upper node.

feature(s) from AVL_NODE
   -- Creation:

   make (i: K)
      require
         i /= Void
      ensure
         key = i

feature(s) from AVL_NODE
   node_inserted: reference BOOLEAN

   node: like Current
      -- Used when inserting a new node while avoiding memory leaks.

   make_new_node (i: K)
      ensure
         node.key = i

   set_node (n: like Current)
      ensure
         node = n

   clear_node
      -- Used when the node has truly been inserted.
      ensure
         node = Void

   set_node_inserted
      ensure
         node_inserted.item

   clear_node_inserted
      ensure
         not node_inserted.item

feature(s) from AVL_NODE
   node_memo: MEMO[AVL_DICTIONARY_NODE[V, K]]
      -- Holds node. The held node may change during insertion

   inserted_node_memo: MEMO[AVL_DICTIONARY_NODE[V, K]]
      -- A node about to be inserted. If the node, is truly inserted, then
      -- that memory will be cleared; otherwise the node is reused at next
      -- insertion (see make_new_node)

   lost_nodes: COLLECTION[AVL_DICTIONARY_NODE[V, K]]
      -- Keeps discarded nodes to avoid memory leaks. Should be a once function. May return Void if lost
      -- nodes are not kept.

   new_node (e: E): AVL_DICTIONARY_NODE[V, K]
      require
         e /= Void
      ensure
         --old lost_nodes.count > 0 implies
         --   (lost_nodes.count = old lost_nodes.count - 1
         --    and then Result = old lost_nodes.last)

   discard_node (n: AVL_DICTIONARY_NODE[V, K])
      require
         n /= Void
      ensure
         discarded: lost_nodes /= Void implies lost_nodes.count = old lost_nodes.count + 1

feature(s) from AVL_NODE
   inserted (n: like Current)

   last_inserted_memory: MEMO[like Current]

feature(s) from AVL_HELPER
   -- Internals:

   a_new_node (k: K): AVL_DICTIONARY_NODE[V, K]
      require
         k /= Void
      ensure
         Result /= Void;
         Result.key = k

feature(s) from AVL_DICTIONARY_NODE
   value: V

   set_value (v: V)
      ensure
         value = v

   at (k: K): AVL_DICTIONARY_NODE[V, K]
      -- Is element e in the tree?

   fast_at (k: K): AVL_DICTIONARY_NODE[V, K]
      -- Is element e in the tree?

   occurrences (v: V): INTEGER

   fast_occurrences (v: V): INTEGER

   key_at (v: V): K

   fast_key_at (v: V): K

feature(s) from AVL_DICTIONARY_NODE
   occurrences_ (v: V; cnt: INTEGER): INTEGER
      ensure
         Result >= cnt

   fast_occurrences_ (v: V; cnt: INTEGER): INTEGER
      ensure
         Result >= cnt


invariant

    left /= Void implies left < Current;

    right /= Void implies Current < right;

end of AVL_DICTIONARY_NODE[V,K->COMPARABLE]