% -----------------------------------------------------------------------------
%  (C) Altran Praxis Limited
% -----------------------------------------------------------------------------
% 
%  The SPARK toolset is free software; you can redistribute it and/or modify it
%  under terms of the GNU General Public License as published by the Free
%  Software Foundation; either version 3, or (at your option) any later
%  version. The SPARK toolset 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 General
%  Public License for more details. You should have received a copy of the GNU
%  General Public License distributed with the SPARK toolset; see file
%  COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
%  the license.
% 
% =============================================================================


%-------------------------------------------------------------------------------
% RULE FAMILIES CONTAINED HEREIN :-
%
% enumeration  : more properties of enumerated types (pred & succ etc.)
%-------------------------------------------------------------------------------
% MODEL DECLARATIONS FOR THIS FILE :-
%
% rule_family enumeration:
%         X <= Y  requires [ X:e,   Y:e   ] &
%         X < Y   requires [ X:e,   Y:e   ] &
%         X >= Y  requires [ X:e,   Y:e   ] &
%         X > Y   requires [ X:e,   Y:e   ] &
%         X <> Y  requires [ X:e,   Y:e   ] &
%         succ(X) requires [ X:e          ] &
%         pred(X) requires [ X:e          ].
%-------------------------------------------------------------------------------


/*** Enumerated type inequality rules ***/

/* Predecessor */

enumeration(1):		X <= pred(Y) may_be_deduced_from [ X < Y        ].
enumeration(2):		pred(X) <= Y may_be_deduced_from
					[ X <= Y, goal(checktype(X, T)),
					  goal(enumeration(T, [E|_])),
					  X <> E ].
enumeration(3):		pred(X) >= Y may_be_deduced_from [ X > Y        ].
enumeration(4):		X >= pred(Y) may_be_deduced_from
					[ X >= Y, goal(checktype(Y, T)),
					  goal(enumeration(T, [E|_])),
					  Y <> E ].

enumeration(5):		X > Y        may_be_deduced_from [ pred(X) >= Y ].
enumeration(6):		X < Y        may_be_deduced_from [ X <= pred(Y) ].
enumeration(7):		X <= Y       may_be_deduced_from [ pred(X) < Y  ].
enumeration(8):		X >= Y       may_be_deduced_from [ X > pred(Y)  ].

enumeration(9):		pred(X) < Y  may_be_deduced_from
					[ X <= Y, goal(checktype(X, T)),
					  goal(enumeration(T, [E|_])),
					  X <> E ].
enumeration(10):	X > pred(Y)  may_be_deduced_from
					[ X >= Y, goal(checktype(Y, T)),
					  goal(enumeration(T, [E|_])),
					  Y <> E ].

enumeration(11):	pred(X) < X  may_be_deduced_from
					[ goal(checktype(X, T)),
					  goal(enumeration(T,[E|_])),
					  X <> E ].
enumeration(12):	X > pred(X)  may_be_deduced_from
					[ goal(checktype(X, T)),
					  goal(enumeration(T,[E|_])),
					  X <> E ].


/* Successor */

enumeration(13):	X <= succ(Y) may_be_deduced_from
					[ X <= Y, goal(checktype(Y, T)),
					  goal(enumeration(T, L)),
					  goal(last(L, E)),
					  Y <> E ].
enumeration(14):	succ(X) <= Y may_be_deduced_from [ X < Y        ].
enumeration(15):	succ(X) >= Y may_be_deduced_from
					[ X >= Y, goal(checktype(X, T)),
					  goal(enumeration(T, L)),
					  goal(last(L, E)),
					  X <> E ].
enumeration(16):	X >= succ(Y) may_be_deduced_from [ X > Y        ].

enumeration(17):	X < Y        may_be_deduced_from [ succ(X) <= Y ].
enumeration(18):	X > Y        may_be_deduced_from [ X >= succ(Y) ].
enumeration(19):	X >= Y       may_be_deduced_from [ succ(X) > Y  ].
enumeration(20):	X <= Y       may_be_deduced_from [ X < succ(Y)  ].

enumeration(21):	succ(X) > Y  may_be_deduced_from
					[ X >= Y, goal(checktype(X, T)),
					  goal(enumeration(T, L)),
					  goal(last(L, E)),
					  X <> E ].
