%*****************************************************************************
%
%       Metis Utility
%               Multi - PSI version
%
%               created by      : A.Ohsuga
%               version         : 2.5
%               revision        : 0.0
%               date created    : 10-28-85
%               date changed    : 9-1-88
%               comments
%***************************************************************************

%:- op(10,xfx,(:)) .

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%       metis utility macro                                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

macro_bank metis_utility_macro has 

    nature
        metis_buildin_methods,
        metis_db_methods,
        metis_device_methods,
        metis_main_methods,
        metis_command_methods;
end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%       metis utility macro                                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

class metis_utility with_macro metis_utility_macro has

:metis_to_skolem(Class,A) :- to_skolem(A);
:metis_operator_infix(Class,Xfx):- operator_infix(Xfx);
:metis_is_var(Class,V) :- is_var(V);
:metis_to_skolem(Class,A,B,C) :- to_skolem(A,B,C);
:metis_to_skolem_list(Class,A) :- to_skolem_list(A);
:metis_to_skolem_list(Class,A,B,C) :- to_skolem_list(A,B,C);
:metis_from_skolem(Class,A,B) :- from_skolem(A,B);
:metis_from_skolem_list(Class,A,B) :- from_skolem_list(A,B);
:metis_to_successor_one(Class,A,B) :- to_successor_one(A,B);
:metis_from_Sexpression_and_successor(Class,A,B) :- from_Sexpression_and_successor(A,B);
:metis_from_successor_one(Class,A,B) :- from_successor_one(A,B);
:metis_to_linear(Class,A,B,C) :- to_linear(A,B,C);
:metis_get_top_operator(Class,A,B) :- get_top_operator(A,B);
:metis_get_top_operator_list(Class,A,B) :- get_top_operator_list(A,B);
:metis_get_top_sub_operator(Class,A,B,C) :- get_top_sub_operator(A,B,C);
:metis_get_top_sub_operator_list(Class,A,B,C) :- get_top_sub_operator_list(A,B,C);
:metis_get_one_list(Class,A,B,C) :- get_one_list(A,B,C);
:metis_get_one_list(Class,A,B) :- get_one_list(A,B);
:metis_get_first_operator(Class,A,B) :- get_first_operator(A,B);
:metis_get_operators_sweep(Class,A,B) :- get_operators_sweep(A,B);
:metis_get_operators(Class,A,B) :- get_operators(A,B);
:metis_get_variables_sweep(Class,A,B) :- get_variables_sweep(A,B);
:metis_get_variables(Class,A,B) :- get_variables(A,B);
:metis_list_to_atom(Class,A,B) :- list_to_atom(A,B);
:metis_list_to_dlist(Class,A,B,C) :- list_to_dlist(A,B,C);
:metis_list_from_dlist(Class,A,B,C) :- list_from_dlist(A,B,C);
:metis_lower_and_upper_string(Class,A,B) :- lower_and_upper_string(A,B);
:metis_lower_and_upper(Class,A,B) :- lower_and_upper(A,B);
:metis_unify_occ(Class,A,B) :- unify_occ(A,B);
:metis_dname(Class,A,B,C) :- dname(A,B,C);
:metis_member_of_list(Class,A,B,C) :- member_of_list(A,B,C);
:metis_compareSet(Class,A,B,C) :- compareSet(A,B,C);
:metis_delete_list(Class,A,B,C,D) :- delete_list(A,B,C,D);
:metis_delete_one_list(Class,A,B,C,D) :- delete_one_list(A,B,C,D);
:metis_can_delete_list(Class,A,B,C,D) :- can_delete_list(A,B,C,D);
:metis_sweep_list(Class,A,B,C) :- sweep_list(A,B,C);
:metis_union_list(Class,A,B,C,D) :- union_list(A,B,C,D);
:metis_intersect_list(Class,A,B,C,D) :- intersect_list(A,B,C,D);
:metis_intersect_list(Class,A,B,C,D,E,F) :- intersect_list(A,B,C,D,E,F);
:metis_app_list(Class,A,B,C) :- app_list(A,B,C);
:metis_rev_list(Class,A,B) :- rev_list(A,B);
:metis_front_ulmatch(Class,A,B) :- front_ulmatch(A,B);
:metis_front_ulmatch(Class,A,B,C) :- front_ulmatch(A,B,C);
:metis_middle_ulmatch(Class,A,B) :- middle_ulmatch(A,B);
:metis_is_list(Class,A) :- is_list(A);
:metis_is_string(Class,A) :- is_string(A);
:metis_counter(Class,A,B) :- counter(A,B);
:metis_counter(Class,A,B,C) :- counter(A,B,C);
:metis_counter(Class,A,B,C,D) :- counter(A,B,C,D);
:metis_trace_on(Class,A) :- trace_on(A);
:metis_traceoff(Class) :- traceoff;
:metis_trace(Class,A) :- trace(A);
:metis_trace(Class,A,B) :- trace(A,B);
:metis_is_trace(Class,A) :- is_trace(A);
:metis_notrace(Class,A) :- notrace(A);
:metis_notrace(Class,A,B) :- notrace(A,B);
:metis_not_flag_trace(Class,A) :- not_flag_trace(A);
:metis_retract_all(Class,A) :- retract_all(A);
:metis_bagoft(Class,A,B,C) :- bagoft(A,B,C);
:metis_operator_prefix(Class,A) :- operator_prefix(A);
:metis_operator_postfix(Class,A) :- operator_postfix(A);
:metis_not_seeing(Class,File) :- not_seeing(File);
:metis_not_unify(Class,L,R) :- not_unify(L,R);
:metis_not_not_unify(Class,L,R) :- not_not_unify(L,R);

local

%/*------------------------------------------------------*/
%/*      to skolem                                       */
%/*------------------------------------------------------*/
%:-public to_skolem/1;
%:-mode to_skolem(?);
to_skolem(X) :- !,
        to_skolem(X,0,_);

