% -----------------------------------------------------------------------------
%  (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.
% 
% =============================================================================


/*** (1) Map principal functor structure to built-in rulefile name ***/

built_in_rulefile( <(_,_),                 file=="NUMINEQS"     ).
built_in_rulefile( <=(_,_),                file=="NUMINEQS"     ).
built_in_rulefile( >(_,_),                 file=="NUMINEQS"     ).
built_in_rulefile( >=(_,_),                file=="NUMINEQS"     ).
built_in_rulefile( =(_,_),                 file=="NUMINEQS"     ).
built_in_rulefile( <>(_,_),                file=="NUMINEQS"     ).
built_in_rulefile( or(_,_),                file=="NUMINEQS"     ).

built_in_rulefile( <(_,_),                 file=="GENINEQS"     ).
built_in_rulefile( <=(_,_),                file=="GENINEQS"     ).
built_in_rulefile( >(_,_),                 file=="GENINEQS"     ).
built_in_rulefile( >=(_,_),                file=="GENINEQS"     ).
built_in_rulefile( =(_,_),                 file=="GENINEQS"     ).
built_in_rulefile( <>(_,_),                file=="GENINEQS"     ).
built_in_rulefile( not(_),                 file=="GENINEQS"     ).

built_in_rulefile( <=(_,_),                file=="INTINEQS"     ).
built_in_rulefile( >(_,_),                 file=="INTINEQS"     ).
built_in_rulefile( >=(_,_),                file=="INTINEQS"     ).
built_in_rulefile( =(_,_),                 file=="INTINEQS"     ).

built_in_rulefile( _ + _,                  file=="ARITH"        ).
built_in_rulefile( _ - _,                  file=="ARITH"        ).
built_in_rulefile( _ * _,                  file=="ARITH"        ).
built_in_rulefile( _ div _,                file=="ARITH"        ).
built_in_rulefile( -(_),                   file=="ARITH"        ).
built_in_rulefile( _ / _,                  file=="ARITH"        ).
built_in_rulefile( _ = _,                  file=="ARITH"        ) :-
        use_subst_rules_for_equality(on).

built_in_rulefile( element(_,_),           file=="ARRAY"        ).
built_in_rulefile( update(_,_,_),          file=="ARRAY"        ).
built_in_rulefile( _ = _,                  file=="ARRAY"        ) :-
        use_subst_rules_for_equality(on).

built_in_rulefile( =(_,_),                 file=="ENUM"         ).
built_in_rulefile( <=(_,_),                file=="ENUM"         ).
built_in_rulefile( <(_,_),                 file=="ENUM"         ).
built_in_rulefile( >=(_,_),                file=="ENUM"         ).
built_in_rulefile( >(_,_),                 file=="ENUM"         ).
built_in_rulefile( <>(_,_),                file=="ENUM"         ).
built_in_rulefile( succ(_),                file=="ENUM"         ).
built_in_rulefile( pred(_),                file=="ENUM"         ).
built_in_rulefile( or(_,_),                file=="ENUM"         ).

built_in_rulefile( <=(_,_),                file=="ENUMERATION"  ).
built_in_rulefile( <(_,_),                 file=="ENUMERATION"  ).
built_in_rulefile( >=(_,_),                file=="ENUMERATION"  ).
built_in_rulefile( >(_,_),                 file=="ENUMERATION"  ).
built_in_rulefile( <>(_,_),                file=="ENUMERATION"  ).
built_in_rulefile( succ(_),                file=="ENUMERATION"  ).
built_in_rulefile( pred(_),                file=="ENUMERATION"  ).

built_in_rulefile( abs(_),                 file=="FDLFUNCS"     ).
built_in_rulefile( >=(_,_),                file=="FDLFUNCS"     ).
built_in_rulefile( >(_,_),                 file=="FDLFUNCS"     ).
built_in_rulefile( or(_,_),                file=="FDLFUNCS"     ).
built_in_rulefile( *(_,_),                 file=="FDLFUNCS"     ).
built_in_rulefile( sqr(_),                 file=="FDLFUNCS"     ).
built_in_rulefile( odd(_),                 file=="FDLFUNCS"     ).
built_in_rulefile( not(_),                 file=="FDLFUNCS"     ).
built_in_rulefile( =(_,_),                 file=="FDLFUNCS"     ).
built_in_rulefile( <>(_,_),                file=="FDLFUNCS"     ).
built_in_rulefile( **(_,_),                file=="FDLFUNCS"     ).  /* CFR042 */
built_in_rulefile( <=(_,_),                file=="FDLFUNCS"     ).  /* CFR042 */
built_in_rulefile( <(_,_),                 file=="FDLFUNCS"     ).  /* CFR042 */

built_in_rulefile( and(_,_),               file=="LOGIC"        ).
built_in_rulefile( or(_,_),                file=="LOGIC"        ).
built_in_rulefile( <->(_,_),               file=="LOGIC"        ).
built_in_rulefile( not(_),                 file=="LOGIC"        ).
built_in_rulefile( ->(_,_),                file=="LOGIC"        ).
built_in_rulefile( _ = _,                  file=="LOGIC"        ) :-
        use_subst_rules_for_equality(on).

built_in_rulefile( >=(_,_),                file=="SEQ"          ).
built_in_rulefile( >(_,_),                 file=="SEQ"          ).
built_in_rulefile( _ @ _,                  file=="SEQ"          ).
built_in_rulefile( [_|_],                  file=="SEQ"          ).
built_in_rulefile( length(_),              file=="SEQ"          ).
built_in_rulefile( first(_),               file=="SEQ"          ).
built_in_rulefile( last(_),                file=="SEQ"          ).
built_in_rulefile( nonfirst(_),            file=="SEQ"          ).
built_in_rulefile( nonlast(_),             file=="SEQ"          ).
built_in_rulefile( _ + _,                  file=="SEQ"          ).
built_in_rulefile( _ - _,                  file=="SEQ"          ).
built_in_rulefile( _ = _,                  file=="SEQ"          ).
built_in_rulefile( _ <-> _,                file=="SEQ"          ).

built_in_rulefile( in(_,_),                file=="SETS"         ).
built_in_rulefile( not_in(_,_),            file=="SETS"         ).
built_in_rulefile( subset_of(_,_),         file=="SETS"         ).
built_in_rulefile( strict_subset_of(_,_),  file=="SETS"         ).
built_in_rulefile( _ \/ _,                 file=="SETS"         ).
built_in_rulefile( _ /\ _,                 file=="SETS"         ).
built_in_rulefile( _ \ _,                  file=="SETS"         ).
built_in_rulefile( not(_),                 file=="SETS"         ).
built_in_rulefile( or(_,_),                file=="SETS"         ).
built_in_rulefile( _ = _,                  file=="SETS"         ) :-
        use_subst_rules_for_equality(on).

built_in_rulefile( for_all(_,_),           file=="QUANTIF"      ).
built_in_rulefile( for_some(_,_),          file=="QUANTIF"      ).
built_in_rulefile( not _,                  file=="QUANTIF"      ).
built_in_rulefile( _ or _,                 file=="QUANTIF"      ).
built_in_rulefile( _ = _,                  file=="QUANTIF"      ) :-
        use_subst_rules_for_equality(on).

built_in_rulefile( bit__and(_,_),  file=="BITWISE").
built_in_rulefile( bit__or(_,_),   file=="BITWISE").
built_in_rulefile( bit__xor(_,_),  file=="BITWISE").
built_in_rulefile( _ < _ ,         file=="BITWISE").
built_in_rulefile( _ <= _ ,        file=="BITWISE").
built_in_rulefile( _ = _ ,         file=="BITWISE").

built_in_rulefile( _ mod _,        file=="MODULAR").
built_in_rulefile( _ <= _,         file=="MODULAR").
built_in_rulefile( _ <> _,         file=="MODULAR").
built_in_rulefile( _ < _,          file=="MODULAR").
built_in_rulefile( _ = _,          file=="MODULAR").


/*** (2) Map built-in rulefile name to rule name ***/

built_in_rulefile( file=="NUMINEQS",    inequals(_)             ).
built_in_rulefile( file=="NUMINEQS",    zero(_)                 ).

built_in_rulefile( file=="GENINEQS",    transitivity(_)         ).
built_in_rulefile( file=="GENINEQS",    strengthen(_)           ).
built_in_rulefile( file=="GENINEQS",    negation(_)             ).

built_in_rulefile( file=="INTINEQS",    inequals(_)             ).

built_in_rulefile( file=="ARITH",       arith(_)                ).
built_in_rulefile( file=="ARITH",       assoc(_)                ).
built_in_rulefile( file=="ARITH",       commut(_)               ).
built_in_rulefile( file=="ARITH",       distrib(_)              ).
built_in_rulefile( file=="ARITH",       minus(_)                ).
built_in_rulefile( file=="ARITH",       intdiv(_)               ).

built_in_rulefile( file=="ARRAY",       array(_)                ).
built_in_rulefile( file=="ARRAY",       mk__array(_)            ) :- spark_enabled. /* CFR040 */

built_in_rulefile( file=="ENUM",        enum(_)                 ).
built_in_rulefile( file=="ENUM",        enum_cases(_)           ).
built_in_rulefile( file=="ENUMERATION", enumeration(_)          ).

built_in_rulefile( file=="FDLFUNCS",    abs(_)                  ).
built_in_rulefile( file=="FDLFUNCS",    sqr(_)                  ).
built_in_rulefile( file=="FDLFUNCS",    odd(_)                  ).
built_in_rulefile( file=="FDLFUNCS",    exp(_)                  ).  /* CFR042 */

built_in_rulefile( file=="LOGIC",       assoc(_)                ).
built_in_rulefile( file=="LOGIC",       commut(_)               ).
built_in_rulefile( file=="LOGIC",       distrib(_)              ).
built_in_rulefile( file=="LOGIC",       equivalence(_)          ).
built_in_rulefile( file=="LOGIC",       implies(_)              ).
built_in_rulefile( file=="LOGIC",       logical_and(_)          ).
built_in_rulefile( file=="LOGIC",       logical_not(_)          ).
built_in_rulefile( file=="LOGIC",       logical_or(_)           ).
built_in_rulefile( file=="LOGIC",       logical(_)              ).

built_in_rulefile( file=="SEQ",         seqlen(_)               ).
built_in_rulefile( file=="SEQ",         append(_)               ).
built_in_rulefile( file=="SEQ",         first(_)                ).
built_in_rulefile( file=="SEQ",         last(_)                 ).
built_in_rulefile( file=="SEQ",         nonfirst(_)             ).
built_in_rulefile( file=="SEQ",         nonlast(_)              ).
built_in_rulefile( file=="SEQ",         seq(_)                  ).

built_in_rulefile( file=="SETS",        sets(_)                 ).

built_in_rulefile( file=="QUANTIF",     quant(_)                ).

built_in_rulefile( file=="BITWISE", bitwise(_) ) :- spark_enabled.

built_in_rulefile( file=="MODULAR", modular(_) ) :- spark_enabled.



/*** SPECIAL RULES ***/

special_rulefile( _,                    file=="SPECIAL"         ).
special_rulefile( _,                    file=="RECORD"          ).

special_rulefile( file=="SPECIAL",      inference(_)            ).
special_rulefile( file=="SPECIAL",      simplify(_)             ).
special_rulefile( file=="SPECIAL",      logic(_)                ).
special_rulefile( file=="SPECIAL",      standardisation(_)      ).
special_rulefile( file=="SPECIAL",      eq(_)                   ).
special_rulefile( file=="SPECIAL",      equiv(_)                ).
special_rulefile( file=="SPECIAL",      unification(_)          ).

special_rulefile( file=="RECORD",       record(_)               ).
special_rulefile( file=="RECORD",       record_equality(_)      ).
special_rulefile( file=="RECORD",       mk__record(_)           ) :- spark_enabled.  /* CFR040 */


/*** Definition of rulefile(_,_) predicate ***/

rulefile(X,Y) :-
        nonvar(X),
        X = (_ = _),
        spade_checker_prefix(SPADE_CHECKER),                    /* CFR048 */
        !,
        (
           ( var(Y) ; atom(Y) ),                                /* CFR048 */
           built_in_rulefile(X,file==YY),                       /* CFR048 */
           append(YY, ".RUL", YYL),                             /* CFR048 */
           append(SPADE_CHECKER, YYL, YL),                      /* CFR048 */
           name(Y, YL)                                          /* CFR048 */
        ;
           user_rulefile(X,Y)
        ;
           user_rulefile(_A,Y),
           \+ user_rulefile(X,Y),
           use_subst_rules_for_equality(on)
        ;
           ( var(Y) ; atom(Y) ),                                /* CFR048 */
           special_rulefile(X,file==YY),                        /* CFR048 */
           append(YY, ".RUL", YYL),                             /* CFR048 */
           append(SPADE_CHECKER, YYL, YL),                      /* CFR048 */
           name(Y, YL)                                          /* CFR048 */
        ).
rulefile(X,Y) :-
        spade_checker_prefix(SPADE_CHECKER),                    /* CFR048 */
        (
           ( var(Y) ; atom(Y) ),                                /* CFR048 */
           built_in_rulefile(X,file==YY),                       /* CFR048 */
           append(YY, ".RUL", YYL),                             /* CFR048 */
           append(SPADE_CHECKER, YYL, YL),                      /* CFR048 */
           name(Y, YL)                                          /* CFR048 */
        ;                                                       /* CFR048 */
           atom(X),                                             /* CFR048 */
           name(X, XL),                                         /* CFR048 */
           triple_append(SPADE_CHECKER, XX, ".RUL", XL),        /* CFR048 */
           built_in_rulefile(file==XX,Y)                        /* CFR048 */
        ;
           user_rulefile(X,Y)
        ;
           ( var(Y) ; atom(Y) ),                                /* CFR048 */
           special_rulefile(X,file==YY),                        /* CFR048 */
           append(YY, ".RUL", YYL),                             /* CFR048 */
           append(SPADE_CHECKER, YYL, YL),                      /* CFR048 */
           name(Y, YL)                                          /* CFR048 */
        ;                                                       /* CFR048 */
           atom(X),                                             /* CFR048 */
           name(X, XL),                                         /* CFR048 */
           triple_append(SPADE_CHECKER, XX, ".RUL", XL),        /* CFR048 */
           special_rulefile(file==XX,Y)                         /* CFR048 */
        ).


/*** TYPE CONSTRAINTS OF BUILT-IN RULE FILES ***/

built_in_classification(X+Y,         "ARITH",     arith(_),        [X:ir, Y:ir]).
built_in_classification(X-Y,         "ARITH",     arith(_),        [X:ir, Y:ir]).
built_in_classification(X*Y,         "ARITH",     arith(_),        [X:ir, Y:ir]).
built_in_classification(X/Y,         "ARITH",     arith(_),        [X:ir, Y:ir]).
built_in_classification(X div Y,     "ARITH",     arith(_),        [X:i, Y:i]).
built_in_classification(X=Y,         "ARITH",     arith(_),        [X:ir, Y:ir]) :-
        use_subst_rules_for_equality(on).

built_in_classification(X+Y,         "ARITH",     assoc(_),        [X:ir, Y:ir]).
built_in_classification(X*Y,         "ARITH",     assoc(_),        [X:ir, Y:ir]).
built_in_classification(X*Y,         "ARITH",     assoc(_),        [X:ir, Y:ir]).
built_in_classification(X=Y,         "ARITH",     assoc(_),        [X:ir, Y:ir]) :-
        use_subst_rules_for_equality(on).

built_in_classification(X+Y,         "ARITH",     commut(_),       [X:ir, Y:ir]).
built_in_classification(X*Y,         "ARITH",     commut(_),       [X:ir, Y:ir]).
built_in_classification(X=Y,         "ARITH",     commut(_),       [X:ir, Y:ir]) :-
        use_subst_rules_for_equality(on).

built_in_classification(X+Y,         "ARITH",     distrib(_),      [X:ir, Y:ir]).
built_in_classification(X-Y,         "ARITH",     distrib(_),      [X:ir, Y:ir]).
built_in_classification(X*Y,         "ARITH",     distrib(_),      [X:ir, Y:ir]).
built_in_classification(X=Y,         "ARITH",     distrib(_),      [X:ir, Y:ir]) :-
        use_subst_rules_for_equality(on).

built_in_classification(X-Y,         "ARITH",     minus(_),        [X:ir, Y:ir]).
built_in_classification(X+Y,         "ARITH",     minus(_),        [X:ir, Y:ir]).
built_in_classification(-X,          "ARITH",     minus(_),        [X:ir]).
built_in_classification(X*Y,         "ARITH",     minus(_),        [X:ir, Y:ir]).
built_in_classification(X=Y,         "ARITH",     minus(_),        [X:ir, Y:ir]) :-
        use_subst_rules_for_equality(on).

built_in_classification(X+Y,         "ARITH",     intdiv(_),       [X:i, Y:i]).
built_in_classification(X div Y,     "ARITH",     intdiv(_),       [X:i, Y:i]).
built_in_classification(-X,          "ARITH",     intdiv(_),       [X:i]).
built_in_classification(X=Y,         "ARITH",     intdiv(_),       [X:i, Y:i]) :-
        use_subst_rules_for_equality(on).

built_in_classification(_,           "ARRAY",     array(_),        []).
built_in_classification(element(_,_),"ARRAY",     mk__array(_),        []) :- spark_enabled.  /* CFR040 */

built_in_classification(X=Y,         "ENUM",      enum(_),         [X:e, Y:e]).
built_in_classification(X<>Y,        "ENUM",      enum(_),         [X:e, Y:e]).
built_in_classification(X<=Y,        "ENUM",      enum(_),         [X:e, Y:e]).
built_in_classification(X<Y,         "ENUM",      enum(_),         [X:e, Y:e]).
built_in_classification(X>=Y,        "ENUM",      enum(_),         [X:e, Y:e]).
built_in_classification(X>Y,         "ENUM",      enum(_),         [X:e, Y:e]).
built_in_classification(pred(_),     "ENUM",      enum(_),         []).
built_in_classification(succ(_),     "ENUM",      enum(_),         []).
built_in_classification(_X or _Y,      "ENUM",      enum(_),         []).

built_in_classification(_X or _Y,      "ENUM",      enum_cases(_),   []).

built_in_classification(X<>Y,        "ENUMERATION",      enumeration(_),         [X:e, Y:e]).
built_in_classification(X<=Y,        "ENUMERATION",      enumeration(_),         [X:e, Y:e]).
built_in_classification(X<Y,         "ENUMERATION",      enumeration(_),         [X:e, Y:e]).
built_in_classification(X>=Y,        "ENUMERATION",      enumeration(_),         [X:e, Y:e]).
built_in_classification(X>Y,         "ENUMERATION",      enumeration(_),         [X:e, Y:e]).
built_in_classification(pred(_),     "ENUMERATION",      enumeration(_),         []).
built_in_classification(succ(_),     "ENUMERATION",      enumeration(_),         []).

built_in_classification(abs(X),      "FDLFUNCS",  abs(_),          [X:ir]).
built_in_classification(X>=Y,        "FDLFUNCS",  abs(_),          [X:ir,Y:ir]).
built_in_classification(X>Y,         "FDLFUNCS",  abs(_),          [X:ir,Y:ir]).
built_in_classification(_X or _Y,      "FDLFUNCS",  abs(_),          []).
built_in_classification(X*Y,         "FDLFUNCS",  abs(_),          [X:ir,Y:ir]).
built_in_classification(X=Y,         "FDLFUNCS",  abs(_),          [X:ir, Y:ir]) :-
        use_subst_rules_for_equality(on).

built_in_classification(sqr(X),      "FDLFUNCS",  sqr(_),          [X:ir]).
built_in_classification(X>=Y,        "FDLFUNCS",  sqr(_),          [X:ir,Y:ir]).
built_in_classification(X>Y,         "FDLFUNCS",  sqr(_),          [X:ir,Y:ir]).
built_in_classification(X*Y,         "FDLFUNCS",  sqr(_),          [X:ir,Y:ir]).
built_in_classification(abs(X),      "FDLFUNCS",  sqr(_),          [X:ir]).
built_in_classification(X=Y,         "FDLFUNCS",  sqr(_),          [X:ir, Y:ir]) :-
        use_subst_rules_for_equality(on).

built_in_classification(odd(X),      "FDLFUNCS",  odd(_),          [X:i]).
built_in_classification(not(_X),      "FDLFUNCS",  odd(_),          []).
built_in_classification(X=Y,         "FDLFUNCS",  odd(_),          [X:i,Y:i]).
built_in_classification(X<>Y,        "FDLFUNCS",  odd(_),          [X:i,Y:i]).

built_in_classification(X**Y,        "FDLFUNCS",  exp(_),          [X:ir,Y:i]).     /* CFR042 */
built_in_classification(X*Y,         "FDLFUNCS",  exp(_),          [X:ir,Y:ir]).    /* CFR042 */
built_in_classification(X>=Y,        "FDLFUNCS",  exp(_),          [X:ir,Y:ir]).    /* CFR042 */
built_in_classification(X<=Y,        "FDLFUNCS",  exp(_),          [X:ir,Y:ir]).    /* CFR042 */
built_in_classification(X>Y,         "FDLFUNCS",  exp(_),          [X:ir,Y:ir]).    /* CFR042 */
built_in_classification(X<Y,         "FDLFUNCS",  exp(_),          [X:ir,Y:ir]).    /* CFR042 */
built_in_classification(X=Y,         "FDLFUNCS",  exp(_),          [X:ir,Y:ir]) :-  /* CFR042 */
        use_subst_rules_for_equality(on).

built_in_classification(_X and _Y,     "LOGIC",     assoc(_),        []).
built_in_classification(_X or _Y,      "LOGIC",     assoc(_),        []).
built_in_classification(_X <-> _Y,     "LOGIC",     assoc(_),        []).
built_in_classification(_X=_Y,         "LOGIC",     assoc(_),        []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X and _Y,     "LOGIC",     commut(_),       []).
built_in_classification(_X or _Y,      "LOGIC",     commut(_),       []).
built_in_classification(_X <-> _Y,     "LOGIC",     commut(_),       []).
built_in_classification(_X=_Y,         "LOGIC",     commut(_),       []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X and _Y,     "LOGIC",     distrib(_),      []).
built_in_classification(_X or _Y,      "LOGIC",     distrib(_),      []).
built_in_classification(_X=_Y,         "LOGIC",     distrib(_),      []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X <-> _Y,     "LOGIC",     equivalence(_),  []).
built_in_classification(_X=_Y,         "LOGIC",     equivalence(_),  []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X -> _Y,      "LOGIC",     implies(_),      []).
built_in_classification(_X=_Y,         "LOGIC",     implies(_),      []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X and _Y,     "LOGIC",     logical_and(_),  []).
built_in_classification(_X=_Y,         "LOGIC",     logical_and(_),  []) :-
        use_subst_rules_for_equality(on).

built_in_classification(not _X,       "LOGIC",     logical_not(_),  []).
built_in_classification(_X=_Y,         "LOGIC",     logical_not(_),  []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X or _Y,      "LOGIC",     logical_or(_),   []).
built_in_classification(_X=_Y,         "LOGIC",     logical_or(_),   []) :-
        use_subst_rules_for_equality(on).

built_in_classification(not _X,       "LOGIC",     logical(_),      []).
built_in_classification(_X and _Y,     "LOGIC",     logical(_),      []).
built_in_classification(_X or _Y,      "LOGIC",     logical(_),      []).
built_in_classification(_X -> _Y,      "LOGIC",     logical(_),      []).
built_in_classification(_X <-> _Y,     "LOGIC",     logical(_),      []).
built_in_classification(_X=_Y,         "LOGIC",     logical(_),      []) :-
        use_subst_rules_for_equality(on).

built_in_classification(X=Y,         "INTINEQS",  inequals(_),     [X:i, Y:i]).
built_in_classification(X<=Y,        "INTINEQS",  inequals(_),     [X:i, Y:i]).
built_in_classification(X>=Y,        "INTINEQS",  inequals(_),     [X:i, Y:i]).
built_in_classification(X>Y,         "INTINEQS",  inequals(_),     [X:i, Y:i]).

built_in_classification(X=Y,         "NUMINEQS",  inequals(_),     [X:ir, Y:ir]).
built_in_classification(X<>Y,        "NUMINEQS",  inequals(_),     [X:ir, Y:ir]).
built_in_classification(X<=Y,        "NUMINEQS",  inequals(_),     [X:ir, Y:ir]).
built_in_classification(X>=Y,        "NUMINEQS",  inequals(_),     [X:ir, Y:ir]).
built_in_classification(X<Y,         "NUMINEQS",  inequals(_),     [X:ir, Y:ir]).
built_in_classification(X>Y,         "NUMINEQS",  inequals(_),     [X:ir, Y:ir]).

built_in_classification(X=Y,         "NUMINEQS",  zero(_),         [X:ir, Y:ir]).
built_in_classification(X<>Y,        "NUMINEQS",  zero(_),         [X:ir, Y:ir]).
built_in_classification(_X or _Y,      "NUMINEQS",  zero(_),         []).

built_in_classification(_X=_Y,         "GENINEQS",  transitivity(_), []).
built_in_classification(_X<>_Y,        "GENINEQS",  transitivity(_), []).
built_in_classification(_X<=_Y,        "GENINEQS",  transitivity(_), []).
built_in_classification(_X>=_Y,        "GENINEQS",  transitivity(_), []).
built_in_classification(_X<_Y,         "GENINEQS",  transitivity(_), []).
built_in_classification(_X>_Y,         "GENINEQS",  transitivity(_), []).

built_in_classification(_X=_Y,         "GENINEQS",  strengthen(_),   []).
built_in_classification(_X<_Y,         "GENINEQS",  strengthen(_),   []).
built_in_classification(_X>_Y,         "GENINEQS",  strengthen(_),   []).

built_in_classification(_,           "GENINEQS",  negation(_),     []).

built_in_classification(_,           "QUANTIF",   quant(_),        []).

built_in_classification(X>=Y,        "SEQ",       seqlen(_),       [X:i, Y:i]).
built_in_classification(X>Y,         "SEQ",       seqlen(_),       [X:i, Y:i]).
built_in_classification(X+Y,         "SEQ",       seqlen(_),       [X:i, Y:i]).
built_in_classification(X-Y,         "SEQ",       seqlen(_),       [X:i, Y:i]).
built_in_classification(length(_),   "SEQ",       seqlen(_),       []).
built_in_classification(X=Y,         "SEQ",       seqlen(_),       [X:i, Y:i]) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X @ _Y,       "SEQ",       append(_),       []).
built_in_classification(_X=_Y,         "SEQ",       append(_),       []) :-
        use_subst_rules_for_equality(on).

