module xstorage;

% Storage and retrieval of critical pairs and polynomials.

% Author: David Hartley

Comment. Critical pairs and polynomials are stored in a search tree,
	 called an xset here:

	xset		::= empty_xset | item . xset
	empty_xset	::= any . nil
	item		::= any

All changes to xset are made destructively as side-effects.

endcomment;


symbolic smacro procedure xset_ptrs c;
   cdr c;


symbolic smacro procedure left_xset c;
   cadr c;


symbolic smacro procedure right_xset c;
   cddr c;


symbolic procedure find_item(pr,c);
   % pr:item, c:xset -> find_item:xset|nil
   % if pr in c, returns pointer to pr, otherwise nil
   if empty_xsetp c then nil
   else find_item(pr,left_xset c) or
	(if xset_item c = pr then c) or
	find_item(pr,right_xset c);
 

symbolic procedure add_item(pr,c);
   % pr:item, c:xset -> add_item:nil
   % add new item pr to structure c as side-effect
   % goes left iff xkey pr < xkey xset_item c
   if empty_xsetp c then
    <<xset_item c := pr;
      xset_ptrs c := empty_xset() . empty_xset();>>
   else if monordp(xkey xset_item c,xkey pr) then
      add_item(pr,left_xset c)
   else
      add_item(pr,right_xset c);


symbolic procedure remove_item(pr,c);
   % pr:item, c:xset -> remove_item:item or nil
   % deletes pr, if present, from c as side-effect
   if c := find_item(pr,c) then remove_root_item c;


symbolic procedure remove_least_item c;
   % c:xset -> remove_least_item:item
   % returns "least" item in structure and deletes it as side-effect
   if empty_xsetp c then rederr "How did we get here?"
   else if empty_xsetp left_xset c then remove_root_item c
   else remove_least_item left_xset c;


symbolic procedure remove_root_item c;
   % c:xset -> remove_root_item:item
   % deletes first item in c, which is not empty
   begin scalar x,y;
   x := left_xset c; y := xset_item c;  
   xset_item c := xset_item right_xset c;
   xset_ptrs c := xset_ptrs right_xset c;
   if not empty_xsetp x then % graft x onto the left-most part of c
    <<while not empty_xsetp c do c := left_xset c;
      xset_item c := xset_item x;
      xset_ptrs c := xset_ptrs x>>;
   return y;
   end;


symbolic procedure remove_items(c,u);
   % c:xset of lists, u:list -> remove_items:nil
   % removes all items containing elements of u from c
   begin
   if empty_xsetp c then return;
   remove_items(left_xset c,u);
   remove_items(right_xset c,u);
   if xnp(u,xset_item c) then remove_root_item c;
   end;

endmodule;

end;