%:-public to_skolem/3;
%:-mode to_skolem(?,+,-);
to_skolem('$SKM'(C,_),C,C1) :- !,
        C1 is C+1;
to_skolem('$SKM'(_,_),C,C) :- !;
to_skolem('$VAR'(_),C,C) :- !;
to_skolem([_|Arg],Cin,Cout) :- !,
        to_skolem_list(Arg,Cin,Cout);
to_skolem(Term,Cin,Cout) :- !,
        Term=..[_|Arg],!,
        to_skolem_list(Arg,Cin,Cout);

%:- public to_skolem_list/1;
%:- mode to_skolem_list(+);
to_skolem_list(L) :- !,
        to_skolem_list(L,0,_);

%:- public to_skolem_list/3;
%:- mode to_skolem_list(+,+,-);
to_skolem_list([],C,C) :- !;
to_skolem_list([One|Rem],Cin,Cout) :- !,
        to_skolem(One,Cin,Cmed),!,
        to_skolem_list(Rem,Cmed,Cout);

%/*------------------------------------------------------*/
%/*      from skolem                                     */
%/*------------------------------------------------------*/
%:- public from_skolem/2;
%:- mode from_skolem(?,-);
from_skolem(V,V) :-
        var(V),!;
from_skolem('$SKM'(_,V),V) :- !;
from_skolem([Op|Args],[Op|Arg]) :- !,
        from_skolem_list(Args,Arg);
from_skolem(Ts,T) :- !,
        Ts=..[Op|Args],
        from_skolem_list(Args,Arg),!,
        T=..[Op|Arg];

%:- public from_skolem_list/2;
%:- mode from_skolem_list(+,?);
from_skolem_list([],[]) :- !;
from_skolem_list([Ts|Args],[T|Arg]) :- !,
        from_skolem(Ts,T),!,
        from_skolem_list(Args,Arg);

%/*------------------------------------------------------*/
%/*      to successor                                    */
%/*------------------------------------------------------*/
%%%:- public to_successor/2;
%%%:- mode to_successor(?,-);
%%to_successor(V,V) :-
%%      is_var(V),!;
%%to_successor([Num],SNum) :-
%%      integer(Num),
%%      to_successor_one([Num],SNum),!;
%%to_successor([F|Arg],[F|SArg]) :- !,
%%      to_successor_list(Arg,SArg);
%%
%%%:- public to_successor_list/2;
%%%:- mode to_successor_list(+,?);
%%to_successor_list([],[]) :- !;
%%to_successor_list([T|Rem],[ST|SRem]) :- !,
%%      to_successor(T,ST),
%%      to_successor_list(Rem,SRem);

%:- public to_successor_one/2;
%:- mode to_successor_one(+,-);
to_successor_one(In,Out) :-
        In >= 0,!,
        to_successor_one_cnv(In,Out);
to_successor_one(In,``(-(Out))) :- !,
        Med is -1*In,!,
        to_successor_one_cnv(Med,Out);

%:- mode to_successor_one_cnv(+,-);
to_successor_one_cnv(0,0) :- !;
to_successor_one_cnv(In,s(S)) :- !,
        Med is In-1,!,
        to_successor_one_cnv(Med,S);

%/*------------------------------------------------------*/
%/*      from S-expression and successor                 */
%/*------------------------------------------------------*/
%:- public from_Sexpression_and_successor/2;
%:- mode from_Sexpression_and_successor(+,-);
%%from_Sexpression_and_successor('$VAR'(C),'$VAR'(C)) :- !;
from_Sexpression_and_successor('$SKM'(_,V),V) :- !;
from_Sexpression_and_successor([s,Succs],Num) :-
        from_successor_one([s,Succs],Num),!;
from_Sexpression_and_successor([Op|Sarg],Term) :- !,
        from_Sexpression_and_successor_list(Sarg,Targ,[]),
        Term=..[Op|Targ];

%%%:- public from_Sexpression_and_successor_list/2;
%%%:- mode from_Sexpression_and_successor_list(?,+);
%%from_Sexpression_and_successor_list(L,SL) :- !,
%%      from_Sexpression_and_successor_list(normal,L-[],SL);

%:- mode from_Sexpression_and_successor_list(+,?,?);
from_Sexpression_and_successor_list([],X,X) :- !;
from_Sexpression_and_successor_list([Sone|Sarg],[Tone|Targ],TT) :- !,
        from_Sexpression_and_successor(Sone,Tone),!,
        from_Sexpression_and_successor_list(Sarg,Targ,TT);

%:- public from_successor_one/2;
%:- mode from_successor_one(?,-);
from_successor_one([0],0) :- !;
from_successor_one([s,Succs],Num) :- !,
        from_successor_one(Succs,Num0),
        Num is Num0+1;

%/*------------------------------------------------------*/
%/*      to linear term                                  */
%/*------------------------------------------------------*/
%:- public to_linear/3;
%:- mode to_linear(?,-,-);
to_linear(T,L,V) :- !,
        to_linear(T,L,MedV,[]),!,
        to_linear_sweep(MedV,[],V);

%:- mode to_linear(?,-,?,?);
to_linear(V,NewV,[``(V=NewV)|VT],VT) :-
        var(V),!;
to_linear('$SKM'(C,V),'$SKM'(C,V),VX,VX) :- !;
to_linear([Op|Arg],[Op|NewArg],Vh,Vt) :- !,
        to_linear_list(Arg,NewArg,Vh,Vt);

%%%:- public to_linear_list/2;
%%%:- mode to_linear_list(+,?);
%%to_linear_list(Lin,Lout) :- !,
%%      to_linear_list(Lin,Lout,_,_);

%:- mode to_linear_list(+,?,?,?);
to_linear_list([],[],VX,VX) :- !;
to_linear_list([One|Arg],[NewOne|NewArg],Vh,Vt) :- !,
        to_linear(One,NewOne,Vh,Vm),!,
        to_linear_list(Arg,NewArg,Vm,Vt);