built_in_classification(first(_),    "SEQ",       first(_),        []).
built_in_classification(_X=_Y,         "SEQ",       first(_),        []) :-
        use_subst_rules_for_equality(on).

built_in_classification(last(_),     "SEQ",       last(_),         []).
built_in_classification(_X=_Y,         "SEQ",       last(_),         []) :-
        use_subst_rules_for_equality(on).

built_in_classification(nonfirst(_), "SEQ",       nonfirst(_),     []).
built_in_classification(_X @ _Y,       "SEQ",       nonfirst(_),     []).
built_in_classification(_X=_Y,         "SEQ",       nonfirst(_),     []) :-
        use_subst_rules_for_equality(on).

built_in_classification(nonlast(_),  "SEQ",       nonlast(_),      []).
built_in_classification(_X @ _Y,       "SEQ",       nonlast(_),      []).
built_in_classification([_|_],       "SEQ",       nonlast(_),      []).
built_in_classification(_X=_Y,         "SEQ",       nonlast(_),      []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_X = _Y,       "SEQ",       seq(_),          []).
built_in_classification(_X <-> _Y,     "SEQ",       seq(_),          []).

built_in_classification(_X in _Y,      "SETS",      sets(_),         []).
built_in_classification(_X not_in _Y,  "SETS",      sets(_),         []).
built_in_classification(not _X,       "SETS",      sets(_),         []).
built_in_classification(_X \/ _Y,      "SETS",      sets(_),         []).
built_in_classification(_X /\ _Y,      "SETS",      sets(_),         []).
built_in_classification(_X \ _Y,       "SETS",      sets(_),         []).
built_in_classification(_X subset_of _Y, "SETS",    sets(_),         []).
built_in_classification(_X strict_subset_of _Y, "SETS", sets(_),     []).
built_in_classification(_X or _Y,      "SETS",      sets(_),         []).
built_in_classification(_X=_Y,         "SETS",      sets(_),         []) :-
        use_subst_rules_for_equality(on).

