#
#  File: list.k3
#  Handles linear lists of INTs.
#
#  Copyright 2005 Radboud University of Nijmegen
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Library General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#  CVS ID: "$Id: list.k3,v 1.8 2006/01/09 16:50:05 marcs Exp $"
#
MODULE list.

DEFINES	LIST,
	SLIST,

	FUNCTION empty (LIST>),
	TEST is empty (>LIST),
	TEST pop (>LIST>, INT>),
	FUNCTION push (>LIST>, >INT),
	FUNCTION get size (>LIST, INT>),

	FUNCTION empty (SLIST>),
	TEST is empty (>SLIST),
	TEST pop (>SLIST>, INT>),
	FUNCTION add (>SLIST>, >INT),
	FUNCTION add (>SLIST1>, >SLIST2),
	FUNCTION remove (>SLIST1>, >SLIST2),
	FUNCTION remove (>SLIST>, >INT),
	TEST is element (>INT, >SLIST),
	FUNCTION get size (>SLIST, INT>),

	FUNCTION convert >SLIST to LIST>,
	FUNCTION convert sorted >LIST to SLIST>,
	FUNCTION convert >SLIST to TEXT>,
	FUNCTION convert >LIST to TEXT>.

#
# Lists are lists of INTs
#
LIST :: hd INT tl LIST;
        nil.

FUNCTION empty (LIST>):
  [ nil -> LIST ].

TEST is empty (>LIST):
  [ LIST -> nil ].

# Do not use push and pop in right recursive functions, otherwise recursion
# will not be removed from those functions due to compiler stupidity.

FUNCTION push (>LIST>, >INT):
  [ hd INT tl LIST -> LIST ].

TEST pop (>LIST>, INT>):
  [ LIST -> hd INT tl LIST ].

FUNCTION get size (>LIST, INT>):
  [ LIST -> nil ], [ 0 -> INT ];
  [ LIST -> hd INT tl LIST1 ], get size (LIST1, INT1), [ INT1 + 1 -> INT ];
  ?.

#
# Sets as ordered lists
#
#
# Invariant: small elements before larger elements in tail.
#
SLIST :: sorted LIST.

FUNCTION empty (SLIST>):
  empty (LIST), convert sorted LIST to SLIST.

TEST is empty (>SLIST):
  convert SLIST to LIST, is empty (LIST).

TEST pop (>SLIST>, INT>):
  convert SLIST to LIST,
    pop (LIST, INT),
      convert sorted LIST to SLIST.

FUNCTION add (>SLIST>, >INT):
  convert SLIST to LIST,
    add (LIST, INT),
    convert sorted LIST to SLIST.

FUNCTION add (>SLIST1>, >SLIST2):
  convert SLIST1 to LIST1, convert SLIST2 to LIST2,
    add (LIST1, LIST2), convert sorted LIST1 to SLIST1.

FUNCTION remove (>SLIST1>, >SLIST2):
  convert SLIST1 to LIST1, convert SLIST2 to LIST2,
    remove (LIST1, LIST2), convert sorted LIST1 to SLIST1.

FUNCTION remove (>SLIST>, >INT):
  convert SLIST to LIST,
    remove (LIST, INT),
    convert sorted LIST to SLIST.

TEST is element (>INT, >SLIST):
  convert SLIST to LIST,
    is element (INT, LIST).

FUNCTION get size (>SLIST, INT>):
  convert SLIST to LIST,
    get size (LIST, INT).

#
# Implementation of sorted list operations
#
FUNCTION add (>LIST1>, >LIST2):
  [ LIST1 -> nil ], [ LIST2 -> LIST1 ];
  [ LIST2 -> nil ];
  [ LIST1 -> hd INT1 tl LIST3 ], [ LIST2 -> hd INT2 tl LIST4 ],
    ( [ INT1 = INT2 ],   add (LIST3, LIST4), [ hd INT1 tl LIST3 -> LIST1 ];
      less (INT1, INT2), add (LIST3, LIST2), [ hd INT1 tl LIST3 -> LIST1 ];
      add (LIST1, LIST4), [ hd INT2 tl LIST1 -> LIST1 ]
    );
  ?.

FUNCTION remove (>LIST1>, >LIST2):
  [ LIST1 -> nil ];
  [ LIST2 -> nil ];
  [ LIST1 -> hd INT1 tl LIST3 ], [ LIST2 -> hd INT2 tl LIST4 ],
    ( [ INT1 = INT2 ], remove (LIST3, LIST4), [ LIST3 -> LIST1 ];
      less (INT1, INT2), remove (LIST3, LIST2), [ hd INT1 tl LIST3 -> LIST1 ];
      remove (LIST1, LIST4)
    );
  ?.

FUNCTION add (>LIST>, >INT):
  [ LIST -> nil ], [ hd INT tl nil -> LIST ];
  [ LIST -> hd INT1 tl LIST1 ],
    ( [ INT = INT1 ];
      less (INT, INT1), [ hd INT tl LIST -> LIST ];
      add (LIST1, INT), [ hd INT1 tl LIST1 -> LIST ]
    );
  ?.

FUNCTION remove (>LIST>, >INT):
  [ LIST -> nil ];
  [ LIST -> hd INT1 tl LIST1 ],
    ( [ INT = INT1 ], [ LIST1 -> LIST ];
      less (INT, INT1);				# Note sorting
      remove (LIST1, INT), [ hd INT1 tl LIST1 -> LIST ]
    );
  ?.

TEST is element (>INT, >LIST):
  [ LIST -> hd INT1 tl LIST1 ],
    ( [ INT = INT1 ];
      less (INT1, INT), is element (INT, LIST1)
    ).

#
# Conversions
#
FUNCTION convert >SLIST to LIST>:
  [ SLIST -> sorted LIST ].

FUNCTION convert sorted >LIST to SLIST>:
  [ sorted LIST -> SLIST ].

FUNCTION convert >SLIST to TEXT>:
  convert SLIST to LIST,
    convert LIST to TEXT.

FUNCTION convert >LIST to TEXT>:
  is empty (LIST), [ "[]" -> TEXT ];
  convert nonempty LIST to TEXT, [ "[ " + TEXT + " ]" -> TEXT ].

FUNCTION convert nonempty >LIST to TEXT>:
  pop (LIST, INT), bindec (INT, TEXT),
    ( is empty (LIST);
      convert nonempty LIST to TEXT1, [ TEXT + ", " + TEXT1 -> TEXT ]
    );
  ?.