%:- mode to_linear_sweep(+,+,-);
to_linear_sweep([],_,[]) :- !;
to_linear_sweep([``(V=NewV)|Vrem],Vext,[``(V=NewV)|NewVrem]) :-
        member_of_list(weak,V,Vext),!,
        to_linear_sweep(Vrem,Vext,NewVrem);
to_linear_sweep([``(V=V)|Vrem],Vext,NewVrem) :- !,
        to_linear_sweep(Vrem,[V|Vext],NewVrem);

%/*------------------------------------------------------*/
%/*      get top operator symbol                         */
%/*------------------------------------------------------*/
%:- public get_top_operator/2;
%:- mode get_top_operator(?,-);
get_top_operator(V,_) :-
        var(V),!;
get_top_operator('$SKM'(_,_),'') :- !;
%%get_top_operator('$VAR'(_),'') :- !;
get_top_operator([Op|_],Op) :- !;

%:- public get_top_operator_list/2;
%:- mode get_top_operator_list(+,?);
get_top_operator_list([],[]) :- !;
get_top_operator_list([T|Trem],[Op|OpRem]) :- !,
        get_top_operator(T,Op),!,
        get_top_operator_list(Trem,OpRem);

%/*------------------------------------------------------*/
%/*      get top and sub operator symbol                 */
%/*------------------------------------------------------*/
%:- public get_top_sub_operator/3;
%:- mode get_top_sub_operator(?,-,-);
get_top_sub_operator(V,_,_) :-
        var(V),!;
get_top_sub_operator('$SKM'(_,_),'','') :- !;
%%get_top_sub_operator('$VAR'(_),'','') :- !;
get_top_sub_operator([Op|Arg],Op,SubOp) :- !,
        get_first_operator(Arg,SubOp);

%:- public get_top_sub_operator_list/3;
%:- mode get_top_sub_operator_list(+,?,?);
get_top_sub_operator_list([],[],[]) :- !;
get_top_sub_operator_list([T|Trem],[Op|OpRem],[SubOp|SubOpRem]) :- !,
        get_top_sub_operator(T,Op,SubOp),!,
        get_top_sub_operator_list(Trem,OpRem,SubOpRem);

%/*------------------------------------------------------*/
%/*      get first operator symbol                       */
%/*------------------------------------------------------*/
%:- public get_first_operator/2;
%:- mode get_first_operator(+,-);
get_first_operator([Term|_],Op) :- !,
        get_top_operator(Term,Op);
get_first_operator(_,'') :- !;

%/*------------------------------------------------------*/
%/*      get all operators                               */
%/*------------------------------------------------------*/
%:- public get_operators_sweep/2;
%:- mode get_operators_sweep(?,-);
get_operators_sweep(Term,OPout) :- !,
        get_operators(Term,OPmed,[]),!,
        sweep_list(strong,OPmed,OPout);

%:- public get_operators/2;
%:- mode get_operators(?,-);
get_operators(Term,OP) :- !,
        get_operators(Term,OP,[]);

%:- mode get_operators(?,?,?);
get_operators(V,X,X) :-
        is_var(V),!;
get_operators([Op|Arg],[Op|Oh],Ot) :- !,
        get_operators_list(Arg,Oh,Ot);

%:- mode get_operators_list(+,?,?);
get_operators_list([],O,O) :- !;
get_operators_list([One|Rem],Oh,Ot) :- !,
        get_operators(One,Oh,Om),!,
        get_operators_list(Rem,Om,Ot);

%/*------------------------------------------------------*/
%/*      get all variables                               */
%/*------------------------------------------------------*/
%:- public get_variables_sweep/2;
%:- mode get_variables_sweep(?,-);
get_variables_sweep(Term,Vout) :- !,
        get_variables(Term,Vmed,[]),!,
        sweep_list(weak,Vmed,Vout);

%:- public get_variables/2;
%:- mode get_variables(?,-);
get_variables(Term,V) :- !,
        get_variables(Term,V,[]);

%:- mode get_variables(?,?,?);
get_variables(Vone,[Vone|Vt],Vt) :-
        is_var(Vone),!;
get_variables([_|Arg],Vh,Vt) :- !,
        get_variables_list(Arg,Vh,Vt);

%:- mode get_variables_list(+,?,?);
get_variables_list([],V,V) :- !;
get_variables_list([One|Rem],Vh,Vt) :- !,
        get_variables(One,Vh,Vm),!,
        get_variables_list(Rem,Vm,Vt);

%/*------------------------------------------------------*/
%/*      other data type conversion                      */
%/*------------------------------------------------------*/

%-------< list to atom >----------------------------------------------

%:- public list_to_atom/2;
%:- mode list_to_atom(+,-);
list_to_atom([26],'end_of_file') :- !;
list_to_atom(List,Name) :- !,
        name(Name,List);

%-------< list to dlist >---------------------------------------------

%:- public list_to_dlist/3;
%:- mode list_to_dlist(+,?,?);
list_to_dlist([],X,X) :- !;
list_to_dlist([C|Rem],[C|H],T) :- !,
        list_to_dlist(Rem,H,T);

%-------< list from dlist >-------------------------------------------

%:- public list_from_dlist/3;
%:- mode list_from_dlist(?,?,?);
list_from_dlist([],H,T) :-
        H==T,!;
list_from_dlist([C|Rem],[C|H],T) :- !,
        list_from_dlist(Rem,H,T);

%%%-------< change tail valuable of dlist >-----------------------------
%%
%%%:- public chg_dlist/4;
%%%:- mode chg_dlist(?,?,?,?);
%%chg_dlist(Vh,Vt,NewVt,NewVt) :-
%%      Vh==Vt,!;
%%chg_dlist([One|Vh],Vt,[One|VVh],VVt) :- !,
%%      chg_dlist(Vh,Vt,VVh,VVt);
%%
%-------< lower and upper >-------------------------------------------