built_in_classification(_,           "SPECIAL",   _,               []).
built_in_classification(_,           "RECORD",    _,               []).

/* Rule family declarations for BITWISE.RUL */
built_in_classification(bit__and(I,J),      "BITWISE",  bitwise(_), [I:i, J:i]).
built_in_classification(bit__or(I,J),       "BITWISE",  bitwise(_), [I:i, J:i]).
built_in_classification(bit__xor(I,J),      "BITWISE",  bitwise(_), [I:i, J:i]).
built_in_classification(I <= J,             "BITWISE",  bitwise(_), [I:i, J:i]).
built_in_classification(I = J,              "BITWISE",  bitwise(_), [I:i, J:i]).

/* Rule family declarations for MODULAR.RUL */
built_in_classification(I mod J,             "MODULAR",  modular(_), [I:i, J:i]).
built_in_classification(I <= J,              "MODULAR",  modular(_), [I:i, J:i]).
built_in_classification(I <> J,              "MODULAR",  modular(_), [I:i, J:i]).
built_in_classification(I < J,               "MODULAR",  modular(_), [I:i, J:i]).
built_in_classification(I = J,               "MODULAR",  modular(_), [I:i, J:i]).

/*** Definition of type_requirements(_,_,_,_) predicate ***/

type_requirements(A,B,C,D) :-
        spade_checker_prefix(SPADE_CHECKER),                    /* CFR048 */
        (
           atom(B),                                             /* CFR048 */
           name(B, BL),                                         /* CFR048 */
           triple_append(SPADE_CHECKER, BB, ".RUL", BL),        /* CFR048 */
           built_in_classification(A,BB,C,D)                    /* CFR048 */
        ;                                                       /* CFR048 */
           var(B),                                              /* CFR048 */
           built_in_classification(A,BB,C,D),                   /* CFR048 */
           append(BB, ".RUL", BBL),                             /* CFR048 */
           append(SPADE_CHECKER, BBL, BL),                      /* CFR048 */
           name(B, BL)                                          /* CFR048 */
        ;
           user_classification(A,B,C,D)
        ).
%###############################################################################
%END-OF-FILE
