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


/******** DONE: top-level checker command ********/
done :-
        \+ command_arg(to_do, _),                               /* CFR024 */
        nl,
        max_conc_no(MAX),
        done_range(1,MAX),
        fail.
done :-
        command_arg(expression, CONCS),
        (
           CONCS=c#N,
           done(N)
        ;
           CONCS=c#N-M,
           done_range(N,M)
        ),
        fail.
done :-
        all_done,
        fail.
done :-
   logfact(proved, _),
   !,
   retractall(do_not_issue_failure_message).
done :-
   retract(do_not_issue_failure_message),
   !,
   retractall(do_not_issue_failure_message).
done :-
   write('*** Cannot eliminate any conclusions at present'),
   nl,
   fail.


done(N) :-
   conc(N,X),
   infer(X),
   write('*** PROVED C'),
   print(N),
   write(': '),
   print(X),
   assertz(logfact(proved, conc(N,X))),
   retract(conc(N,X)),
   case_pointer(CP),
   (
      on_case(CP,CN,_),
      write(' FOR CASE '),
      print(CN)
   ;
      true
   ),
   !,
   nl,                                                          /* CFR024 */
   (                                                            /* CFR024 */
      \+ conc(_, _),                                            /* CFR024 */
      auto_done(on),                                            /* CFR024 */
      all_done                                                  /* CFR024 */
   ;                                                            /* CFR024 */
      true                                                      /* CFR024 */
   ),                                                           /* CFR024 */
   !.                                                           /* CFR024 */



/*** ALL_DONE - see if all conclusions at present depth done & act if so ***/
all_done :-
   \+ conc(_,_),
   case_pointer(CP),
   (
      CP=0,                                                     /* CFR024 */
      logfact(proved, vc(_)),                                   /* CFR024 */
      !                                                         /* CFR024 */
   ;                                                            /* CFR024 */
      CP=0,
      !,
      write('*** VC PROVED -- Well done!'),
      nl,
      assertz(logfact(proved, all)),
      current_vc(VCNAME, _),
      assertz(logfact(proved, vc(VCNAME))),
      update_vcs_to_prove,
      nl,                                                       /* CFR025 */
      assertz(time_for_new_vc)                                  /* CFR025 */
   ;
      CP>0,
      (
         on_case(CP, CASE, _),
         maybe_add(proved_for_case(CP, CASE)),
         fail
      ;
         case(CP, N, F),
         \+ proved_for_case(CP, N),
         !,
         maybe_add(do_not_issue_failure_message),
         case(N)
      ;
         subgoal_formula(CP, F, N, METHOD),
         write('*** PROVED '),
         print(F),
         write(' BY '),
         print(METHOD),
         nl,
         CP1 is CP-1,
         retractall(case_pointer(_)),
         asserta(case_pointer(CP1)),
         case_restore(CP),                      /* ??? */
         assertz(logfact(exitframe, CP)),
         write('[Exiting depth '),                              /* CFR024 */
         print(CP),                                             /* CFR024 */
         write(' proof frame]'),                                /* CFR024 */
         nl,                                                    /* CFR024 */
         retractall(proved_for_case(CP,_)),
         retractall(case(CP,_,_)),
         retractall(subgoal_formula(CP,_,_,_)),
         clear_up_could_facts,
         add_new_hyp(F,1),
         (
            integer(N),
            !,
            (
               auto_done(on),
               !,
               done
            ;
               done(N)
            )
         ;
            maybe_add(do_not_issue_failure_message)
         )
      )
   ), !.


done_range(N,N) :-
        done(N),
        !.
done_range(N,M) :-
        N<M,
        ( done(N) ; true ),
        !,
        N1 is N+1,
        done_range(N1,M),
        !.


update_vcs_to_prove :-
        current_vc(VCNAME, VCNUM),
        retractall(is_vc(VCNAME)),
        retractall(vc(VCNAME,_)),
        vcs_to_prove(OLDVCLIST),
        delete_number(VCNUM, OLDVCLIST, NEWVCLIST),
        retractall(vcs_to_prove(_)),
        asserta(vcs_to_prove(NEWVCLIST)),
        update_vcs_proved(VCNUM),
        !.


delete_number(N, [[N]|REST], REST) :- !.
delete_number(N, [LIST|REST], NEWLIST) :-
        append(FRONT, [N|BACK], LIST),
        (
           FRONT=[],
           !,
           NEWLIST=[BACK|REST]
        ;
           BACK=[],
           !,
           NEWLIST=[FRONT|REST]
        ;
           NEWLIST=[FRONT,BACK|REST]
        ),
        !.
delete_number(N, [LIST|REST], [LIST|NEWREST]) :-
        (\+ is_in(N, LIST)),
        delete_number(N, REST, NEWREST),
        !.


update_vcs_proved(NUM) :-
        \+ vcs_proved_this_session(_),
        !,
        asserta(vcs_proved_this_session([[NUM]])),
        !.
update_vcs_proved(NUM) :-
        vcs_proved_this_session(LIST),
        !,
        insert_in_vc_list(NUM, LIST, NEW_LIST),
        !,
        asserta(vcs_proved_this_session(NEW_LIST)),
        retract(vcs_proved_this_session(LIST)),
        !.


insert_in_vc_list(N, [ListNm1, [Np1|List] | REST], [NewList | REST]) :-
        Np1 is N+1,
        Nm1 is N-1,
        last(ListNm1, Nm1),
        append(ListNm1, [N,Np1|List], NewList),
        !.
insert_in_vc_list(N, [[Np1|List] | REST], [[N,Np1|List] | REST]) :-
        Np1 is N+1,
        !.
insert_in_vc_list(N, [ListNm1 | REST], [ListN | REST]) :-
        Nm1 is N-1,
        last(ListNm1, Nm1),
        append(ListNm1, [N], ListN),
        !.
insert_in_vc_list(N, [List | REST], [List | NEW_REST]) :-
        last(List, HI),
        HI < N,
        insert_in_vc_list(N, REST, NEW_REST), !.
insert_in_vc_list(N, LIST, [[N]|LIST]) :- !.
%###############################################################################
%END-OF-FILE