%:- public lower_and_upper_string/2;
%:- mode lower_and_upper_string(?,?);
lower_and_upper_string([],[]) :- !;
lower_and_upper_string([Low|LowRem],[Upp|UppRem]) :- !,
        lower_and_upper(Low,Upp),!,
        lower_and_upper_string(LowRem,UppRem);

%:- public lower_and_upper/2;
%:- mode lower_and_upper(?,?);
lower_and_upper(97,65) :- !;
lower_and_upper(98,66) :- !;
lower_and_upper(99,67) :- !;
lower_and_upper(100,68) :- !;
lower_and_upper(101,69) :- !;
lower_and_upper(102,70) :- !;
lower_and_upper(103,71) :- !;
lower_and_upper(104,72) :- !;
lower_and_upper(105,73) :- !;
lower_and_upper(106,74) :- !;
lower_and_upper(107,75) :- !;
lower_and_upper(108,76) :- !;
lower_and_upper(109,77) :- !;
lower_and_upper(110,78) :- !;
lower_and_upper(111,79) :- !;
lower_and_upper(112,80) :- !;
lower_and_upper(113,81) :- !;
lower_and_upper(114,82) :- !;
lower_and_upper(115,83) :- !;
lower_and_upper(116,84) :- !;
lower_and_upper(117,85) :- !;
lower_and_upper(118,86) :- !;
lower_and_upper(119,87) :- !;
lower_and_upper(120,88) :- !;
lower_and_upper(121,89) :- !;
lower_and_upper(122,90) :- !;
lower_and_upper(X,X) :- !;

%/*------------------------------------------------------*/
%/*      do unify with occur check                       */
%/*------------------------------------------------------*/
%:- public unify/2;
%:- mode unify(?,?);
unify_occ(X,Y) :-
        X == Y, !;
unify_occ(X,Y) :-
        var(X),!,
        occur_check(Y,X),!,
        X=Y;
unify_occ(X,Y) :-
        var(Y),!,
        occur_check(X,Y),!,
        X=Y;
unify_occ([Op|Xarg],[Op|Yarg]) :- !,
        unify_list(Xarg,Yarg);

%:- mode unify_list(+,+);
unify_list([],[]) :- !;
unify_list([X|Xrem],[Y|Yrem]) :- !,
        unify_occ(X,Y),!,
        unify_list(Xrem,Yrem);

%:- mode occur_check(?,-);
occur_check(X,Y) :-
        X==Y,!,
        fail;
occur_check(X,_) :-
        var(X),!;
occur_check([_|Arg],Y) :- !,
        occur_check_list(Arg,Y);

%:- mode occur_check_list(+,-);
occur_check_list([],_) :- !;
occur_check_list([X|Rem],Y) :- !,
        occur_check(X,Y),!,
        occur_check_list(Rem,Y);

%/*------------------------------------------------------*/
%/*      D-list utility                                  */
%/*------------------------------------------------------*/

%-------< dname >-----------------------------------------------------

%:- public dname/3;
%:- mode dname(?,?,?);
dname(Name,Dh,Dt) :-
        atomic(Name),!,
        name(Name,List),!,
        list_to_dlist(List,Dh,Dt);
dname(Atom,Dh,Dt) :-
        list_from_dlist(List,Dh,Dt),!,
        list_to_atom(List,Atom);

%/*------------------------------------------------------*/
%/*      list utility                                    */
%/*------------------------------------------------------*/

%-------< member of >-------------------------------------------------

%:- public member_of_list/3;
%:- mode member_of_list(+,?,+);
member_of_list(strong,X,[X|_]) :- !;
member_of_list(weak,X,[Y|_]) :-
        X==Y,!;
member_of_list(Mode,X,[_|Rem]) :- !,
        member_of_list(Mode,X,Rem);

%-------< in set >----------------------------------------------------

%:- public compareSet/3;
%:- mode compareSet(-,+,+);
compareSet(=,L,R) :-
        L==R,!;
compareSet(<,L,R) :-
        inSet(L,R),!;
compareSet(>,L,R) :-
        inSet(R,L),!;