enumeration(22):	X < succ(Y)  may_be_deduced_from
					[ X <= Y, goal(checktype(Y, T)),
					  goal(enumeration(T, L)),
					  goal(last(L, E)),
					  Y <> E ].

enumeration(23):	succ(X) > X  may_be_deduced_from
					[ goal(checktype(X, T)),
					  goal(enumeration(T, L)),
					  goal(last(L, E)),
					  X <> E ].
enumeration(24):	X < succ(X)  may_be_deduced_from
					[ goal(checktype(X, T)),
					  goal(enumeration(T, L)),
					  goal(last(L, E)),
					  X <> E ].


/* General */

enumeration(25):	X <> E       may_be_deduced_from
					[ X > Y, goal(checktype(X, T)),
					  goal(enumeration(T, [E|_])) ].

enumeration(26):	X <> E       may_be_deduced_from
					[ X < Y, goal(checktype(X, T)),
					  goal(enumeration(T, L)),
					  goal(last(L, E)) ].


/*============================================================================*

 Justifications
 --------------

 1:  If X < Y, then X <= pred(Y) must hold.  (Note that because X < Y, Y
     cannot be equal to the first enumeration literal in its type.)
 2:  If X <= Y, then if pred(X) exists it must also be <= Y.  (The additional
     immediate conditions ensure X is not the first literal, so pred(X)
     does indeed exist.)
 3:  This rule is equivalent to rule 1 (though with X and Y interchanged).
 4:  This rule is equivalent to rule 2 (though with X and Y interchanged).
 5:  Given pred(X) >= Y, X cannot be the first enumeration literal in its type
     and given X > pred(X) (rule 12) we see X > Y by transitivity.
 6:  This rule is equivalent to rule 5 (though with X and Y interchanged).
 7:  Given pred(X) < Y, X cannot be the first enumeration literal in its type.
     If pred(X) < Y it follows that X <= Y (since if X > Y were to hold, then
     pred(X) would have to be at least Y).
 8:  This rule is equivalent to rule 7 (though with X and Y interchanged).
 9:  If X <= Y then provided X is not equal to the first enumeration literal
     in its type, pred(X) exists and pred(X) < X (rule 11), so pred(X) < Y by
     transitivity.
 10: This rule is equivalent to rule 9 (though with X and Y interchanged).
 11: If X is not equal to the first enumeration literal in its type, then
     pred(X) exists.  Whenever this is so, pred(X) precedes X in the type,
     so pred(X) < X holds in such cases as required.
 12: This rule is equivalent to rule 11.
 13: If Y is not equal to the last enumeration literal in its type, then
     succ(Y) exists and Y<succ(Y) (rule 24), so X <= succ(Y) by transitivity.
 14: If X < Y, X cannot be the last enumeration literal in its type, so
     succ(X) exists and must be at most Y (since if it were greater than Y,
     then X would have to be at least Y, contradicting X < Y).
 15: This rule is equivalent to rule 13 (though with X and Y interchanged).
 16: This rule is equivalent to rule 14 (though with X and Y interchanged).
 17: Given succ(X) <= Y, X is not the last enumeration literal in its type, so
     X < succ(X) (rule 24), thus X < Y by transitivity.
 18: This rule is equivalent to rule 17 (though with X and Y interchanged).
 19: If succ(X) > Y, then X must be at least Y as required.
 20: This rule is equivalent to rule 19 (though with X and Y interchanged).
 21: If X is not the last enumeration literal in its type, then succ(X) > X
     (rule 23), so succ(X) > Y follows from X >= Y by transitivity.
 22: This rule is equivalent to rule 21 (though with X and Y interchanged).
 23: If X is not equal to the last enumeration literal in its type, then
     succ(X) exists.  Whenever this is so, succ(X) succeeds X in the type,
     so succ(X) > X holds in such cases as required.
 24: This rule is equivalent to rule 23.
 25: If X is bigger than something (Y), then X cannot be equal to the first
     enumeration literal in its type.
 26: If X is smaller than something (Y), then X cannot be equal to the last
     enumeration literal in its type.

 *============================================================================*/

