C:/Users/Dennis/src/lang/Life_start/Life/life-1.02/source/login.c

Go to the documentation of this file.
00001 /* Copyright 1991 Digital Equipment Corporation.
00002  ** All Rights Reserved.
00003  *****************************************************************/
00004 /*      $Id: login.c,v 1.4 1995/01/14 00:25:33 duchier Exp $     */
00005 
00006 #ifndef lint
00007 static char vcid[] = "$Id: login.c,v 1.4 1995/01/14 00:25:33 duchier Exp $";
00008 #endif /* lint */
00009 
00010 #include "extern.h"
00011 #include "login.h"
00012 #include "trees.h"
00013 #include "copy.h"
00014 #include "parser.h"
00015 #include "token.h"
00016 #include "print.h"
00017 #ifndef OS2_PORT
00018 #include "built_ins.h"
00019 #else
00020 #include "built_in.h"
00021 #endif
00022 #include "types.h"
00023 #include "lefun.h"
00024 #include "memory.h"
00025 #include "error.h"
00026 #include "xpred.h"
00027 #include "modules.h" /*  RM: Jan 27 1993  */
00028 #ifndef OS2_PORT
00029 #include "interrupt.h"
00030 #else
00031 #include "interrup.h"
00032 #endif
00033 
00034 int global_unify_attr();   /*  RM: Feb  9 1993  */
00035 int global_unify();        /*  RM: Feb 11 1993  */
00036 
00037 /* Clean trail toggle */
00038 /* Removed temporarily because of comb bug 1.6 */
00039 #define CLEAN_TRAIL
00040 
00041 /* Statistics on trail cleaning */
00042 long clean_iter=0;
00043 long clean_succ=0;
00044 
00045 ptr_stack undo_stack;
00046 ptr_choice_point choice_stack;
00047 /* ptr_choice_point prompt_choice_stack; 12.7 */
00048 #ifdef TS
00049 /* Should never wrap (32 bit is enough) 9.6 */
00050 /* Rate of incrementing: One per choice point */
00051 unsigned long global_time_stamp=INIT_TIME_STAMP; /* 9.6 */
00052 #endif
00053 
00054 ptr_goal goal_stack,aim;
00055 
00056 
00057 long goal_count;
00058 #ifndef OS2_PORT
00059 struct tms start_time,end_time;
00060 #else
00061 float start_time,end_time;
00062 #endif
00063 long ignore_eff; /* 'Ignore efficiency' flag */
00064 
00065 long assert_first;
00066 long assert_ok;
00067 
00068 long main_loop_ok;
00069 long xeventdelay;
00070 long xcount;
00071 
00072 long more_u_attr; /* TRUE if U has attributes V doesn't */
00073 long more_v_attr; /* Vice-versa */
00074 
00075 long u_func,v_func;  /* TRUE if U or V is a curried function */
00076 long new_stat;
00077 
00078 char prompt_buffer[PROMPT_BUFFER];
00079 
00080 
00081 /******************************************************************************
00082   
00083   What follows are the functions which assert facts in their correct places:
00084   function definitions, rule definitions or type definitions.
00085   
00086   ****************************************************************************/
00087 
00088 
00089 
00090 /******** GET_TWO_ARGS(attr_list,arg1,arg2)
00091   Get the arguments labelled '1' and '2' as quickly as possible from the
00092   binary tree ATTR_LIST, place them in ARG1 and ARG2. This routine nearly
00093   always makes a direct hit.
00094   */
00095 void get_two_args(t,a,b)
00096      ptr_node t;
00097      ptr_psi_term *a;
00098      ptr_psi_term *b;
00099 {
00100   ptr_node n;
00101   
00102   *a=NULL;
00103   *b=NULL;
00104   if (t) {
00105     if (t->key==one) {
00106       *a=(ptr_psi_term )t->data;
00107       n=t->right;
00108       if (n) 
00109         if (n->key==two)
00110           *b=(ptr_psi_term )n->data;
00111         else {
00112           n=find(featcmp,two,t);
00113           if(n==NULL)
00114             *b=NULL;
00115           else
00116             *b=(ptr_psi_term )n->data;
00117         }
00118       else
00119         *b=NULL;
00120     }
00121     else {
00122       n=find(featcmp,one,t);
00123       if (n==NULL)
00124         *a=NULL;
00125       else
00126         *a=(ptr_psi_term )n->data;
00127       n=find(featcmp,two,t);
00128       if (n==NULL)
00129         *b=NULL;
00130       else
00131         *b=(ptr_psi_term )n->data;
00132     }
00133   }
00134 }
00135 
00136 
00137 
00138 
00139 /******** GET_ONE_ARG(attr_list,arg1)
00140   Get the argument labelled '1' as quickly as possible from the
00141   binary tree ATTR_LIST, place it in ARG1. This routine nearly
00142   always makes a direct hit.
00143   */
00144 void get_one_arg(t,a)
00145      ptr_node t;
00146      ptr_psi_term *a;
00147 {
00148   ptr_node n;
00149   
00150   *a=NULL;
00151   if (t) {
00152     if (t->key==one) {
00153       *a=(ptr_psi_term)t->data;
00154     }
00155     else {
00156       n=find(featcmp,one,t);
00157       if (n==NULL)
00158         *a=NULL;
00159       else
00160         *a=(ptr_psi_term)n->data;
00161     }
00162   }
00163 }
00164 
00165 
00166 
00167 
00168 /******** GET_ONE_ARG_ADDR(attr_list,arg1addr)
00169   Get address of slot in the attr_list that points to the argument labelled
00170   '1' as quickly as possible from the binary tree ATTR_LIST.
00171   This routine nearly always makes a direct hit.
00172   */
00173 void get_one_arg_addr(t,a)
00174      ptr_node t;
00175      ptr_psi_term **a;
00176 {
00177   ptr_node n;
00178   ptr_psi_term *b;
00179   
00180   *a=NULL;
00181   if (t) {
00182     if (t->key==one)
00183       *a= (ptr_psi_term *)(&t->data);
00184     else {
00185       n=find(featcmp,one,t);
00186       if (n==NULL)
00187         *a=NULL;
00188       else
00189         *a= (ptr_psi_term *)(&n->data);
00190     }
00191   }
00192 }
00193 
00194 
00195 
00196 
00197 /******** ADD_RULE(head,body,typ)
00198   The TYP argument is either 'predicate', 'function', or 'type'.
00199   For predicates or functions, insert the clause 'HEAD :- BODY' or the rule
00200   'HEAD -> BODY' into the definition of HEAD.
00201   For types, insert HEAD as a term of type attributes and BODY as a type
00202   constraint.
00203   The global flag ASSERT_FIRST indicates whether to do the insertion at the
00204   head or the tail of the existing list.
00205   */
00206 void add_rule(head,body,typ)
00207      ptr_psi_term head;
00208      ptr_psi_term body;
00209      def_type typ;
00210 {
00211   psi_term succ;
00212   ptr_psi_term head2;
00213   ptr_definition def;
00214   ptr_pair_list p, *p2;
00215   
00216   if (!body && typ==predicate) {
00217     succ.type=succeed;
00218     succ.value=NULL;
00219     succ.coref=NULL;
00220     succ.resid=NULL;
00221     succ.attr_list=NULL;
00222     body= ≻
00223   }
00224   
00225   deref_ptr(head);
00226   head2=head;
00227   
00228   /* assert(head->resid==NULL); 10.8 */
00229   /* assert(body->resid==NULL); 10.8 */
00230   
00231   if (redefine(head)) {
00232     
00233     def=head->type;
00234     
00235     if (def->type==undef || def->type==typ)
00236       
00237       /*  RM: Jan 27 1993  */
00238       if(TRUE
00239          /* def->type==undef ||
00240             def->keyword->module==current_module */
00241          /*  RM: Feb  2 1993  Commented out */
00242          ) {
00243         if (def->rule && (unsigned long)def->rule<=MAX_BUILT_INS) {
00244           Errorline("the built-in %T '%s' may not be redefined.\n",
00245                     def->type, def->keyword->symbol);
00246         }
00247         else {
00248           def->type=typ;
00249           
00250           /* PVR single allocation in source */
00251           p=HEAP_ALLOC(pair_list);
00252           clear_copy();
00253           /* p->a=exact_copy(head2,HEAP); 24.8 25.8 */
00254           /* p->b=exact_copy(body,HEAP); 24.8 25.8 */
00255           
00256           p->a=quote_copy(head2,HEAP); /* 24.8 25.8 */
00257           p->b=quote_copy(body,HEAP); /* 24.8 25.8 */
00258           
00259           if (assert_first) {
00260             p->next=def->rule;
00261             def->rule=p;
00262           }
00263           else {
00264             p->next=NULL;
00265             p2= &(def->rule);
00266             while (*p2) {
00267               p2= &((*p2)->next);
00268             }
00269             *p2=p;
00270           }
00271           assert_ok=TRUE;
00272         }
00273       }
00274       else { /*  RM: Jan 27 1993  */
00275         Errorline("the %T '%s' may not be redefined from within module %s.\n",
00276                   def->type,
00277                   def->keyword->combined_name,
00278                   current_module->module_name);
00279       }
00280     else {
00281       Errorline("the %T '%s' may not be redefined as a %T.\n",
00282                 def->type, def->keyword->symbol, typ);
00283     }
00284   }
00285 }
00286 
00287 
00288 
00289 /******** ASSERT_RULE(t,typ)
00290   Add a rule to the rule tree.
00291   It may be either a predicate or a function.
00292   The psi_term T is of the form 'H :- B' or 'H -> B', but it may be incorrect
00293   (report errors). TYP is the type, function or predicate.
00294   */
00295 void assert_rule(t,typ)
00296      psi_term t;
00297      def_type typ;
00298 {
00299   ptr_psi_term head;
00300   ptr_psi_term body;
00301   
00302   get_two_args(t.attr_list,&head,&body);
00303   if (head)
00304     if (body)
00305       add_rule(head,body,typ);
00306     else {
00307       Syntaxerrorline("body missing in definition of %T '%P'.\n", typ, head);
00308     }
00309   else {
00310     Syntaxerrorline("head missing in definition of %T.\n",typ);
00311   }
00312 }
00313 
00314 
00315 
00316 /******** ASSERT_CLAUSE(t)
00317   Assert the clause T.
00318   Cope with various syntaxes for predicates.
00319   
00320   ASSERT_FIRST is a flag indicating the position:
00321   1= insert before existing rules (asserta),
00322   0= insert after existing rules (assert),
00323   */
00324 
00325 void assert_clause(t)
00326      ptr_psi_term t;
00327 {
00328   ptr_psi_term arg1,arg2;
00329   char *str;
00330   
00331   assert_ok=FALSE;  
00332   deref_ptr(t);
00333   
00334   /*  RM: Feb 22 1993  defined c_alias in modules.c
00335       if (equ_tok((*t),"alias")) {
00336       get_two_args(t->attr_list,&arg1,&arg2);
00337       if (arg1 && arg2) {
00338       Warningline("'%s' has taken the meaning of '%s'.\n",
00339       arg2->type->keyword->symbol, arg1->type->keyword->symbol);
00340       str=arg2->type->keyword->symbol;
00341       assert_ok=TRUE;
00342       deref_ptr(arg1);
00343       deref_ptr(arg2);
00344       *(arg2->type)= *(arg1->type);
00345       arg2->type->keyword->symbol=str;
00346       }
00347       else
00348       Errorline("arguments missing in %P.\n",t);
00349       }
00350       else
00351       */
00352   
00353   if (equ_tok((*t),":-"))
00354     assert_rule((*t),predicate);
00355   else
00356     if (equ_tok((*t),"->"))
00357       assert_rule((*t),function);
00358     else
00359       if (equ_tok((*t),"::"))
00360         assert_attributes(t);
00361       else
00362         
00363 #ifdef CLIFE
00364         if (equ_tok((*t),"block_struct"))
00365           define_block(t);
00366         else
00367 #endif /* CLIFE */
00368           /* if (equ_tok((*t),"<<<-")) {   RM: Feb 10 1993
00369              declare T as global. To do... maybe.
00370              }
00371              else
00372              */
00373           
00374           if (equ_tok((*t),"<|") || equ_tok((*t),":="))
00375             assert_complicated_type(t);
00376           else
00377             add_rule(t,NULL,predicate);
00378   
00379   /* if (!assert_ok && warning()) perr("the declaration is ignored.\n"); */
00380 }
00381 
00382 
00383 
00384 /******** START_CHRONO()
00385   This initialises the CPU time counter.
00386   */
00387 
00388 void start_chrono()
00389 {
00390   times(&start_time);
00391 }
00392 
00393 
00394 
00395 /******************************************************************************
00396   
00397   PROOF and UNIFICATION routines.
00398   
00399   These two different functions are written without using explicit recursion
00400   so that backtracking can easily take place between the two. PROVE can call
00401   UNIFY and vice-versa.
00402   
00403   The argument to PROVE is the adress of a PSI_TERM (psi-term) which represents
00404   a goal to prove.
00405   
00406   Prove then passes that on the goal stack to MAIN_PROVE() which does
00407   the real work, involving calls to UNIFY_AIM, PROVE_AIM and backtracking.
00408   
00409   ****************************************************************************/
00410 
00411 
00412 
00413 /******* PUSH_PTR_VALUE(p)
00414   Push the pair (P,*P) onto the stack of things to be undone (trail).
00415   It needn't be done if P is greater than the latest choice point because in
00416   that case memory is reclaimed.
00417   */
00418 void push_ptr_value(t,p)
00419      type_ptr t;
00420      GENERIC *p;
00421 {
00422   ptr_stack n;
00423   
00424   assert((GENERIC)p<heap_pointer); /*  RM: Feb 15 1993  */
00425   
00426   assert(VALID_ADDRESS(p));
00427   if (p < (GENERIC *)choice_stack || p > (GENERIC *)stack_pointer) 
00428     {
00429       n=STACK_ALLOC(stack);
00430       n->type=t;
00431       n->a= (GENERIC)p;
00432       n->b= *p;
00433       n->next=undo_stack;
00434       undo_stack=n;
00435     }
00436 }
00437 
00438 
00439 /******** PUSH_DEF_PTR_VALUE(q,p) (9.6)
00440   Same as push_ptr_value, but only for psi-terms whose definition field is
00441   being modified.  (If another field is modified, use push_ptr_value.)
00442   This routine implements the time-stamp technique of only trailing
00443   once between choice point creations, even on multiple bindings.
00444   q is address of psi-term, p is address of field inside psi-term
00445   that is modified.  Both the definition and the time_stamp must be trailed.
00446   */
00447 void push_def_ptr_value(q,p)
00448      ptr_psi_term q;
00449      GENERIC *p;
00450 {
00451   ptr_stack m,n;
00452   
00453   assert(VALID_ADDRESS(q));
00454   assert(VALID_ADDRESS(p));
00455 #ifdef TS
00456   if (TRAIL_CONDITION(q) &&
00457       /* (q->time_stamp != global_time_stamp) && */
00458       (p < (GENERIC *)choice_stack || p > (GENERIC *)stack_pointer))
00459     {
00460 #define TRAIL_TS
00461 #ifdef TRAIL_TS
00462       
00463       assert((GENERIC)q<heap_pointer); /*  RM: Feb 15 1993  */
00464       
00465       m=STACK_ALLOC(stack); /* Trail time_stamp */
00466       m->type=int_ptr;
00467       m->a= (GENERIC) &(q->time_stamp);
00468       m->b= (GENERIC) (q->time_stamp);
00469       m->next=undo_stack;
00470       n=STACK_ALLOC(stack); /* Trail definition field (top of undo_stack) */
00471       n->type=def_ptr;
00472       n->a= (GENERIC)p;
00473       n->b= *p;
00474       n->next=m;
00475       undo_stack=n;
00476 #else
00477       n=STACK_ALLOC(stack); /* Trail definition field (top of undo_stack) */
00478       n->type=def_ptr;
00479       n->a= (GENERIC)p;
00480       n->b= *p;
00481       n->next=undo_stack;
00482       undo_stack=n;
00483 #endif
00484       q->time_stamp=global_time_stamp;
00485     }
00486 #else
00487   push_ptr_value(def_ptr,p);
00488 #endif
00489 }
00490 
00491 
00492 
00493 /******** PUSH_PSI_PTR_VALUE(q,p) (9.6)
00494   Same as push_ptr_value, but only for psi-terms whose coref field is being
00495   modified.  (If another field is modified, use push_ptr_value.)
00496   This routine implements the time-stamp technique of only trailing
00497   once between choice point creations, even on multiple bindings.
00498   q is address of psi-term, p is address of field inside psi-term
00499   that is modified.  Both the coref and the time_stamp must be trailed.
00500   */
00501 void push_psi_ptr_value(q,p)
00502      ptr_psi_term q;
00503      GENERIC *p;
00504 {
00505   ptr_stack m,n;
00506   
00507   assert(VALID_ADDRESS(q));
00508   assert(VALID_ADDRESS(p));
00509 #ifdef TS
00510   if (TRAIL_CONDITION(q) &&
00511       /* (q->time_stamp != global_time_stamp) && */
00512       (p < (GENERIC *)choice_stack || p > (GENERIC *)stack_pointer))
00513     {
00514 #define TRAIL_TS
00515 #ifdef TRAIL_TS
00516       m=STACK_ALLOC(stack); /* Trail time_stamp */
00517       m->type=int_ptr;
00518       m->a= (GENERIC) &(q->time_stamp);
00519       m->b= (GENERIC) (q->time_stamp);
00520       m->next=undo_stack;
00521       n=STACK_ALLOC(stack); /* Trail coref field (top of undo_stack) */
00522       n->type=psi_term_ptr;
00523       n->a= (GENERIC)p;
00524       n->b= *p;
00525       n->next=m;
00526       undo_stack=n;
00527 #else
00528       n=STACK_ALLOC(stack); /* Trail coref field (top of undo_stack) */
00529       n->type=psi_term_ptr;
00530       n->a= (GENERIC)p;
00531       n->b= *p;
00532       n->next=undo_stack;
00533       undo_stack=n;
00534 #endif
00535       q->time_stamp=global_time_stamp;
00536     }
00537 #else
00538   push_ptr_value(psi_term_ptr,p);
00539 #endif
00540 }
00541 
00542 
00543 /* Same as push_ptr_value, but for objects that must always be trailed. */
00544 /* This includes objects outside of the Life data space and entries in  */
00545 /* the var_tree. */
00546 void push_ptr_value_global(t,p)
00547      type_ptr t;
00548      GENERIC *p;
00549 {
00550   ptr_stack n;
00551   
00552   assert(VALID_ADDRESS(p)); /* 17.8 */
00553   n=STACK_ALLOC(stack);
00554   n->type=t;
00555   n->a= (GENERIC)p;
00556   n->b= *p;
00557   n->next=undo_stack;
00558   undo_stack=n;
00559 }
00560 
00561 
00562 
00563 /******* PUSH_WINDOW(type,disp,wind)
00564   Push the window information (operation, display and window identifiers) on
00565   the undo_stack (trail) so that the window can be destroyed, redrawn, or
00566   hidden on backtracking.
00567   */
00568 void push_window(type,disp,wind)
00569      long type,disp,wind;
00570 {
00571   ptr_stack n;
00572   
00573   assert(type & undo_action);
00574   n=STACK_ALLOC(stack);
00575   n->type=type;
00576   n->a=(GENERIC)disp;
00577   n->b=(GENERIC)wind;
00578   n->next=undo_stack;
00579   undo_stack=n;
00580 }
00581 
00582 
00583 
00584 /******* PUSH2_PTR_VALUE(p)
00585   Push the pair (P,V) onto the stack of things to be undone (trail).
00586   It needn't be done if P is greater than the latest choice point because in
00587   that case memory is reclaimed.
00588   */
00589 void push2_ptr_value(t,p,v)
00590      type_ptr t;
00591      GENERIC *p;
00592      GENERIC v;
00593 {
00594   ptr_stack n;
00595   
00596   if (p<(GENERIC *)choice_stack || p>(GENERIC *)stack_pointer) {
00597     n=STACK_ALLOC(stack);
00598     n->type=t;
00599     n->a= (GENERIC)p;
00600     n->b= (GENERIC)v;
00601     n->next=undo_stack;
00602     undo_stack=n;
00603   }
00604 }
00605 
00606 
00607 
00608 /******** PUSH_GOAL(t,a,b,c)
00609   Push a goal onto the goal stack.
00610   T is the type of the goal, A,B and C are various parameters.
00611   See PUSH_CHOICE_POINT(t,a,b,c).
00612   */
00613 void push_goal(t,a,b,c)
00614      goals t;
00615      ptr_psi_term  a;
00616      ptr_psi_term  b;
00617      GENERIC c;
00618 {
00619   ptr_goal thegoal;
00620   
00621   thegoal=STACK_ALLOC(goal);
00622   
00623   thegoal->type=t;
00624   thegoal->a=a;
00625   thegoal->b=b;
00626   thegoal->c=c;
00627   thegoal->next=goal_stack;
00628   thegoal->pending=FALSE;
00629   
00630   goal_stack=thegoal;
00631 }
00632 
00633 
00634 
00635 /******** PUSH_CHOICE_POINT(t,a,b,c)
00636   T,A,B,C is an alternative goal to try.
00637   T is the type of the goal: unify or prove.
00638   
00639   If T=prove then
00640   a=goal to prove
00641   b=definition to use
00642   if b=DEFRULES then that means it's a first call.
00643   
00644   If T=unify then
00645   a and b are the terms to unify.
00646   
00647   etc...
00648   */
00649 void push_choice_point(t,a,b,c)
00650      goals t;
00651      ptr_psi_term a;
00652      ptr_psi_term b;
00653      GENERIC c;
00654 {
00655   ptr_goal alternative;
00656   ptr_choice_point choice;
00657   GENERIC top;
00658   
00659   alternative=STACK_ALLOC(goal);
00660   
00661   alternative->type=t;
00662   alternative->a=a;
00663   alternative->b=b;
00664   alternative->c=c;
00665   alternative->next=goal_stack;
00666   alternative->pending=FALSE;
00667   
00668   top=stack_pointer;
00669   
00670   choice=STACK_ALLOC(choice_point);
00671   
00672   choice->undo_point=undo_stack;
00673   choice->goal_stack=alternative;
00674   choice->next=choice_stack;
00675   choice->stack_top=top;
00676   
00677 #ifdef TS
00678   choice->time_stamp=global_time_stamp; /* 9.6 */
00679   global_time_stamp++; /* 9.6 */
00680 #endif
00681   
00682   choice_stack=choice;  
00683 }
00684 
00685 
00686 #define RESTORE_TIME_STAMP global_time_stamp=\
00687 choice_stack?choice_stack->time_stamp:INIT_TIME_STAMP;
00688 
00689 
00690 
00691 /******** UNDO(limit)
00692   Undoes any side-effects up to LIMIT. Limit being the adress of the stack of
00693   side-effects you wish to return to.
00694   
00695   Possible improvement:
00696   LIMIT is a useless parameter because GOAL_STACK is equivalent if one takes
00697   care when stacking UNDO actions. Namely, anything to be undone must be
00698   stacked LATER (=after) the goal which caused these things to be done, so that
00699   when the goal fails, everything done after it can be undone and the memory
00700   used can be reclaimed.
00701   This routine could be modified in order to cope with goals to be proved
00702   on backtracking: undo(goal).
00703   */
00704 void undo(limit)
00705      ptr_stack limit;
00706 {
00707   /*
00708     while((unsigned long)undo_stack>(unsigned long)goal_stack)
00709     */
00710   
00711   while ((unsigned long)undo_stack>(unsigned long)limit) { 
00712 #ifdef X11
00713     if (undo_stack->type & undo_action) {
00714       /* Window operation on backtracking */
00715       switch(undo_stack->type) { /*** RM 8/12/92 ***/
00716       case destroy_window:
00717         x_destroy_window((unsigned long)undo_stack->a,(unsigned long)undo_stack->b);
00718         break;
00719       case show_window:
00720         x_show_window((unsigned long)undo_stack->a,(unsigned long)undo_stack->b);
00721         break;
00722       case hide_window:
00723         x_hide_window((unsigned long)undo_stack->a,(unsigned long)undo_stack->b);
00724         break;
00725       case show_subwindow:
00726         x_show_subwindow((unsigned long)undo_stack->a,(unsigned long)undo_stack->b);
00727         break;
00728       case hide_subwindow:
00729         x_hide_subwindow((unsigned long)undo_stack->a,(unsigned long)undo_stack->b);
00730         break;
00731       }
00732     }
00733     else
00734 #endif
00735       /* Restoring variable value on backtracking */
00736       *((GENERIC *)(undo_stack->a))=undo_stack->b;
00737     undo_stack=undo_stack->next;
00738   }
00739 }
00740 
00741 
00742 
00743 /******** UNDO_ACTIONS()
00744   A subset of undo(limit) (the detrailing routine) that does all undo
00745   actions on the undo_stack, but does not undo any variable bindings,
00746   nor does it change the value of undo_stack.
00747   */
00748 void undo_actions()
00749 {
00750   ptr_stack u=undo_stack;
00751   
00752   Errorline("undo_actions should not be called.\n");
00753   undo(NULL); /* 8.10 */
00754   return;
00755   /*
00756     #ifdef X11
00757     while ((unsigned long)u) {
00758     if (u->type & undo_action) {
00759     if (u->type==destroy_window) {
00760     x_destroy_window((unsigned long)u->a,(unsigned long)u->b);
00761     }
00762     else if (u->type==show_window) {
00763     x_show_window((unsigned long)u->a,(unsigned long)u->b);
00764     }
00765     else if (u->type==hide_window) {
00766     x_hide_window((unsigned long)u->a,(unsigned long)u->b);
00767     }
00768     }
00769     u=u->next;
00770     }
00771     #endif
00772     */
00773 }
00774 
00775 
00776 
00777 /******** BACKTRACK()
00778   Undo everything back to the previous choice-point and take the alternative
00779   decision. This routine would have to be modified, along with UNDO to cope
00780   with goals to be proved on backtracking.
00781   */
00782 void backtrack()
00783 {
00784   long gts;
00785   
00786   goal_stack=choice_stack->goal_stack;
00787   undo(choice_stack->undo_point);
00788 #ifdef TS
00789   /* global_time_stamp=choice_stack->time_stamp; */ /* 9.6 */
00790 #endif
00791   stack_pointer=choice_stack->stack_top;
00792   choice_stack=choice_stack->next;
00793   resid_aim=NULL;
00794   
00795   
00796   /* assert((unsigned long)stack_pointer>=(unsigned long)cut_point); 13.6 */
00797   /* This situation occurs frequently in some benchmarks (e.g comb) */
00798   /* printf("*** Possible GC error: cut_point is dangling\n"); */
00799   /* fflush(stdout); */
00800   
00801   /* assert((unsigned long)stack_pointer>=(unsigned long)match_date); 13.6 */
00802 }
00803 
00804 
00805 
00806 /******** CLEAN_TRAIL(cutpt)
00807   This routine removes all trail entries between the top of the undo_stack
00808   and the cutpt, whose addresses are between the cutpt and stack_pointer.
00809   (The cutpt is the choice point that will become the most recent
00810   one after the cut.)
00811   This routine should be called when a cut built-in is done.
00812   This routine is careful not to remove any trailed entries that are
00813   on the heap or outside of Life space.
00814   */
00815 static void clean_trail(cutpt)
00816      ptr_choice_point cutpt;
00817 {
00818   ptr_stack *prev,u,cut_limit;
00819   GENERIC cut_sp;
00820   
00821   u = undo_stack;
00822   prev = &undo_stack;
00823   if (cutpt) {
00824     cut_sp = cutpt->stack_top;
00825     cut_limit = cutpt->undo_point;
00826   }
00827   else {
00828     cut_sp = mem_base; /* Empty stack */
00829     cut_limit = NULL;  /* Empty undo_stack */
00830   }
00831   
00832   while ((unsigned long)u > (unsigned long)cut_limit) {
00833     clean_iter++;
00834     if (!(u->type & undo_action) && VALID_RANGE(u->a) &&
00835         (unsigned long)u->a>(unsigned long)cut_sp && (unsigned long)u->a<=(unsigned long)stack_pointer) {
00836       *prev = u->next;
00837       clean_succ++;
00838     }
00839     prev = &(u->next);
00840     u = u->next;
00841   }
00842 }
00843 
00844 
00845 
00846 /******* CLEAN_UNDO_WINDOW(disp,wind)
00847   Remove all trail entries that reference a given window.
00848   This is called when the window is destroyed.
00849   */
00850 void clean_undo_window(disp,wind)
00851      long disp,wind;
00852 {
00853   ptr_stack *prev,u;
00854   ptr_choice_point c;
00855   
00856 #ifdef X11
00857   /* Remove entries on the trail */
00858   u = undo_stack;
00859   prev = &undo_stack;
00860   while (u) {
00861     if ((u->type & undo_action) &&
00862         ((unsigned long)u->a==disp) && ((unsigned long)u->b==wind)) {
00863       *prev = u->next;
00864     }
00865     prev = &(u->next);
00866     u = u->next;
00867   }
00868   
00869   /* Remove entries at the *tops* of trail entry points from the   */
00870   /* choice point stack.  It's only necessary to look at the tops, */
00871   /* since those are the only ones that haven't been touched by    */
00872   /* the previous while loop. */
00873   c = choice_stack;
00874   while (c) {
00875     u = c->undo_point;
00876     prev = &(c->undo_point);
00877     while (u && (u->type & undo_action) &&
00878            ((unsigned long)u->a==disp) && ((unsigned long)u->b==wind)) {
00879       *prev = u->next;
00880       prev = &(u->next);
00881       u = u->next;
00882     }
00883     c = c->next;
00884   }
00885 #endif
00886 }
00887 
00888 
00889 
00890 /* Unify the corresponding arguments */
00891 void merge1(u,v)
00892      ptr_node *u,v;
00893 {
00894   long cmp;
00895   ptr_node temp;
00896   
00897   if (v) {
00898     if (*u==NULL) {
00899       /* push_ptr_value(int_ptr,u); */
00900       /* (*u)=STACK_ALLOC(node); */
00901       /* **u= *v; */
00902       /* more_v_attr=TRUE; */
00903     }
00904     else {
00905       cmp=featcmp((*u)->key,v->key);
00906       if (cmp==0) {
00907         if (v->right)
00908           merge1(&((*u)->right),v->right);
00909         
00910         push_goal(unify,(*u)->data,v->data,NULL);
00911         
00912         if (v->left)
00913           merge1(&((*u)->left),v->left);
00914       }
00915       else if (cmp>0) {
00916         temp=v->right;
00917         v->right=NULL;
00918         merge1(&((*u)->left),v);
00919         merge1(u,temp);
00920         v->right=temp;
00921       }
00922       else {
00923         temp=v->left;
00924         v->left=NULL;
00925         merge1(&((*u)->right),v);
00926         merge1(u,temp);
00927         v->left=temp;
00928       }
00929     }
00930   }
00931   else if (*u!=NULL) {
00932     /* more_u_attr=TRUE; */
00933   }
00934 }
00935 
00936 
00937 /* Evaluate the lone arguments (For LAZY failure + EAGER success) */
00938 /* Evaluate low numbered lone arguments first. */
00939 /* For each lone argument in either u or v, create a new psi-term to put */
00940 /* the (useless) result: This is needed so that *all* arguments of a uni-*/
00941 /* unified psi-term are evaluated, which avoids incorrect 'Yes' answers. */
00942 void merge2(u,v)
00943      ptr_node *u,v;
00944 {
00945   long cmp;
00946   ptr_node temp;
00947   
00948   if (v) {
00949     if (*u==NULL) {
00950       ptr_psi_term t;
00951       merge2(u,v->right);
00952       t = (ptr_psi_term) v->data;
00953       deref2_rec_eval(t); /* Assumes goal_stack is already restored. */
00954       merge2(u,v->left);
00955     }
00956     else {
00957       cmp=featcmp((*u)->key,v->key);
00958       if (cmp==0) {
00959         /* if (v->right) */
00960         merge2(&((*u)->right),v->right);
00961         
00962         /* if (v->left) */
00963         merge2(&((*u)->left),v->left);
00964       }
00965       else if (cmp>0) {
00966         temp=v->right;
00967         v->right=NULL;
00968         merge2(&((*u)->left),v);
00969         merge2(u,temp);
00970         v->right=temp;
00971       }
00972       else {
00973         temp=v->left;
00974         v->left=NULL;
00975         merge2(&((*u)->right),v);
00976         merge2(u,temp);
00977         v->left=temp;
00978       }
00979     }
00980   }
00981   else if (*u!=NULL) {
00982     ptr_psi_term t;
00983     merge2(&((*u)->right),v);
00984     t = (ptr_psi_term) (*u)->data;
00985     deref2_rec_eval(t); /* Assumes goal_stack is already restored. */
00986     merge2(&((*u)->left),v);
00987   }
00988 }
00989 
00990 
00991 /* Merge v's loners into u and evaluate the corresponding arguments */
00992 void merge3(u,v)
00993      ptr_node *u,v;
00994 {
00995   long cmp;
00996   ptr_node temp;
00997   
00998   if (v) {
00999     if (*u==NULL) {
01000       push_ptr_value(int_ptr,u);
01001       (*u)=STACK_ALLOC(node);
01002       **u= *v;
01003       more_v_attr=TRUE;
01004     }
01005     else {
01006       ptr_psi_term t1,t2;
01007       
01008       cmp=featcmp((*u)->key,v->key);
01009       if (cmp==0) {
01010         if (v->right)
01011           merge3(&((*u)->right),v->right);
01012         
01013         t1 = (ptr_psi_term) (*u)->data;
01014         /* t2 = (ptr_psi_term) v->data; */
01015         deref2_eval(t1);
01016         /* deref2_eval(t2); */
01017         /* push_goal(unify,(*u)->data,v->data,NULL); */
01018         
01019         if (v->left)
01020           merge3(&((*u)->left),v->left);
01021       }
01022       else if (cmp>0) {
01023         temp=v->right;
01024         v->right=NULL;
01025         merge3(&((*u)->left),v);
01026         merge3(u,temp);
01027         v->right=temp;
01028       }
01029       else {
01030         temp=v->left;
01031         v->left=NULL;
01032         merge3(&((*u)->right),v);
01033         merge3(u,temp);
01034         v->left=temp;
01035       }
01036     }
01037   }
01038   else if (*u!=NULL) {
01039     more_u_attr=TRUE;
01040   }
01041 }
01042 
01043 
01044 
01045 
01046 /******** MERGE(u,v)
01047   U and V are two binary trees containing the
01048   attributes fields of psi-terms.  U and V are merged together, that is U
01049   becomes the union of U and V:
01050   For each label L in V and L->Vpsi_term:
01051   If L is in U Then With L->Upsi_term Do unify(Upsi_term,Vpsi_term)
01052   Else merge L->Vpsi_term in U.
01053   Unification is simply done by appending the 2 psi_terms to the unification
01054   stack.  All effects must be recorded in the trail so that they can be
01055   undone on backtracking.
01056   */
01057 
01058 #if FALSE
01059 /* This version is not quite right */
01060 void merge(u,v)
01061      ptr_node *u,v;
01062 {
01063   long cmp;
01064   ptr_node temp;
01065   
01066   if (v) {
01067     if (*u==NULL) {
01068       ptr_psi_term t;
01069       merge(u,v->right);
01070       
01071       push_ptr_value(int_ptr,u);
01072       (*u)=STACK_ALLOC(node);
01073       **u= *v;
01074       more_v_attr=TRUE;
01075       
01076       t = (ptr_psi_term) v->data;
01077       deref2_rec_eval(t); /* Assumes goal_stack is already restored. */
01078       merge(u,v->left);
01079     }
01080     else {
01081       cmp=featcmp((*u)->key,v->key);
01082       if (cmp==0) {
01083         /* if (v->right) */
01084         merge(&((*u)->right),v->right);
01085         
01086         push_goal(unify,(*u)->data,v->data,NULL);
01087         
01088         /* if (v->left) */
01089         merge(&((*u)->left),v->left);
01090       }
01091       else if (cmp>0) {
01092         temp=v->right;
01093         v->right=NULL;
01094         merge(&((*u)->left),v);
01095         merge(u,temp);
01096         v->right=temp;
01097       }
01098       else {
01099         temp=v->left;
01100         v->left=NULL;
01101         merge(&((*u)->right),v);
01102         merge(u,temp);
01103         v->left=temp;
01104       }
01105     }
01106   }
01107   else if (*u!=NULL) {
01108     ptr_psi_term t;
01109     merge(&((*u)->right),v);
01110     t = (ptr_psi_term) (*u)->data;
01111     deref2_rec_eval(t); /* Assumes goal_stack is already restored. */
01112     merge(&((*u)->left),v);
01113     
01114     more_u_attr=TRUE;
01115   }
01116 }
01117 #endif
01118 
01119 void merge(u,v)
01120      ptr_node *u,v;
01121 {
01122   merge1(u,v); /* Unify corresponding arguments */
01123   merge2(u,v); /* Evaluate lone arguments (lazy failure + eager success) */
01124   merge3(u,v); /* Merge v's loners into u & evaluate corresponding arguments */
01125 }
01126 
01127 /* For built-ins.c */
01128 void merge_unify(u,v)
01129      ptr_node *u,v;
01130 {
01131   merge1(u,v); /* Unify corresponding arguments */
01132   merge3(u,v); /* Merge v's loners into u & evaluate corresponding arguments */
01133 }
01134 
01135 
01136 
01137 
01138 /******** SHOW_COUNT()
01139   This routine doesn't do anything if not in verbose mode.
01140   It prints the number of of sub-goals attempted, along with cpu-time
01141   spent during the proof etc...
01142   */
01143 void show_count()
01144 {
01145   float t;
01146   
01147   if (verbose) {
01148     printf("  [");
01149     
01150     times(&end_time);
01151 #ifndef OS2_PORT
01152     t = (end_time.tms_utime - start_time.tms_utime)/60.0;
01153 #else
01154     t = (end_time - start_time)/60.0;
01155 #endif    
01156     printf("%1.3fs cpu, %ld goal%s",t,goal_count,(goal_count!=1?"s":""));
01157     
01158     if (t!=0.0) printf(" (%0.0f/s)",goal_count/t);
01159     
01160     printf(", %ld stack",sizeof(mem_base)*(stack_pointer-mem_base));
01161     printf(", %ld heap",sizeof(mem_base)*(mem_limit-heap_pointer));
01162     
01163     printf("]");
01164   }
01165   
01166   if(NOTQUIET) {
01167     printf("\n");
01168     stack_info(stdout);
01169   }
01170   
01171   goal_count=0;
01172 }
01173 
01174 
01175 
01176 /******** FETCH_DEF(psi_term)
01177   Fetch the type definition of a psi_term and execute it.
01178   That is, get the list of (term,predicate) pairs that define the type.
01179   Unify the psi_term with the term, then prove the predicate.
01180   
01181   This routine only gets the pairs that are defined in the type itself,
01182   not those defined in any types above it.  This is the correct behavior
01183   for enumerating type disjunctions--all higher constraints have already
01184   been checked.
01185   
01186   The above is true if allflag==FALSE.  If allflag==TRUE then all constraints
01187   are executed, not just those defined in the type itself.
01188   */
01189 void fetch_def(u, allflag)
01190      ptr_psi_term u;
01191      long allflag;
01192 {
01193   ptr_triple_list prop;
01194   ptr_psi_term v,w;
01195   ptr_definition utype;
01196   
01197   /* Uses SMASK because called from check_out */
01198   push2_ptr_value(int_ptr,&(u->status),(u->status & SMASK));
01199   u->status=(4 & SMASK) | (u->status & RMASK);
01200   
01201   utype=u->type;
01202   prop=u->type->properties;
01203   if (prop) {
01204     
01205     Traceline("fetching definition of %P\n",u);
01206     
01207     while (prop) {
01208       if (allflag || prop->c==utype) {
01209         clear_copy();
01210         v=eval_copy(prop->a,STACK);
01211         w=eval_copy(prop->b,STACK);
01212         
01213         if (w) push_goal(prove,w,DEFRULES,NULL);
01214         
01215         deref_ptr(v);
01216         v->status=4;
01217         push_goal(unify,u,v,NULL);
01218         i_eval_args(v->attr_list);
01219       }
01220       prop=prop->next;
01221     }
01222   }
01223 }
01224 
01225 
01226 /******** FETCH_DEF_LAZY(psi_term,type1,type2,attr_list1,attr_list2)
01227   Fetch the type definition of a psi_term and execute it.
01228   That is, get the list of (term,pred) pairs that define the type.
01229   'Term' is one of the type's attributes and 'pred' is a constraint.
01230   Unify the psi_term with the term, then prove pred.
01231   
01232   Only those (term,pred) pairs are executed whose original type is
01233   below both type1 and type2, the types of the two psi-terms whose
01234   unification created psi_term.  This avoids doing much superfluous work.
01235   
01236   The above behavior is correct for a psi_term when always_check==TRUE for
01237   that psi_term.  If always_check==FALSE for a psi_term, then if it does not
01238   have attributes it is not checked, and the addition of an attribute will
01239   force checking to occur.
01240   
01241   Example:
01242   
01243   :: t(a=>one,b=>two,c=> X) | thing(X).
01244   
01245   psi_term = A:t (it can be any psi_term of type t)
01246   term     = t(a=>one,b=>two,c=> X)
01247   pred     = thing(X)
01248   */
01249 void fetch_def_lazy(u, old1, old2, old1attr, old2attr, old1stat, old2stat)
01250      ptr_psi_term u;
01251      ptr_definition old1, old2;
01252      ptr_node old1attr, old2attr;
01253      long old1stat, old2stat;
01254 {
01255   ptr_triple_list prop;
01256   ptr_psi_term v,w;
01257   long checked1, checked2;
01258   long m1, m2;
01259   
01260   if (!u->type->always_check) if (u->attr_list==NULL) return;
01261   
01262   push_ptr_value(int_ptr,&(u->status));
01263   u->status=4;
01264   
01265   prop=u->type->properties;
01266   if (prop) {
01267     Traceline("fetching partial definition of %P\n",u);
01268     
01269     checked1 = old1attr || old1->always_check;
01270     checked2 = old2attr || old2->always_check;
01271 
01272     /* checked1 = (old1stat==4); */ /* 18.2.94 */
01273     /* checked2 = (old2stat==4); */
01274     
01275     while (prop) {
01276       /* Only do those constraints that have not yet been done: */
01277       /* In matches, mi is TRUE iff oldi <| prop->c.            */
01278       if (!checked1) m1=FALSE; else matches(old1,prop->c,&m1);
01279       if (!checked2) m2=FALSE; else matches(old2,prop->c,&m2);
01280       if (!m1 && !m2) {
01281         /* At this point, prop->c is an attribute that has not yet */
01282         /* been checked. */
01283         clear_copy();
01284         v=eval_copy(prop->a,STACK);
01285         w=eval_copy(prop->b,STACK);
01286         
01287         if (w) push_goal(prove,w,DEFRULES,NULL);
01288         
01289         deref_ptr(v);
01290         v->status=4;
01291         push_goal(unify,u,v,NULL);
01292         i_eval_args(v->attr_list);
01293       }
01294       prop=prop->next;
01295     }
01296   }
01297 }
01298 
01299 
01300 
01301 /******** UNIFY_AIM()
01302   This routine performs one unification step.
01303   AIM is the current unification goal.
01304   
01305   U and V are the two psi-terms to unify.
01306   
01307   It swaps the two psi-terms into chronological order.
01308   U is the oldest (smallest stack address).
01309   Calculates their GLB, check their values are unifiable.
01310   It deals with all the messy things like:
01311   curried functions gaining missing arguments,
01312   types which need checking,
01313   residuation variables whose constraints must be released,
01314   disjunctions appearing in the GLB etc...
01315   
01316   It's a rather lengthy routine, only its speed is fairly crucial in the
01317   overall performance of Wild_Life, and the code is not duplicated elsewhere.
01318   */
01319 
01320 long unify_body();
01321 
01322 long unify_aim_noeval()
01323 {
01324   return unify_body(FALSE);
01325 }
01326 
01327 long unify_aim()
01328 {
01329   return unify_body(TRUE);
01330 }
01331 
01332 long unify_body(eval_flag)
01333      long eval_flag;
01334 {
01335   long success=TRUE,compare;
01336   ptr_psi_term u,v,tmp;
01337   ptr_list lu,lv;
01338   REAL r;
01339   ptr_definition new_type,old1,old2;
01340   ptr_node old1attr, old2attr;
01341   ptr_int_list new_code;
01342   ptr_int_list d=NULL;
01343   long old1stat,old2stat; /* 18.2.94 */
01344   
01345   u=(ptr_psi_term )aim->a;
01346   v=(ptr_psi_term )aim->b;
01347   
01348   deref_ptr(u);
01349   deref_ptr(v);
01350 
01351   Traceline("unify %P with %P\n",u,v);
01352   
01353   if (eval_flag) {
01354     deref(u);
01355     deref(v);
01356   }
01357   
01358   if (u!=v) {
01359     
01360     /**** Swap the two psi-terms to get them into chronological order ****/
01361     if (u>v) { tmp=v; v=u; u=tmp; }
01362       
01363     /**** Check for curried functions ****/
01364     u_func=(u->type->type==function);
01365     v_func=(v->type->type==function);
01366     old1stat=u->status; /* 18.2.94 */
01367     old2stat=v->status; /* 18.2.94 */
01368     
01369     /* PVR 18.2.94 */
01370     /* if (u_func && !(u->flags&QUOTED_TRUE) && v->attr_list) { */
01371     if (u_func && u->status==4 && !(u->flags&QUOTED_TRUE) && v->attr_list) {
01372       Errorline("attempt to unify with curried function %P\n", u);
01373       return FALSE;
01374     }
01375     /* if (v_func && !(v->flags&QUOTED_TRUE) && u->attr_list) { */
01376     if (v_func && v->status==4 && !(v->flags&QUOTED_TRUE) && u->attr_list) {
01377       Errorline("attempt to unify with curried function %P\n", v);
01378       return FALSE;
01379     }
01380 
01381     
01382 #ifdef ARITY  /*  RM: Mar 29 1993  */
01383     arity_unify(u,v);
01384 #endif
01385     
01386     /***** Deal with global vars ****   RM: Feb  8 1993  */
01387     if((GENERIC)v>=heap_pointer)
01388       return global_unify(u,v);
01389     
01390     
01391     /**** Calculate their Greatest Lower Bound and compare them ****/
01392     success=(compare=glb(u->type,v->type,&new_type,&new_code));
01393     
01394     if (success) {
01395       
01396       /**** Keep the old types for later use in incr. constraint checking ****/
01397       old1 = u->type;
01398       old2 = v->type;
01399       old1attr = u->attr_list;
01400       old2attr = v->attr_list;
01401       
01402       /**** DECODE THE RESULTING TYPE ****/
01403       if (!new_type) {
01404         d=decode(new_code);
01405         if (d) {
01406           new_type=(ptr_definition )d->value;
01407           d=d->next;
01408         }
01409         else
01410           Errorline("undecipherable sort code.\n");
01411       }
01412       
01413       /**** Make COMPARE a little more precise ****/
01414       if (compare==1)
01415         if (u->value && !v->value)
01416           compare=2;
01417         else
01418           if (v->value && !u->value)
01419             compare=3;
01420       
01421       /**** Determine the status of the resulting psi-term ****/
01422       new_stat=4;
01423       switch (compare) {
01424       case 1:
01425         if (u->status <4 && v->status <4)
01426           new_stat=2;
01427         break;
01428       case 2:
01429         if (u->status<4)
01430           new_stat=2;
01431         break;
01432       case 3:
01433         if (v->status<4)
01434           new_stat=2;
01435         break;
01436       case 4:
01437         new_stat=2;
01438         break;
01439       }
01440       
01441       /*
01442         printf("u=%s, v=%s, compare=%ld, u.s=%ld, v.s=%ld, ns=%ld\n",
01443         u->type->keyword->symbol,
01444         v->type->keyword->symbol,
01445         compare,
01446         u->status,
01447         v->status,
01448         new_stat);
01449         */
01450       
01451       /**** Check that integers have no decimals ****/
01452       if (u->value && sub_type(new_type,integer)) {
01453         r= *(REAL *)u->value;
01454         success=(r==floor(r));
01455       }
01456       if (success && v->value && sub_type(new_type,integer)) {
01457         r= *(REAL *)v->value;
01458         success=(r==floor(r));
01459       }
01460       
01461       /**** Unify the values of INTs REALs STRINGs LISTs etc... ****/
01462       if (success) {
01463         /* LAZY-EAGER */
01464         if (u->value!=v->value)
01465           if (!u->value) {
01466             compare=4;
01467             push_ptr_value(int_ptr,&(u->value));
01468             u->value=v->value;          
01469           }
01470           else if (v->value) {
01471             if (overlap_type(new_type,real))
01472               success=(*((REAL *)u->value)==(*((REAL *)v->value)));
01473             else if (overlap_type(new_type,quoted_string))
01474               success=(strcmp((char *)u->value,(char *)v->value)==0);
01475             else if (overlap_type(new_type,sys_bytedata)) {
01476               unsigned long ulen = *((unsigned long *)u->value);
01477               unsigned long vlen = *((unsigned long *)v->value);
01478               success=(ulen==vlen &&
01479                        (bcmp((char *)u->value,(char *)v->value,ulen)==0));
01480             }
01481             else if (u->type==cut && v->type==cut) { /* 22.9 */
01482               GENERIC mincut;
01483               mincut = (u->value<v->value?u->value:v->value);
01484               if (mincut!=u->value) {
01485                 push_ptr_value(cut_ptr,&(u->value));
01486                 u->value=mincut;
01487               }
01488             }
01489             else {
01490               Warningline("'%s' may not be unified.\n",new_type->keyword->symbol);
01491               success=FALSE;
01492             }
01493           }
01494           else
01495             compare=4;
01496       }
01497       
01498       /**** Bind the two psi-terms ****/
01499       if (success) {
01500         /* push_ptr_value(psi_term_ptr,&(v->coref)); 9.6 */
01501         push_psi_ptr_value(v,&(v->coref));
01502         v->coref=u;
01503         
01504         if (!equal_types(u->type,new_type)) {         
01505           push_ptr_value(def_ptr,&(u->type));
01506           /* This does not seem to work right with cut.lf: */
01507           /* push_def_ptr_value(u,&(u->type)); */ /* 14.8 */
01508           u->type=new_type;
01509         }
01510         
01511         if (u->status!=new_stat) {
01512           push_ptr_value(int_ptr,&(u->status));
01513           u->status=new_stat;
01514         }
01515         
01516         /**** Unify the attributes ****/
01517         more_u_attr=FALSE;
01518         more_v_attr=FALSE;
01519         
01520         
01521 #ifdef ARITY  /*  RM: Mar 29 1993  */
01522         arity_merge(u->attr_list,v->attr_list);
01523 #endif
01524         
01525         
01526         if (u->attr_list || v->attr_list)
01527           merge(&(u->attr_list),v->attr_list);
01528         
01529         /**** Look after curried functions ****/
01530         /*
01531         if ((u_func && more_v_attr) || (v_func && more_u_attr)) {
01532           if (!(u->flags&QUOTED_TRUE | v->flags&QUOTED_TRUE)) {
01533             Traceline("re-evaluating curried expression %P\n", u);
01534             if (u->status!=0) {
01535               push_ptr_value(int_ptr,&(u->status));
01536               u->status=0;
01537             }
01538             check_func(u);
01539           }
01540           }
01541           */
01542         
01543         if (v->flags&QUOTED_TRUE && !(u->flags&QUOTED_TRUE)) { /* 16.9 */
01544           push_ptr_value(int_ptr,&(u->flags));
01545           u->flags|=QUOTED_TRUE;
01546         }
01547         
01548         /**** RELEASE RESIDUATIONS ****/
01549         /* This version implements the correct semantics. */
01550         if (u->resid)
01551           release_resid(u);
01552         if (v->resid)
01553           release_resid(v);
01554         
01555         /**** Alternatives in a type disjunction ****/
01556         if (d) {
01557           Traceline("pushing type disjunction choice point for %P\n",u);
01558           push_choice_point(type_disj,u,d,NULL);
01559         }
01560         
01561         /**** VERIFY CONSTRAINTS ****/
01562         /* if ((old1stat<4 || old2stat<4) &&
01563              (u->type->type==type || v->type->type==type)) { 18.2.94 */
01564         if (new_stat<4 && u->type->type==type) {
01565           /* This does not check the already-checked properties     */
01566           /* (i.e. those in types t with t>=old1 or t>=old2),       */
01567           /* and it does not check anything if u has no attributes. */
01568           /* It will, however, check the unchecked properties if a  */
01569           /* type gains attributes.                                 */
01570           fetch_def_lazy(u, old1, old2, 
01571                          old1attr, old2attr,
01572                          old1stat, old2stat);
01573         }
01574       }
01575     }
01576   }
01577   return success;
01578 }
01579 
01580 
01581 
01582 /******** DISJUNCT_AIM()
01583   This is the disjunction enumeration routine.
01584   If U is the disjunction {H|T} then first bind U to H, then on backtracking
01585   enumerate the disjunction T.  U is always passed along so that every choice
01586   of the disjunction can be bound to U.
01587   */
01588 long disjunct_aim()
01589 {
01590   ptr_psi_term u,v;
01591   ptr_list l;
01592   long success=TRUE;
01593   
01594   printf("Call to disjunct_aim\nThis routine inhibited by RM: Dec  9 1992\n");
01595   
01596   return success;
01597 }
01598 
01599 
01600 
01601 /******** PROVE_AIM()
01602   This is the proving routine.  It performs one
01603   proof step, that is: finding the definition to use to prove AIM, and
01604   unifying the HEAD with the GOAL before proving. It all works by pushing
01605   sub-goals onto the goal_stack. Special cases are CUT and AND (","). Built-in
01606   predicates written in C are called.
01607   */
01608 long prove_aim()
01609 {
01610   long success=TRUE;
01611   ptr_psi_term thegoal,head,body,arg1,arg2;
01612   ptr_pair_list rule;
01613   
01614   thegoal=(ptr_psi_term )aim->a;
01615   rule=(ptr_pair_list )aim->b;
01616   
01617   if (thegoal && rule) {
01618     
01619     deref_ptr(thegoal); /* Evaluation is explicitly handled later. */
01620     
01621     if (thegoal->type!=and) {
01622       if (thegoal->type!=cut)
01623         if(thegoal->type!=life_or) {
01624           /* User-defined predicates with unevaluated arguments */
01625           /* Built-ins do this themselves (see built_ins.c). */
01626           /* if (!thegoal->type->evaluate_args) mark_quote(thegoal); 24.8 25.8 */
01627           
01628           if(i_check_out(thegoal)) { /* RM: Apr  6 1993  */
01629             
01630             goal_stack=aim->next;
01631             goal_count++;
01632             
01633             if ((unsigned long)rule==DEFRULES) {
01634               rule=(ptr_pair_list)thegoal->type->rule;
01635               if (thegoal->type->type==predicate) {
01636                 if (!rule) /* This can happen when RETRACT is used */
01637                   success=FALSE;
01638               }
01639               else if ( thegoal->type->type==function
01640                       || ( thegoal->type->type==type
01641                          && sub_type(boolean,thegoal->type)
01642                          )
01643                       ) {
01644                 if (thegoal->type->type==function && !rule)
01645                   /* This can happen when RETRACT is used */
01646                   success=FALSE;
01647                 else {
01648                   ptr_psi_term bool_pred;
01649                   ptr_node a;
01650                   /* A function F in pred. position is called as */
01651                   /* '*bool_pred*'(F), which succeeds if F returns true */
01652                   /* and fails if it returns false.  It can residuate too. */
01653                   bool_pred=stack_psi_term(0);
01654                   bool_pred->type=boolpredsym;
01655                   bool_pred->attr_list=(a=STACK_ALLOC(node));
01656                   a->key=one;
01657                   a->left=a->right=NULL;
01658                   a->data=(GENERIC) thegoal;
01659                   push_goal(prove,bool_pred,DEFRULES,NULL);
01660                   return success; /* We're done! */
01661                 }
01662               }
01663               else if (!thegoal->type->protected && thegoal->type->type==undef) {
01664                 /* Don't give an error message for undefined dynamic objects */
01665                 /* that do not yet have a definition */
01666                 success=FALSE;
01667               }
01668               else if (thegoal->type==true || thegoal->type==false) {
01669                 /* What if the 'true' or 'false' have arguments? */
01670                 success=(thegoal->type==true);
01671                 return success; /* We're done! */
01672               }
01673               else {
01674                 /* Error: undefined predicate. */
01675                 /* Call the call_handler (which may do an auto-load). */
01676                 ptr_psi_term call_handler;
01677                 /* mark_quote(thegoal); */
01678                 
01679                 /*  RM: Jan 27 1993 */
01680                 /* Warningline("call handler invoked for %P\n",thegoal); */
01681                 
01682                 call_handler=stack_psi_term(0);
01683                 call_handler->type=call_handlersym;
01684                 stack_add_psi_attr(call_handler,"1",thegoal);
01685                 push_goal(prove,call_handler,DEFRULES,NULL);
01686                 return success; /* We're done! */
01687               }
01688             }
01689             
01690             if (success) {
01691               
01692               if ((unsigned long)rule<=MAX_BUILT_INS) {
01693                 
01694                 /* For residuation (RESPRED) */
01695                 curried=FALSE;
01696                 can_curry=TRUE;
01697                 resid_vars=NULL;
01698                 /* resid_limit=(ptr_goal )stack_pointer; 12.6 */
01699                 
01700                 if (thegoal->type!=tracesym) /* 26.1 */
01701                   Traceline("prove built-in %P\n", thegoal);
01702                 
01703                 /* RESPRED */ resid_aim=aim;
01704                 /* Residuated predicate must return success=TRUE */
01705                 success=c_rule[(unsigned long)rule]();
01706                 
01707                 /* RESPRED */ if (curried)
01708                 /* RESPRED */   do_currying();
01709                 /* RESPRED */ else if (resid_vars)
01710                 /* RESPRED */   success=do_residuation_user(); /* 21.9 */ /* PVR 9.2.94 */
01711               }
01712               else {
01713                 
01714                 /* Evaluate arguments of a predicate call before the call. */
01715                 deref_args(thegoal,set_empty);
01716                 
01717                 Traceline("prove %P\n", thegoal);
01718                 
01719                 /* For residuation (RESPRED) */
01720                 curried=FALSE;
01721                 can_curry=TRUE;
01722                 resid_vars=NULL;
01723                 /* resid_limit=(ptr_goal )stack_pointer; 12.6 */
01724                 
01725                 while (rule && (rule->a==NULL || rule->b==NULL)) {
01726                   rule=rule->next;
01727                   Traceline("alternative clause has been retracted\n");
01728                 }
01729                 if (rule) {
01730                   
01731                   clear_copy();
01732                   if (TRUE) /* 8.9 */
01733                     /* if (thegoal->type->evaluate_args) 8.9 */
01734                     head=eval_copy(rule->a,STACK);
01735                   else
01736                     head=quote_copy(rule->a,STACK);
01737 
01738                   body=eval_copy(rule->b,STACK);
01739 
01740                   /* What does this do?? */
01741                   /* if (body->type==built_in) */
01742                   /*   body->coref=head; */
01743                   
01744                   if (rule->next)
01745                     push_choice_point(prove,thegoal,rule->next,NULL);
01746                   
01747                   if (body->type!=succeed)
01748                     push_goal(prove,body,DEFRULES,NULL);
01749                   
01750                   /* push_ptr_value(psi_term_ptr,&(head->coref)); 9.6 */
01751                   push_psi_ptr_value(head,&(head->coref));
01752                   head->coref=thegoal;
01753                   merge(&(thegoal->attr_list),head->attr_list);
01754                   if (!head->status) {
01755                     i_eval_args(head->attr_list);
01756                   }
01757                 }
01758                 else {
01759                   success=FALSE;
01760                 }
01761               }
01762             }
01763           }
01764         }
01765         else { /* ';' built-in */
01766           /*  RM: Apr  6 1993  */
01767           goal_stack=aim->next;
01768           goal_count++;
01769           get_two_args(thegoal->attr_list,&arg1,&arg2);
01770           push_choice_point(prove,arg2,DEFRULES,NULL);
01771           push_goal(prove,arg1,DEFRULES,NULL);
01772         }
01773       else { /* 'Cut' built-in*/
01774         goal_stack=aim->next;
01775         goal_count++;
01776         /* assert((ptr_choice_point)(thegoal->value)<=choice_stack); 12.7 */
01777         cut_to(thegoal->value); /* 12.7 */
01778 #ifdef CLEAN_TRAIL
01779         clean_trail(choice_stack);
01780 #endif
01781         Traceline("cut all choice points back to %x\n",choice_stack);
01782       }
01783     }
01784     else { /* 'And' built-in */
01785       goal_stack=aim->next;
01786       goal_count++;
01787       get_two_args(thegoal->attr_list,&arg1,&arg2);
01788       push_goal(prove,arg2,DEFRULES,NULL);
01789       push_goal(prove,arg1,DEFRULES,NULL);
01790     }
01791   }
01792   else
01793     success=FALSE;
01794   
01795   /* RESPRED */ resid_aim=NULL;
01796   return success;
01797 }
01798 
01799 
01800 
01801 /******** TYPE_DISJ_AIM()
01802   This routine implements type disjunctions, that is, when a type has been
01803   decoded and found to be a disjunction of types, enumerates the different
01804   values one by one.
01805   */
01806 
01807 void type_disj_aim()
01808 {
01809   ptr_psi_term t;
01810   ptr_int_list d;
01811   
01812   t=(ptr_psi_term)aim->a;
01813   d=(ptr_int_list)aim->b;
01814   
01815   if (d->next) {
01816     Traceline("pushing type disjunction choice point for %P\n", t);
01817     push_choice_point(type_disj,t,d->next,NULL);
01818   }
01819   
01820   push_ptr_value(def_ptr,&(t->type));
01821   /* Below makes cut.lf behave incorrectly: */
01822   /* push_def_ptr_value(t,&(t->type)); */ /* 14.8 */
01823   t->type=(ptr_definition)d->value;
01824   
01825   Traceline("setting type disjunction to %s.\n", t->type->keyword->symbol);
01826   
01827   if ((t->attr_list || t->type->always_check) && t->status<4)
01828     fetch_def(t, FALSE);
01829 }
01830 
01831 
01832 
01833 /******** CLAUSE_AIM(r)
01834   Prove a CLAUSE or RETRACT goal. That is try to
01835   unify the calling argument with the current rule. If this succeeds and
01836   R=TRUE then delete the rule (RETRACT).
01837   */
01838 long clause_aim(r)
01839      long r;
01840 {
01841   long success=FALSE;
01842   ptr_pair_list *p;
01843   ptr_psi_term head,body,rule_head,rule_body;
01844   
01845   head=(ptr_psi_term)aim->a;
01846   body=(ptr_psi_term)aim->b;
01847   p=(ptr_pair_list *)aim->c;
01848   
01849   if ((unsigned long)(*p)>MAX_BUILT_INS) {
01850     success=TRUE;
01851     /* deref(head); 17.9 */
01852     
01853     if ((*p)->next) {
01854       if (r) {
01855         Traceline("pushing 'retract' choice point for %P\n", head);
01856         push_choice_point(del_clause,head,body,&((*p)->next));
01857         /* push_choice_point(del_clause,head,body,p); */
01858       }
01859       else {
01860         Traceline("pushing 'clause' choice point for %P\n", head);
01861         push_choice_point(clause,head,body,&((*p)->next));
01862       }
01863     }
01864     
01865     if (r)
01866       push_goal(retract,p,NULL,NULL);
01867     if ((*p)->a) {
01868       clear_copy();
01869       rule_head=quote_copy((*p)->a,STACK);
01870       rule_body=quote_copy((*p)->b,STACK);
01871       
01872       push_goal(unify,body,rule_body,NULL);
01873       push_goal(unify,head,rule_head,NULL);
01874       
01875       rule_head->status=4;
01876       rule_body->status=4;
01877       
01878       i_eval_args(rule_body->attr_list);
01879       i_eval_args(rule_head->attr_list);
01880       
01881       Traceline("fetching next clause for %s\n", head->type->keyword->symbol);
01882     }
01883     else {
01884       success=FALSE;
01885       Traceline("following clause had been retracted\n");
01886     }
01887   }
01888   else if ((unsigned long)(*p)>0) {
01889     if (r)
01890       Errorline("the built-in %P cannot be retracted.\n",head);
01891     else
01892       Errorline("the definition of built-in %P is not accessible.\n",head);
01893   }
01894   
01895   return success;
01896 }
01897 
01898 
01899 /* Return TRUE iff the top choice point is a what_next choice point */
01900 /* or if there are no choice points. */
01901 long no_choices()
01902 {
01903   return (choice_stack==NULL) || (choice_stack->goal_stack->type==what_next);
01904 }
01905 
01906 
01907 /* Return the number of choice points on the choice point stack */
01908 long num_choices()
01909 {
01910   long num;
01911   ptr_choice_point cp;
01912   
01913   num=0;
01914   cp=choice_stack;
01915   while (cp) {
01916     num++;
01917     cp=cp->next;
01918   }
01919   return num;
01920 }
01921 
01922 
01923 /* Return the number of variables in the variable tree. */
01924 long num_vars(vt)
01925      ptr_node vt;
01926 {
01927   long num;
01928   
01929   return (vt?(num_vars(vt->left)+1+num_vars(vt->right)):0);
01930 }
01931 
01932 
01933 
01934 /* Cut away up to and including the first 'what_next' choice point. */
01935 long what_next_cut()
01936 {
01937   long flag=TRUE;
01938   long result=FALSE;
01939   
01940   do {
01941     if (choice_stack) {
01942       backtrack();
01943       if (goal_stack->type==what_next) {
01944         flag=FALSE;
01945         result=TRUE;
01946       }
01947     }
01948     else {
01949       /* This undo does the last undo actions before returning to top level. */
01950       /* It is not needed for variable undoing, but for actions (like */
01951       /* closing windows). */
01952       undo(NULL);
01953       /* undo(mem_base); 7.8 */
01954 #ifdef TS
01955       /* global_time_stamp=INIT_TIME_STAMP; */ /* 9.6 */
01956 #endif
01957       flag=FALSE;
01958     }
01959   } while (flag);
01960   
01961   return result;
01962 }
01963 
01964 
01965 /* UNUSED 12.7 */
01966 /* Return the choice point corresponding to the first 'what_next' */
01967 /* choice point in the choice point stack.  Return NULL if there is none. */
01968 /* This is used to ensure that cuts don't go below the most recent */
01969 /* 'what_next' choice point. */
01970 ptr_choice_point topmost_what_next()
01971 {
01972   ptr_choice_point cp=choice_stack;
01973   
01974   while (cp && cp->goal_stack && cp->goal_stack->type!=what_next)
01975     cp=cp->next;
01976   
01977   if (cp && cp->goal_stack && cp->goal_stack->type==what_next)
01978     return cp;
01979   else
01980     return (ptr_choice_point) NULL;
01981 }
01982 
01983 
01984 /* Called when level jumps back to zero.  Setting these two pointers to */
01985 /* NULL causes an exit from main_prove and will then reset all other    */
01986 /* global information. */
01987 void reset_stacks()
01988 {
01989   undo(NULL); /* 8.10 */
01990   goal_stack=NULL;
01991   choice_stack=NULL;
01992 #ifdef TS
01993   /* global_time_stamp=INIT_TIME_STAMP; */ /* 9.6 */
01994 #endif
01995 }
01996 
01997 
01998 /******** WHAT_NEXT_AIM()
01999   Find out what the user wants to do:
02000   a) retry current goal -> ';'
02001   b) quit current goal -> RETURN
02002   c) add current goal -> 'new goal ?'
02003   d) return to top level -> '.'
02004   */
02005 long what_next_aim()
02006 {
02007   long result=FALSE;
02008   ptr_psi_term s;
02009   long c, c2; /* 21.12 (prev. char) */
02010   char *pr;
02011   long sort,cut=FALSE;
02012   long level,i;
02013   long eventflag;
02014   ptr_stack save_undo_stack;
02015   
02016   begin_terminal_io();
02017   
02018   level=((unsigned long)aim->c);
02019   
02020   if (aim->a) {
02021     /* Must remember var_occurred from the what_next goal and from */
02022     /* execution of previous query (it may have contained a parse) */
02023     var_occurred=var_occurred || ((unsigned long)aim->b)&TRUEMASK; /* 18.8 */
02024     eventflag=(((unsigned long)aim->b)&(TRUEMASK*2))!=0;
02025     if (
02026         !var_occurred && no_choices() && level>0
02027 #ifdef X11
02028         /* Keep level same if no window & no X event */
02029         && !x_window_creation && !eventflag
02030 #endif
02031        ) {
02032       /* Keep level the same if in a query, the number of choice points */
02033       /* has not increased and there are no variables. */
02034       /* This has to have the same behavior as if an EOLN was typed */
02035       /* and no 'No' message should be given on the lowest level,   */
02036       level--;
02037       what_next_cut();
02038       if (level==0) { result=TRUE; }
02039     }
02040   }
02041     
02042 #ifdef X11
02043   x_window_creation=FALSE;
02044 #endif
02045   
02046   Infoline(aim->a?"\n*** Yes":"\n*** No");
02047   show_count();
02048   if (aim->a || level>0) print_variables(NOTQUIET);
02049 
02050   {
02051     long lev=(MAX_LEVEL<level?MAX_LEVEL:level);
02052     pr=prompt_buffer;
02053     /*  RM: Oct 13 1993  */
02054     if(current_module==user_module)
02055       *pr='\0';
02056     else
02057       strcpy(pr,current_module->module_name);
02058     pr += strlen(pr);
02059     for(i=1;i<=lev;i++) { *pr='-'; pr++; *pr='-'; pr++; }
02060     if (level>0)
02061       sprintf(pr,"%ld",level);
02062     strcat(pr,PROMPT);
02063     
02064     prompt=prompt_buffer;
02065   }
02066   
02067   stdin_cleareof();
02068   /* The system waits for either an input command or an X event. */
02069   /* An X event is treated *exactly* like an input command that  */
02070   /* has the same effect. */
02071 #ifdef X11
02072   c=x_read_stdin_or_event(&eventflag);
02073   if (eventflag) {
02074     /* Include eventflag info in var_occurred field. */
02075     push_goal(what_next,TRUE,FALSE+2*TRUE,level /* +1 RM: Jun 22 1993 */);
02076     release_resid(xevent_existing);
02077     result=TRUE;
02078   }
02079   else
02080 #else
02081     c=read_char();
02082 #endif
02083   {
02084     while (c!=EOLN && c>0 && c<=32 && c!=EOF) {
02085       c=read_char();
02086     }
02087     if (c==EOF) {
02088       reset_stacks();
02089     }
02090     else if (c==EOLN) {
02091       cut=TRUE;
02092     }
02093     else if (c==';' || c=='.') {
02094       do {
02095         c2=read_char();
02096       } while (c2!=EOLN && c2!=EOF && c2>0 && c2<=32);
02097       if (c=='.') { /* 6.10 */
02098         reset_stacks();
02099         result=TRUE;
02100       }
02101     }
02102     else {
02103       if (level>0) push_choice_point(what_next,FALSE,FALSE,level);
02104   
02105       put_back_char(c);
02106       var_occurred=FALSE;
02107       save_undo_stack=undo_stack;
02108       s=stack_copy_psi_term(parse(&sort));
02109       
02110       if (s->type==eof) {
02111         reset_stacks();
02112         put_back_char(EOF);
02113       } else if (sort==QUERY) {
02114         push_goal(what_next,TRUE,var_occurred,level+1);
02115         push_goal(prove,s,DEFRULES,NULL);
02116         reset_step();
02117         result=TRUE;
02118       }
02119       else if (sort==FACT) { /* A declaration */
02120         push_goal(what_next,TRUE,FALSE,level+1); /* 18.5 */
02121         assert_first=FALSE;
02122         assert_clause(s);
02123         /* Variables in the query may be used in a declaration, */
02124         /* but the declaration may not add any variables. */
02125         undo(save_undo_stack); /* 17.8 */
02126         encode_types();
02127         result=TRUE;
02128       }
02129       else {
02130         /* Stay at same level on syntax error */
02131         push_goal(what_next,TRUE,FALSE,level+1); /* 20.8 */
02132         result=TRUE; /* 20.8 */
02133       }
02134     }
02135   }
02136 
02137   if (cut) result = what_next_cut() || result;
02138   
02139   end_terminal_io();
02140   
02141   var_occurred=FALSE;
02142   start_chrono();
02143   
02144   return result;
02145 }
02146 
02147 
02148 
02149 /******** LOAD_AIM()
02150   Continue loading a file from the current psi-term up to the next query.
02151   Files are loaded in blocks of assertions that end with a query.
02152   Such a chunk is loaded by a 'load' goal on the goal_stack.
02153   This goal contains the input file state information.  This guarantees that
02154   all queries in the input file are executed in the order they are encountered
02155   (which includes load operations).
02156 */
02157 long load_aim()
02158 {
02159   long success=TRUE,exitloop;
02160   ptr_psi_term s;
02161   long sort;
02162   char *fn;
02163   long old_noisy,old_file_date;
02164   ptr_node old_var_tree;
02165   ptr_choice_point cutpt;
02166   long old_var_occurred; /* 18.8 */
02167   int end_of_file=FALSE; /*  RM: Jan 27 1993  */
02168 
02169   
02170   save_state(input_state);
02171   input_state=(ptr_psi_term)aim->a;
02172   restore_state(input_state);
02173   old_file_date=file_date;
02174   file_date=(unsigned long)aim->b;
02175   old_noisy=noisy;
02176   noisy=FALSE;
02177   fn=(char*)aim->c;
02178   exitloop=FALSE;
02179 
02180 
02181   
02182   do {
02183     /* Variables in queries in files are *completely independent* of top- */
02184     /* level variables.  I.e.: top-level variables are *not* recognized   */
02185     /* while loading files and variables in file queries are *not* added. */
02186     old_var_occurred=var_occurred; /* 18.8 */
02187     old_var_tree=var_tree;
02188     var_tree=NULL;
02189     s=stack_copy_psi_term(parse(&sort));
02190     var_tree=old_var_tree;
02191     var_occurred=old_var_occurred; /* 18.8 */
02192 
02193     if (s->type==eof) {
02194       encode_types();
02195       if (input_stream!=stdin) fclose(input_stream);
02196       exitloop=TRUE;
02197       end_of_file=TRUE; /*  RM: Jan 27 1993  */
02198     }
02199     else if (sort==FACT) {
02200       assert_first=FALSE;
02201       assert_clause(s);
02202     }
02203     else if (sort==QUERY) {
02204       encode_types();
02205       save_state(input_state);
02206       /* Handle both successful and failing queries correctly. */
02207       cutpt=choice_stack;
02208       push_choice_point(load,input_state,file_date,fn);
02209       push_goal(load,input_state,file_date,fn);
02210       push_goal(general_cut,cutpt,NULL,NULL);
02211       push_goal(prove,s,DEFRULES,NULL);
02212       exitloop=TRUE;
02213     }
02214     else {
02215       /* fprintf(stderr,"*** Error: in input file %c%s%c.\n",34,fn,34); */
02216       /* success=FALSE; */
02217       /* fail_all(); */
02218       if (input_stream!=stdin) fclose(input_stream);
02219       abort_life(TRUE);
02220       /* printf("\n*** Abort\n"); */
02221       /* main_loop_ok=FALSE; */
02222     }
02223   } while (success && !exitloop);
02224 
02225 
02226   /*  RM: Jan 27 1993 */
02227   if(end_of_file || !success) {
02228     /*
02229       printf("END OF FILE %s, setting module to %s\n",
02230       ((ptr_psi_term)get_attr(input_state,
02231       INPUT_FILE_NAME))->value,
02232       ((ptr_psi_term)get_attr(input_state,
02233       CURRENT_MODULE))->value);
02234       */
02235            
02236     set_current_module(
02237        find_module(((ptr_psi_term)get_attr(input_state,
02238        CURRENT_MODULE))->value));
02239   }
02240 
02241   
02242   noisy=old_noisy;
02243   file_date=old_file_date;
02244   open_input_file("stdin");
02245 
02246   
02247   return success;
02248 }
02249 
02250 
02251 
02252 /******** MAIN_PROVE()
02253   This is the inference engine.  It distributes sub-goals to the appropriate
02254   routines.  It deals with backtracking.  It fails if there is not enough
02255   memory available or if there is an interrupt that causes the current query
02256   to be aborted. 
02257 */
02258 void main_prove()
02259 {
02260   long success=TRUE;
02261   ptr_pair_list *p;
02262   ptr_psi_term unused_match_date; /* 13.6 */
02263     
02264   xcount=0;
02265   xeventdelay=XEVENTDELAY;
02266   interrupted=FALSE;
02267   main_loop_ok=TRUE;
02268   
02269   while (main_loop_ok && goal_stack) {
02270 
02271     /*  RM: Oct 28 1993  For debugging a horrible mess.
02272     { 
02273       ptr_choice_point c=choice_stack;
02274       while(c) {
02275         if((GENERIC)stack_pointer<(GENERIC)c) {
02276           printf("########### Choice stack corrupted! %x\n",c);
02277           trace=TRUE;
02278           c=NULL;
02279         }
02280         else
02281           c=c->next;
02282       }
02283     }
02284     */
02285 
02286     
02287     aim=goal_stack;
02288     switch(aim->type) {
02289       
02290     case unify:
02291       goal_stack=aim->next;
02292       goal_count++;
02293       success=unify_aim();
02294       break;
02295       
02296     /* Same as above, but do not evaluate top level */
02297     /* Used to bind with unbound variables */
02298     case unify_noeval:
02299       goal_stack=aim->next;
02300       goal_count++;
02301       success=unify_aim_noeval();
02302       break;
02303       
02304     case prove:
02305       success=prove_aim();
02306       break;
02307       
02308     case eval:
02309       goal_stack=aim->next;
02310       goal_count++;
02311       success=eval_aim();
02312       break;
02313 
02314     case load:
02315       goal_stack=aim->next;
02316       goal_count++;
02317       success=load_aim();
02318       break;
02319       
02320     case match:
02321       goal_stack=aim->next;
02322       goal_count++;
02323       success=match_aim();
02324       break;
02325       
02326     case disj:
02327       goal_stack=aim->next;
02328       goal_count++;
02329       success=disjunct_aim();
02330       break;
02331 
02332     case general_cut:
02333       goal_stack=aim->next;
02334       goal_count++;
02335       /* assert((ptr_choice_point)aim->a <= choice_stack); 12.7 */
02336       /* choice_stack=(ptr_choice_point)aim->a; */
02337       cut_to(aim->a); /* 12.7 */
02338 #ifdef CLEAN_TRAIL
02339       clean_trail(choice_stack);
02340 #endif
02341 #ifdef TS
02342       /* RESTORE_TIME_STAMP; */ /* 9.6 */
02343 #endif
02344       break;
02345       
02346     case eval_cut:
02347       /* RESID */ restore_resid((ptr_resid_block)aim->c, &unused_match_date);
02348       if (curried)
02349         do_currying();
02350       else if (resid_vars) {
02351         success=do_residuation_user(); /* 21.9 */ /* PVR 9.2.94 */
02352       } else {
02353         if (resid_aim)
02354           Traceline("result of %P is %P\n", resid_aim->a, aim->a);
02355         goal_stack=aim->next;
02356         goal_count++;
02357         /* resid_aim=NULL; 21.9 */
02358         /* PVR 5.11 choice_stack=(ptr_choice_point)aim->b; */
02359         i_check_out(aim->a);
02360       }
02361       resid_aim=NULL; /* 21.9 */
02362       resid_vars=NULL; /* 22.9 */
02363       /* assert((ptr_choice_point)aim->b<=choice_stack); 12.7 */
02364       /* PVR 5.11 */ /* choice_stack=(ptr_choice_point)aim->b; */
02365       if (success) { /* 21.9 */
02366         cut_to(aim->b); /* 12.7 */
02367 #ifdef CLEAN_TRAIL
02368         clean_trail(choice_stack);
02369 #endif
02370         /* match_date=NULL; */ /* 13.6 */
02371 #ifdef TS
02372         /* RESTORE_TIME_STAMP; */ /* 9.6 */
02373 #endif
02374       }
02375       break;
02376       
02377     case freeze_cut:
02378       /* RESID */ restore_resid((ptr_resid_block)aim->c, &unused_match_date);
02379       if (curried) {
02380         Warningline("frozen goal has a missing parameter '%P' and fails.\n",aim->a);
02381         success=FALSE;
02382       }
02383       else if (resid_vars) {
02384         success=do_residuation_user(); /* 21.9 */ /* PVR 9.2.94 */
02385       } else {
02386         if (resid_aim) Traceline("releasing frozen goal: %P\n", aim->a);
02387         /* resid_aim=NULL; 21.9 */
02388         /* PVR 5.12 choice_stack=(ptr_choice_point)aim->b; */
02389         goal_stack=aim->next;
02390         goal_count++;
02391       }
02392       resid_aim=NULL; /* 21.9 */
02393       resid_vars=NULL; /* 22.9 */
02394       if (success) { /* 21.9 */
02395         /* assert((ptr_choice_point)aim->b<=choice_stack); 12.7 */
02396         /* PVR 5.12 */ /* choice_stack=(ptr_choice_point)aim->b; */
02397         cut_to(aim->b); /* 12.7 */
02398 #ifdef CLEAN_TRAIL
02399         clean_trail(choice_stack);
02400 #endif
02401         /* match_date=NULL; */ /* 13.6 */
02402 #ifdef TS
02403         /* RESTORE_TIME_STAMP; */ /* 9.6 */
02404 #endif
02405       }
02406       break;
02407       
02408     case implies_cut: /* 12.10 */
02409       /* This 'cut' is actually more like a no-op! */
02410       restore_resid((ptr_resid_block)aim->c, &unused_match_date);
02411       if (curried) {
02412         Warningline("implied goal has a missing parameter '%P' and fails.\n",aim->a);
02413         success=FALSE;
02414       }
02415       else if (resid_vars)
02416         success=FALSE;
02417       else {
02418         if (resid_aim) Traceline("executing implied goal: %P\n", aim->a);
02419         goal_stack=aim->next;
02420         goal_count++;
02421       }
02422       resid_aim=NULL; /* 21.9 */
02423       resid_vars=NULL; /* 22.9 */
02424       break;
02425 
02426     case fail:
02427       goal_stack=aim->next;
02428       success=FALSE;
02429       break;
02430       
02431     case what_next:
02432       goal_stack=aim->next;
02433       success=what_next_aim();
02434       break;
02435       
02436     case type_disj:
02437       goal_stack=aim->next;
02438       goal_count++;
02439       type_disj_aim();
02440       break;
02441       
02442     case clause:
02443       goal_stack=aim->next;
02444       goal_count++;
02445       success=clause_aim(0);
02446       break;
02447       
02448     case del_clause:
02449       goal_stack=aim->next;
02450       goal_count++;
02451       success=clause_aim(1);
02452       break;
02453       
02454     case retract:
02455       goal_stack=aim->next;
02456       goal_count++;
02457       p=(ptr_pair_list*)aim->a;
02458       Traceline("deleting clause (%P%s%P)\n",
02459                 (*p)->a,((*p)->a->type->type==function?"->":":-"),(*p)->b);
02460       (*p)->a=NULL;
02461       (*p)->b=NULL;
02462       (*p)=(*p)->next; /* Remove retracted element from pairlist */
02463       break;
02464 
02465     case c_what_next: /*  RM: Mar 31 1993  */
02466       main_loop_ok=FALSE; /* Exit the main loop */
02467       break;
02468       
02469     default:
02470       Errorline("bad goal on stack %d.\n",goal_stack->type);
02471       goal_stack=aim->next;
02472     }
02473 
02474     if (main_loop_ok) {
02475     
02476       if (success) {
02477 
02478 #ifdef X11
02479         /* Polling on external events */
02480         if (xcount<=0 && aim->type==prove) {
02481           if (x_exist_event()) {
02482             /* printf("At event, xeventdelay = %ld.\n",xeventdelay); */
02483             xeventdelay=0;
02484             release_resid(xevent_existing);
02485           } else {
02486             if (xeventdelay<XEVENTDELAY)
02487               /* If XEVENTDELAY=1000 it takes 90000 goals to get back */
02488               /* from 100 at the pace of 1%. */
02489               xeventdelay=(xeventdelay*101)/100+2;
02490             else
02491               xeventdelay=XEVENTDELAY;
02492           }
02493           xcount=xeventdelay;
02494         }
02495         else
02496           xcount--;
02497 #endif
02498         
02499       }
02500       else {
02501         if (choice_stack) {
02502           backtrack();
02503           Traceline("backtracking\n");
02504           success=TRUE;
02505         }
02506         else /* if (goal_stack) */ {
02507           undo(NULL); /* 8.10 */
02508           Infoline("\n*** No");
02509           /* printf("\n*** No (in main_prove)."); */
02510           show_count();
02511 #ifdef TS
02512           /* global_time_stamp=INIT_TIME_STAMP; */ /* 9.6 */
02513 #endif
02514           main_loop_ok=FALSE;
02515         }
02516       }
02517       
02518       if (heap_pointer-stack_pointer < GC_THRESHOLD)
02519         memory_check();
02520       
02521       if (interrupted || (stepflag && steptrace))
02522         handle_interrupt();
02523       else if (stepcount>0) {
02524         stepcount--;
02525         if (stepcount==0 && !stepflag) {
02526           stepflag=TRUE;
02527           handle_interrupt();
02528         }
02529       }
02530     }
02531   }
02532 }
02533 
02534 
02535 int dummy_printf(f,s,t)
02536      
02537      char *f, *s, *t;
02538 {
02539   return strlen(f);
02540 }

Generated on Sat Jan 26 08:48:07 2008 for WildLife by  doxygen 1.5.4