compareSet(#,_,_) :- !;

%:- mode inSet(+,+);
inSet([],_) :- !;
inSet([L|Lrem],[R|Rrem]) :- !,
        inSet(Rrem,R,Lrem,L);

%:- mode inSet(+,?,+,?);
inSet(Rrem,R,Lrem,L) :-
        R==L,!,
        inSet(Lrem,Rrem);
inSet([R|Rrem],_,Lrem,L) :- !,
        inSet(Rrem,R,Lrem,L);

%-------< delete list >-----------------------------------------------

%:- public delete_list/4;
%:- mode delete_list(+,+,+,-);
delete_list(_,_,[],[]) :- !;
delete_list(strong,V,[V|X],Y) :- !,
        delete_list(strong,V,X,Y);
delete_list(weak,V,[W|X],Y) :-
        V == W,!,
        delete_list(weak,V,X,Y);
delete_list(Mode,V,[W|X],[W|Y]) :- !,
        delete_list(Mode,V,X,Y);

%-------< delete one list >-------------------------------------------

%:- public delete_one_list/4;
%:- mode delete_one_list(+,+,+,-);
delete_one_list(strong,V,[V|Rem],Rem) :- !;
delete_one_list(weak,V,[W|Rem],Rem) :-
        V == W,!;
delete_one_list(Mode,V,[W|Rem],[W|NewRem]) :- !,
        delete_one_list(Mode,V,Rem,NewRem);

%-------< can delete list >-------------------------------------------

%:- public can_delete_list/4;
%:- mode can_delete_list(+,+,+,-);
can_delete_list(Mode,One,Lin,Lout) :- !,
        delete_one_list(Mode,One,Lin,Lmed),!,
        delete_list(Mode,One,Lmed,Lout);

%-------< sweep list >------------------------------------------------

%:- public sweep_list/3;
%:- mode sweep_list(+,+,-);
sweep_list(weak,L,R) :- !,
        sort(L,R);
sweep_list(_,L,R) :- !,
        sweep_list_(L,[],R);

%:- mode sweep_list_(+,+,-);
sweep_list_([One|Rem],R0,R) :- !,
        sweep_list_partition(Rem,One,L1,L2),
        sweep_list_(L2,R0,R1),
        sweep_list_(L1,[One|R1],R);
sweep_list_([],R,R) :- !;

%:- mode sweep_list_partition(+,+,-,-);
sweep_list_partition([],_,[],[]) :- !;
sweep_list_partition([Y|L],Y,L1,L2) :- !,
        sweep_list_partition(L,Y,L1,L2);
sweep_list_partition([X|L],Y,L1,[X|L2]) :-
        X>Y,!,
        sweep_list_partition(L,Y,L1,L2);
sweep_list_partition([X|L],Y,[X|L1],L2) :- !,
        sweep_list_partition(L,Y,L1,L2);

%-------< union list >------------------------------------------------

%:- public union_list/4;
%:- mode union_list(+,+,+,-);
union_list(Mode,L,R,OUT) :- !,
        app_list(L,R,Med),
        sweep_list(Mode,Med,OUT);

%-------< intersect list >--------------------------------------------

%:- public intersect_list/4;
%:- mode intersect_list(+,+,+,-);
intersect_list(Mode,L,R,I) :- !,
        intersect_list(Mode,L,R,I,_,_);

%:- public intersect_list/6;
%:- mode intersect_list(+,+,+,-,-,-);
intersect_list(Mode,L,R,I,Lrem,Rrem) :- !,
        sweep_list(Mode,L,Lsweep),
        sweep_list(Mode,R,Rsweep),!,
        intersect_list_(Lsweep,Rsweep,Mode,I,Lrem,Rrem);

%:- mode intersect_list_(+,+,+,-,-,-);
intersect_list_([],Rrem,_,[],[],Rrem) :- !;
intersect_list_(Lrem,[],_,[],Lrem,[]) :- !;
intersect_list_([L|Lrem],[R|Rrem],Mode,I,Lout,Rout) :- !,
        intersect_list_one(Mode,L,R,Lrem,Rrem,I,Lout,Rout);

%:- mode intersect_list_one(+,?,?,+,+,-,-,-);
intersect_list_one(strong,T,T,Lrem,Rrem,[T|I],Lout,Rout) :- !,
        intersect_list_(Lrem,Rrem,strong,I,Lout,Rout);
intersect_list_one(weak,L,R,Lrem,Rrem,[L|I],Lout,Rout) :-
        L==R,!,
        intersect_list_(Lrem,Rrem,weak,I,Lout,Rout);
intersect_list_one(Mode,L,R,Lrem,Rrem,I,[L|Lout],Rout) :-
        L<R,!,
        intersect_list_(Lrem,[R|Rrem],Mode,I,Lout,Rout);
intersect_list_one(Mode,L,R,Lrem,Rrem,I,Lout,[R|Rout]) :- !,
        intersect_list_([L|Lrem],Rrem,Mode,I,Lout,Rout);

%-------< append list >-----------------------------------------------

%:- public app_list/3;
%:- mode app_list(+,+,-);
app_list([X],[Y],[X,Y]) :- !;
app_list([],X,X) :- !;
app_list([X|Rem],Y,[X|Z]) :- !,
        app_list(Rem,Y,Z);

%-------< reverse list >----------------------------------------------

%:- public rev_list/2;
%:- mode rev_list(+,-);
rev_list(X,Y) :- !,
        rev_list(X,[],Y);

%:- mode rev_list(+,+,-);
rev_list([],X,X) :- !;
rev_list([X|Rem],Y,Z) :- !,
        rev_list(Rem,[X|Y],Z);

%-------< get one list >----------------------------------------------

%%%:- public get_one_list/2;
%%%:- mode get_one_list(+,?);
get_one_list(List,One) :- !,
      get_one_list(List,One,_);

%%%:- public get_one_list/3;
%%%:- mode get_one_list(+,?,-);
get_one_list([X],X,[]) :- !;  % for speed up.
get_one_list([X|Rem],X,Rem);
get_one_list([X|Rem],Y,[X|NewRem]) :- !,
      get_one_list(Rem,Y,NewRem);

%/*------------------------------------------------------*/
%/*      string pattern match                            */
%/*------------------------------------------------------*/

%-------< front UL match >--------------------------------------------

%%%:- public not_front_ulmatch/2;
%%%:- mode not_front_ulmatch(?,?);
%%not_front_ulmatch(L,R) :- !,
%%      ( front_ulmatch(L,R,_),!,fail;true),!;

%:- public front_ulmatch/2;
%:- mode front_ulmatch(?,?);
front_ulmatch(A1,B1) :- !,
        front_ulmatch(A1,B1,_);

%:- public front_ulmatch/3;
%:- mode front_ulmatch(?,?,-);
front_ulmatch(X,X,'') :- !;
front_ulmatch(L,R,C) :- !,
        ulmatch_name(L,Llis),
        ulmatch_name(R,Rlis),
        front_strcmp(Llis,Rlis,Clis),!,
        name(C,Clis);

%:- mode front_strcmp(+,+,-);
front_strcmp([],Rem,Rem) :- !;
front_strcmp([C|Lrem],[C|Rrem],Out) :- !,
        front_strcmp(Lrem,Rrem,Out);
front_strcmp([C1|Lrem],[C2|Rrem],Out) :- !,
        lower_and_upper(C1,C),
        lower_and_upper(C2,C),!,
        front_strcmp(Lrem,Rrem,Out);

%-------< middle UL match >-------------------------------------------

%:- public middle_ulmatch/2;
%:- mode middle_ulmatch(?,?);
middle_ulmatch(X,X) :- !;
middle_ulmatch(L,R) :- !,
        ulmatch_name(L,Llis),
        ulmatch_name(R,Rlis),!,
        middle_strcmp(Llis,Rlis);

%:- mode middle_strcmp(+,+);
middle_strcmp([],[]) :- !;
middle_strcmp([42],_) :- !;     % name(*,[42]).
middle_strcmp([42|Lrem],R) :-
        middle_strcmp(Lrem,R),!;
middle_strcmp([42|Lrem],[_|Rrem]) :- !,
        middle_strcmp([42|Lrem],Rrem);
middle_strcmp([C|Lrem],[C|Rrem]) :- !,
        middle_strcmp(Lrem,Rrem);
middle_strcmp([C1|Lrem],[C2|Rrem]) :- !,
        lower_and_upper(C1,C),
        lower_and_upper(C2,C),!,
        middle_strcmp(Lrem,Rrem);

%-------< to string >-------------------------------------------------

%:- mode ulmatch_name(?,-);
ulmatch_name(V,_) :-
        var(V),!,
        fail;
ulmatch_name([],[]) :- !;
ulmatch_name([H|T],[H|T]) :- !;
ulmatch_name(A,Lis):- !,
        atomic(A),!,
        name(A,Lis);

%/*------------------------------------------------------*/
%/*      data type check                                 */
%/*------------------------------------------------------*/

%-------< is list >---------------------------------------------------

%:- public is_list/1;
is_list(X) :- var(X),!,fail;
is_list([_|_]) :- !;

%-------< is var >----------------------------------------------------

%:- public is_var/1;
%:- mode is_var(?);
is_var(V) :-
        var(V),!;
%%is_var('$VAR'(_)) :- !;
is_var('$SKM'(_,_)) :- !;

%-------< is string >-------------------------------------------------

%:- public is_string/1;
%:- mode is_string(+);
is_string(V) :- is_var(V),!,fail;
is_string([H|T]) :- !,
        is_string_loop([H|T]);

%:- mode is_string_loop(+);
is_string_loop([]) :- !;
is_string_loop([C|Rem]) :- !,
        integer(C),!,
        is_string_loop(Rem);

%/*------------------------------------------------------*/
%/*      counter                                         */
%/*------------------------------------------------------*/
%:- public counter/2,counter/3, counter/4;
%:- mode counter(+,+);
counter(init,Fun) :- !,
        retract_all(``('{CNT}'(Fun,_)));
counter(up,Fun) :- !,
        counter(add,Fun,1,_);
counter(end,Fun) :- !,
        retract_all(``('{CNT}'(Fun,_)));

%:- mode counter(+,+,-);
counter(refer,Fun,Num) :- !,
        ( '{CNT}'(Fun,Num) ; Num=0 ),!;
counter(set,Fun,Num) :- !,
        counter(init,Fun),!,
        asserta('{CNT}'(Fun,Num));
counter(end,Fun,Num) :- !,
        ( retract('{CNT}'(Fun,Num)),
          retract_all(``('{CNT}'(Fun,_)))
        ; Num=0
        ),!;

%:- mode counter(+,+,+,?);
counter(add,Fun,Num,N) :- !,
        ( retract('{CNT}'(Fun,N0)),
          N is N0 + Num
        ; N = Num
        ),!,
        asserta('{CNT}'(Fun,N));

%/*------------------------------------------------------*/
%/*      trace on/off                                    */
%/*------------------------------------------------------*/
%:- public trace_on/1, traceoff/0;
trace_on([]) :-
        '{DFT}'(trace(Mode)),!,
        trace_on([Mode]);
trace_on([P]) :-
        integer(P), 0=<P, P=<9,!,
        ( '{FLG}trace'(P)
        ; abolish('{FLG}trace',1),
          asserta('{FLG}trace'(P))
        ),!;
trace_on(_) :- !,
        printf([{bell},'...trace priority error.',{nl}]);

traceoff :- !,
        retract_all(``('{FLG}trace'(_)));

%-------< trace/1 >---------------------------------------------------

%:- public trace/1;
%:- mode trace(+);
trace(X) :-
        '{FLG}trace'(_),!,
        printf(X),printf({ttyflush});
trace(_) :- !;

%-------< trace/2 >---------------------------------------------------

%:- public trace/2;
%:- mode trace(+,+);
trace(P,X) :-
        is_trace(P),!,
        ( P=<5,!,
           printf(X),printf({ttyflush})
        ; X=[{continue}|T],!,
          printf(T),printf({ttyflush})
        ; printf(['DBG(',P,')>> '|X]),printf({ttyflush})
        ),!;
trace(_,_) :- !;

%:- public is_trace/1;
%:- mode is_trace(+);
is_trace(P) :- !,
        '{FLG}trace'(F),!,
        P=<F;

%-------< notrace/1 >-------------------------------------------------

%:- public notrace/1;
%:- mode notrace(+);
notrace(_) :-
        '{FLG}trace'(_),!;
notrace(X) :- !,
        printf(X),printf({ttyflush});

%-------< notrace/2 >-------------------------------------------------

%:- public notrace/2;
%:- mode notrace(+,+);
notrace(P,X) :-
        not_flag_trace(P),!,
        printf(X);
notrace(_,_) :- !;

%:- mode not_flag_trace(+);
not_flag_trace(P) :-
        '{FLG}trace'(PP),!,
        P>PP;
not_flag_trace(_) :- !;

%/*------------------------------------------------------*/
%/*      others                                          */
%/*------------------------------------------------------*/

%-------< retract all >-----------------------------------------------

%:- public retract_all/1;
%:- mode retract_all(+);
retract_all(Obj) :-
        retract(Obj),
        fail;
retract_all(_) :- !;

%-------< bagof never fail >------------------------------------------

%:- public bagoft/3;
%:- mode bagoft(?,+,?);
bagoft(A,B,C) :-
        bagof(A,B,C);
bagoft(_,_,[]) :- !;

%-------< operator format >-------------------------------------------

%:- public operator_prefix/1;
operator_prefix(fx);
operator_prefix(fy);

%:- public operator_infix/1;
operator_infix(xfx);
operator_infix(xfy);
operator_infix(yfx);

%:- public operator_postfix/1;
operator_postfix(xf);
operator_postfix(yf);

%/********************************************************/
%/*      not                                             */
%/*********************************************************/
%:- public not_seeing/1;
%:- mode not_seeing(?);
not_seeing(File) :- !,
        ( seeing(File),!,fail ; true ),!;

%:- public not_unify/2;
%:- mode not_unify(?,?);
not_unify(L,R) :- !,
        ( unify_occ(L,R),!,fail ; true ),!;

%:- public not_not_unify/2;
%:- mode not_not_unify(?,?);
not_not_unify(L,R) :- !,
        ( not_unify(L,R),!,fail ; true ),!;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%       interface                                               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%% metis_assert
'{DB}title'(A) :- !, interface('{DB}title'(A)); 
'{DB-op}inf'(A,B,C,D) :- !, interface('{DB-op}inf'(A,B,C,D));
'{DB-op}cons'(A) :- !, interface('{DB-op}cons'(A));
'{DB-op}less'(A,B) :- !, interface('{DB-op}less'(A,B));
'{DB-eq}###'(A,B,C,D,E,F,G,H,I,J) :- !, interface('{DB-eq}###'(A,B,C,D,E,F,G,H,I,J));
'{DB-eq}#/#'(A,B,C,D,E,F,G,H,I,J,K) :- !, interface('{DB-eq}#/#'(A,B,C,D,E,F,G,H,I,J,K));
'{CPC}current'(A) :- !, interface('{CPC}current'(A));
'{CPC}evaluated'(A) :- !, interface('{CPC}evaluated'(A));
'{DB-rl}>>>'(A,B,C,D,E,F) :- !, interface('{DB-rl}>>>'(A,B,C,D,E,F));
'{DB-rl}#>>'(A,B,C,D,E,F,G) :- !, interface('{DB-rl}#>>'(A,B,C,D,E,F,G));
'{DB-rl}##>'(A,B,C,D,E,F) :- !, interface('{DB-rl}##>'(A,B,C,D,E,F));
'{DB-rl}#<<'(A,B,C,D,E,F,G) :- !, interface('{DB-rl}#<<'(A,B,C,D,E,F,G));
'{DB-rl}##<'(A,B,C,D,E,F) :- !, interface('{DB-rl}##<'(A,B,C,D,E,F));
'{DB-rl}</>'(A,B,C,D,E,F,G) :- !, interface('{DB-rl}</>'(A,B,C,D,E,F,G));
'{CPC}>>>'(A,B,C,D,E) :- !, interface('{CPC}>>>'(A,B,C,D,E));
'{CPC}#>>'(A,B,C,D,E) :- !, interface('{CPC}#>>'(A,B,C,D,E));
'{CPC}##>'(A,B,C,D) :- !, interface('{CPC}##>'(A,B,C,D));
'{CPC}#<<'(A,B,C,D,E) :- !, interface('{CPC}#<<'(A,B,C,D,E));
'{CPC}##<'(A,B,C,D) :- !, interface('{CPC}##<'(A,B,C,D));
'{HIS}'(A) :- !, interface('{HIS}'(A));
%%%%% for save/restore
'{CNT}'(A,B) :- !, interface('{CNT}'(A,B));
'{CNT}id'(A,B) :- !, interface('{CNT}id'(A,B));
%%%%% flags
'{FLG}bell' :- !, interface('{FLG}bell');
'{FLG}trace'(A) :- !, interface('{FLG}trace'(A));
'{FLG}completion' :- !, interface('{FLG}completion');
'{FLG}monitor'(A,B) :- !, interface('{FLG}monitor'(A,B));
'{FLG}history' :- !, interface('{FLG}history');  % save delted data
'{FLG}comlog' :- !, interface('{FLG}comlog');  % make command log file
'{SYS}ttycopy' :- !, interface('{SYS}ttycopy');
'{FLG}log' :- !, interface('{FLG}log');  % make prolog.log
'{FLG}to_interactive' :- !, interface('{FLG}to_interactive');
'{DFT}monitor'(A,B) :- !, interface('{DFT}monitor'(A,B)); 
'{DFT}trace'(A) :- !, interface('{DFT}trace'(A)); 
'{DB-op}form'(A,B,C) :- !, interface('{DB-op}form'(A,B,C));
'{SYS}com_mode'(A) :- !, interface('{SYS}com_mode'(A));
'{SYS}version'(A) :- !, interface('{SYS}version'(A));
'{SYS}compiled'(A,B,C) :- !, interface('{SYS}compiled'(A,B,C));
'{SYS}jobno'(A,B) :- !, interface('{SYS}jobno'(A,B));
'{SYS}ttylength'(A) :- !, interface('{SYS}ttylength'(A));
'{SYS}ttylevel'(A) :- !, interface('{SYS}ttylevel'(A));
'{SYS}print'(A) :- !, interface('{SYS}print'(A));
'{SYS}ttytype'(A) :- !, interface('{SYS}ttytype'(A));
'{DFT}ttytype'(A) :- !, interface('{DFT}ttytype'(A));
'{CPC}terminate' :- !, interface('{CPC}terminate');
'{SYS}command_file'(A,B) :- !, interface('{SYS}command_file'(A,B));
'{SYS}compiled_date'(A,B,C) :- !, interface('{SYS}compiled_date'(A,B,C));
'{SYS}current_file'(A,B) :- !, interface('{SYS}current_file'(A,B));
'{SYS}executable_file'(A) :- !, interface('{SYS}executable_file'(A));
'{DFT}'(A) :- !, interface('{DFT}'(A));
'{CPC}induction'(A) :- !, interface('{CPC}induction'(A));

%%%%%%% metis_command
command(A,B,C,D,E,F) :- interface(command(A,B,C,D,E,F) );
default_command(A,B) :- interface(default_command(A,B) );
cpc_mode_and_id(B,C) :- interface(cpc_mode_and_id(B,C) );

%%%%%%% metis_device
terminal_type_data(A,B,C,D,E):- interface( terminal_type_data(A,B,C,D,E));
terminal_level_data(A,B):- interface( terminal_level_data(A,B));
read(Prompt,Inp):- interface( read(Prompt,Inp));
read_file(A,Ext,Out):- interface( read_file(A,Ext,Out));
lininp(Prompt,Buff):- interface( lininp(Prompt,Buff));
lininp(Prompt,Buff,Trm):- interface( lininp(Prompt,Buff,Trm));
lininpTop(Prompt,Top):- interface( lininpTop(Prompt,Top));
lininpCase(Prompt,Cases,Num):- interface( lininpCase(Prompt,Cases,Num));
set_prompt(Atom):- interface( set_prompt(Atom));
printf(Item):-interface(printf(Item));
printf_nomore :- interface( printf_nomore);
set_terminal_type(A):- interface( set_terminal_type(A));
get_terminal_type(Type):- interface( get_terminal_type(Type));
get_terminal_level(Level):- interface( get_terminal_level(Level));
get_terminal_length(Size):- interface( get_terminal_length(Size));
get_terminal_range(Top,Bottom):- interface( get_terminal_range(Top,Bottom));
get_control_sequence(Type,Level,Ctrl,Char):- interface( get_control_sequence(Type,Level,Ctrl,Char));
can_file_open(Read,File):- interface( can_file_open(Read,File));
can_file_open(Flg,A,Key,Ext,File):- interface( can_file_open(Flg,A,Key,Ext,File));
file_open(Read,Key,File):- interface( file_open(Read,Key,File));
file_close(Read):- interface( file_close(Read));
is_end_of_file(End):- interface( is_end_of_file(End));
is_end_of_file(A,B,C,D):- interface( is_end_of_file(A,B,C,D));
create_tmpfile(Name,File):- interface( create_tmpfile(Name,File));
rename_tmpfile(Name,NewFile):- interface( rename_tmpfile(Name,NewFile));
delete_tmpfile(Name):- interface( delete_tmpfile(Name));
clock(T):- interface( clock(T));

%%%%%%% metis_main
%%metis => interface(metis_metis);
%%c => interface(c);
%%continue => interface(continue);
command_select(A,B,C,D,E) :- interface(command_select(A,B,C,D,E) );
portray(A) :- interface(portray(A) );
orient(A,B,C) :- interface(orient(A,B,C) );
%%i => interface(i);
%%interactive => interface(interactive);
less(A,B) :- interface(less(A,B) );
can_less(A,B,C,D,E,F) :- interface(can_less(A,B,C,D,E,F) );
reduce_one(A,B,C) :- interface(reduce_one(A,B,C) );
reduce_ass :- interface(reduce_ass );
refer(A,B,C,D) :- interface(refer(A,B,C,D) );
refer_match(A,B,C,D) :- interface(refer_match(A,B,C,D) );
set(A) :- interface(set(A) );
ref(A) :- interface(ref(A) );
new_port(A,B) :- interface(new_port(A,B) );

%%%%%%% metis_buildin
abolish(Clause,Arity):- interface(abolish(Clause,Arity));
assert(Clause):- interface(assert(Clause));
assert(Clause,Ref):- interface(assert(Clause,Ref));
asserta(Clause):- interface(asserta(Clause));             
asserta(Clause,Ref):- interface(asserta(Clause,Ref));
assertz(Clause):- interface(assertz(Clause));
assertz(Clause,Ref):- interface(assertz(Clause,Ref));
bagof(Data,Pred,List):- interface(bagof(Data,Pred,List));
call(Clause):- interface(call(Clause));
notcall(Clause):- interface(notcall(Clause));
clause(Hed,Body,Ref):- interface(clause(Hed,Body,Ref));
clause(Hed,Body):- interface(clause(Hed,Body));
compare(OP,L,R):- interface(compare(OP,L,R));
erase(Ref):- interface(erase(Ref));
trimcore :- true;
terminal_open:- interface(terminal_open);
terminal_close:- interface(terminal_close);
get0(X):- interface(get0(X));   
length(List,L):- interface(length(List,L));
name(X,List):- interface(name(X,List));
numbervars(Term,Cin,Cout):- interface(numbervars(Term,Cin,Cout));
nl:- interface(nl);
op(P,F,O):- interface(op(P,F,O));
print(Format,Arg_list):- interface(print(Format,Arg_list));
put(X):- interface(put(X));
read(X):- interface(read(X));
retract(Clause):- interface(retract(Clause));
rename(Old_file,New_file):- interface(rename(Old_file,New_file));
see(Fanam):- interface(see(Fanam));
seeing(Fnam):- interface(seeing(Fnam));
seen:- interface(seen);
sort(X,List):- interface(sort(X,List));
tell(Fanam):- interface(tell(Fanam));
told:- interface(told);
telling(Fnam):- interface(telling(Fnam));
write(X):- interface(write(X));
write(X,Y,Z):- interface(write(X,Y,Z));
'=..'(Term,List):- interface('=..'(Term,List));
functor(Term,A,B):- interface(functor(Term,A,B));
tab(A):- interface(tab(A));
prompt(A,B):- interface(prompt(A,B)); 
print(A):- interface(print(A));
ttyflush:- interface(ttyflush);
log:- interface(log);
nolog:- interface(nolog);
plsys(A):- interface(plsys(A));
nofileerrors:- interface(nofileerrors);
writeq(A):- interface(writeq(A));
writeq(A,B,C):- interface(writeq(A,B,C));
nonvar(A):- interface(nonvar(A));
var(A):- interface(var(A));
statistics(A,B) :- interface(statistics(A,B));
compile(A)  :- true;
reconsult(A)  :- true;
incore(A)  :- true;
halt :- true;
abort :- true;

end.