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

Go to the documentation of this file.
00001 /* Copyright 1991 Digital Equipment Corporation.
00002 ** All Rights Reserved.
00003 *****************************************************************/
00004 /*      $Id: lefun.c,v 1.4 1995/01/14 00:24:55 duchier Exp $     */
00005 
00006 #ifndef lint
00007 static char vcid[] = "$Id: lefun.c,v 1.4 1995/01/14 00:24:55 duchier Exp $";
00008 #endif /* lint */
00009 
00010 #include "extern.h"
00011 #include "login.h"
00012 #include "copy.h"
00013 #include "trees.h"
00014 #include "parser.h"
00015 #include "print.h"
00016 #include "lefun.h"
00017 #include "token.h"
00018 
00019 
00020 ptr_goal resid_aim;
00021 ptr_resid_list resid_vars; /* 21.9 */
00022 /* ptr_goal resid_limit; 12.6 */
00023 
00024 long curried;
00025 long can_curry;
00026 
00027 /* ptr_psi_term match_date; 13.6 */
00028 /* ptr_choice_point cut_point; 13.6 */
00029 
00030 static long attr_missing;
00031 static long check_func_flag;
00032 
00033 void eval_global_var(); /*  RM: Feb 10 1993  */
00034 
00035 
00036 /* Create a new psi_term on the stack with value '@' (top) and no attributes. */
00037 ptr_psi_term stack_psi_term(stat)
00038 long stat;
00039 {
00040   ptr_psi_term result;
00041 
00042   result=STACK_ALLOC(psi_term);
00043   result->type=top;
00044   result->status=stat;
00045   result->flags=stat?QUOTED_TRUE:FALSE; /* 14.9 */
00046   result->attr_list=NULL;
00047   result->coref=NULL;
00048 #ifdef TS
00049   result->time_stamp=global_time_stamp; /* 9.6 */
00050 #endif
00051   result->resid=NULL;
00052   result->value=NULL;
00053 
00054   return result;
00055 }
00056 
00057 
00058 
00059 /* Create a new psi_term on the stack with a real number value. */
00060 ptr_psi_term real_stack_psi_term(stat,thereal)
00061 long stat;
00062 REAL thereal;
00063 {
00064   ptr_psi_term result;
00065 
00066   result=STACK_ALLOC(psi_term);
00067   result->type = (thereal==floor(thereal)) ? integer : real;
00068   result->status=stat;
00069   result->flags=stat?QUOTED_TRUE:FALSE; /* 14.9 */
00070   result->attr_list=NULL;
00071   result->coref=NULL;
00072 #ifdef TS
00073   result->time_stamp=global_time_stamp; /* 9.6 */
00074 #endif
00075   result->resid=NULL;
00076   result->value=(GENERIC)heap_alloc(sizeof(REAL));
00077   (* (REAL *)(result->value)) = thereal;
00078 
00079   return result;
00080 }
00081 
00082 
00083 
00084 /* Create a new psi_term on the heap with value '@' (top) and no attributes. */
00085 ptr_psi_term heap_psi_term(stat)
00086 long stat;
00087 {
00088   ptr_psi_term result;
00089 
00090   result=HEAP_ALLOC(psi_term);
00091   result->type=top;
00092   result->status=stat;
00093   result->flags=stat?QUOTED_TRUE:FALSE; /* 14.9 */
00094   result->attr_list=NULL;
00095   result->coref=NULL;
00096 #ifdef TS
00097   result->time_stamp=global_time_stamp; /* 9.6 */
00098 #endif
00099   result->resid=NULL;
00100   result->value=NULL;
00101 
00102   return result;
00103 }
00104 
00105 
00106 
00107 /* Create an empty list on the stack,  wiped out by RM: Dec 14 1992  */
00108 /* ptr_psi_term stack_empty_list()  is now aliased to stack_nil()    */
00109 
00110 
00111 
00112 /******** RESIDUATE_DOUBLE(t,u)
00113   Residuate the current expression with T in the Residuation Variable set.
00114   Also store the other variable, so that its sort can be used in the
00115   'bestsort' calculation needed to implement disequality constraints.
00116 */
00117 void residuate_double(t,u) /* 21.9 */
00118 ptr_psi_term t,u;
00119 {
00120   ptr_resid_list curr;
00121 
00122   curr=STACK_ALLOC(resid_list);
00123   curr->var=t;
00124   curr->othervar=u;
00125   curr->next=resid_vars;
00126   resid_vars=curr;
00127 }
00128 
00129 
00130 
00131 
00132 /******** RESIDUATE(t)
00133   Residuate the current expression with T in the Residuation Variable set.
00134 */
00135 void residuate(t)
00136 ptr_psi_term t;
00137 {
00138   ptr_resid_list curr;
00139 
00140   curr=STACK_ALLOC(resid_list);
00141   curr->var=t;
00142   curr->othervar=NULL; /* 21.9 */
00143   curr->next=resid_vars;
00144   resid_vars=curr;
00145 }
00146 
00147 
00148 
00149 /******** RESIDUATE2(u,v)
00150   Residuate the current function on the two variables U and V.
00151 */
00152 void residuate2(u,v)
00153 ptr_psi_term u,v;
00154 {
00155   residuate(u);
00156   if (v && u!=v) residuate(v);
00157 }
00158 
00159 
00160 
00161 /******** RESIDUATE3(u,v,w)
00162   Residuate the current function on the three variables U, V, and W.
00163 */
00164 void residuate3(u,v,w)
00165 ptr_psi_term u,v,w;
00166 {
00167   residuate(u);
00168   if (v && u!=v) residuate(v);
00169   if (w && u!=w && v!=w) residuate(w);
00170 } 
00171 
00172 
00173 
00174 /******** CURRY()
00175   Decide that the current function will have to be curried.
00176   This has become so simple it could be a MACRO.
00177   The real work is done by DO_CURRY.
00178 */
00179 void curry()
00180 {
00181   if (can_curry)
00182     curried=TRUE;
00183 }
00184 
00185 
00186 
00187 
00188 /******** RESIDUATEGOALONVAR(g,var,othervar)
00189   Add the goal to the variable's residuation list.
00190   Also update the residuation's 'bestsort' field if it exists (needed to
00191   implement complete disequality semantics).  The 'othervar' parameter
00192   is needed for this.
00193 */
00194 long residuateGoalOnVar(g, var, othervar)
00195 ptr_goal g;
00196 ptr_psi_term var,othervar;
00197 {
00198   long result;
00199   long resflag,resflag2;
00200   GENERIC rescode,rescode2,resvalue,resvalue2;
00201   /* Set to FALSE if the goal is already residuated on the var: */
00202   long not_found = TRUE;
00203   /* Points to a pointer to a residuation structure.  Used so we can */
00204   /* add the goal to the end of the residuation list, so that it can */
00205   /* can be undone later if backtracking happens.  See the call to   */
00206   /* push_ptr_value.  */
00207   ptr_residuation *r;
00208     
00209   /* 5.8 PVR */
00210   if ((GENERIC)var>=heap_pointer) {
00211     Errorline("attempt to residuate on psi-term %P in the heap.\n",var);
00212 
00213     return FALSE;
00214   }
00215 
00216   r= &(var->resid);
00217     
00218   while (not_found && *r) {
00219     if ((*r)->goal == g) { /* This goal is already attached */
00220       /* Keep track of best sort so far */
00221       /* Glb_code(..) tries to keep 'sortflag' TRUE if possible. */
00222       result=glb_code((*r)->sortflag,(*r)->bestsort,
00223                       TRUE,var->type,&resflag,&rescode);
00224       result=glb_value(result,resflag,rescode,(*r)->value,var->value,
00225                        &resvalue); /* 6.10 */
00226       if (!result)
00227         return FALSE; /* 21.9 */
00228       else if (othervar) {
00229         result=glb_code(resflag,rescode,TRUE,othervar->type,
00230                         &resflag2,&rescode2);
00231         result=glb_value(result,resflag2,rescode2,resvalue,othervar->value,
00232                          &resvalue2); /* 6.10 */
00233         if (!result) {
00234           return FALSE;
00235         }
00236         else {
00237           /* The value field only has to be trailed once, since its value */
00238           /* does not change, once given. */
00239           if ((*r)->value==NULL && resvalue2!=NULL) { /* 6.10 */
00240             push_ptr_value(int_ptr,&((*r)->value));
00241           }
00242           if ((*r)->bestsort!=rescode2) {
00243             push_ptr_value(((*r)->sortflag?def_ptr:code_ptr),
00244                            &((*r)->bestsort));
00245             (*r)->bestsort=rescode2; /* 21.9 */
00246           }
00247           if ((*r)->sortflag!=resflag2) {
00248             push_ptr_value(int_ptr,&((*r)->sortflag));
00249             (*r)->sortflag=resflag2; /* 21.9 */
00250           }
00251         }
00252       }
00253       else {
00254         if ((*r)->value==NULL && resvalue!=NULL) { /* 6.10 */
00255           push_ptr_value(int_ptr,&((*r)->value));
00256         }
00257         if ((*r)->bestsort!=rescode) {
00258           push_ptr_value(((*r)->sortflag?def_ptr:code_ptr),
00259                          &((*r)->bestsort));
00260           (*r)->bestsort=rescode; /* 21.9 */
00261         }
00262         if ((*r)->sortflag!=resflag) {
00263           push_ptr_value(int_ptr,&((*r)->sortflag));
00264           (*r)->sortflag=resflag; /* 21.9 */
00265         }
00266       }
00267       not_found = FALSE;
00268     }
00269     else
00270       r= &((*r)->next);  /* look at the next one */
00271   }
00272   
00273   if (not_found) {
00274     /* We must attach this goal & the variable's sort onto this variable */
00275     
00276     push_ptr_value(resid_ptr,r);
00277     *r=STACK_ALLOC(residuation);
00278     if (othervar) {
00279       result=glb_code(TRUE,var->type,TRUE,othervar->type,&resflag,&rescode);
00280       result=glb_value(result,resflag,rescode,var->value,othervar->value,
00281                        &resvalue); /* 6.10 */
00282       if (!result) {
00283         return FALSE;
00284       }
00285       else {
00286         (*r)->sortflag=resflag;
00287         (*r)->bestsort=rescode; /* 21.9 */
00288         (*r)->value=resvalue; /* 6.10 */
00289       }
00290     }
00291     else {
00292       (*r)->sortflag=TRUE;
00293       (*r)->bestsort=(GENERIC)var->type; /* 21.9 */
00294       (*r)->value=(GENERIC)var->value; /* 6.10 */
00295     }
00296     (*r)->goal=g;
00297     (*r)->next=NULL;
00298   }
00299   
00300   if (!(g->pending)) {
00301     /* this goal is not pending, so make sure it will be put on the goal
00302      * stack later
00303      */
00304     push_ptr_value(int_ptr,&(g->pending));
00305     g->pending=TRUE;
00306   }
00307   
00308   return TRUE; /* 21.9 */
00309 }
00310 
00311 
00312 
00313 /******** DO_RESIDUATION()
00314   Undo anything that matching may have done, then
00315   create a residuated expression. Check that the same constraint does not
00316   hang several times on the same variable.
00317 
00318   This routine takes time proportional to the square of the number of
00319   residuations.  This is too slow; eventually it should be sped up, 
00320   especially if equality constraints are often used.
00321 */
00322 long do_residuation(); /* forward declaration */
00323 
00324 /* LIFE-defined routines reset the goal stack to what it was */
00325 /* before the function call. */
00326 long do_residuation_user()
00327 {
00328   goal_stack=resid_aim->next; /* reset goal stack */
00329   return do_residuation();
00330 }
00331 
00332 /* C-defined routines do all stack manipulation themselves */
00333 long do_residuation()
00334 {
00335   long success;
00336   ptr_psi_term t,u;
00337   ptr_goal *gs;
00338   
00339   /* This undoes perfectly valid work! */
00340   /* The old version of Wild_Life did not trail anything
00341      during matching, so I think this was a nop for it. */
00342   /* PVR 11.5 undo(resid_limit); */
00343   /* PVR 11.5 choice_stack=cut_point; */
00344 
00345   /* PVR 9.2.94 */
00346   /* goal_stack=resid_aim->next; */
00347 
00348   if (trace) {
00349     tracing();
00350     print_resid_message(resid_aim->a,resid_vars);
00351   }
00352 
00353   while (resid_vars) {
00354     
00355     t=resid_vars->var; /* 21.9 */
00356     u=resid_vars->othervar; /* 21.9 */
00357     /* PVR */ deref_ptr(t);
00358     resid_vars=resid_vars->next;
00359     Traceline("residuating on %P (other = %P)\n",t,u);
00360     
00361     success=residuateGoalOnVar(resid_aim, t, u); /* 21.9 */
00362     if (!success) { /* 21.9 */
00363       Traceline("failure because of disentailment\n");
00364       return FALSE;
00365     }
00366   }
00367   
00368   Traceline("no failure because of disentailment\n");
00369   return TRUE; /* 21.9 */
00370 }
00371 
00372 
00373 
00374 /********* DO_CURRYING()
00375   This performs CURRYing: all that needs to be done is to yield the calling
00376   term as the result after having given up on evaluation. In effect the calling
00377   psi-term is left intact.
00378 */
00379 void do_currying()
00380 {
00381   ptr_psi_term funct,result;
00382 
00383   /* PVR 5.11 undo(resid_limit); */
00384   /* PVR 5.11 choice_stack=cut_point; */
00385   goal_stack=resid_aim->next;
00386   funct=(ptr_psi_term )resid_aim->a;
00387   result=(ptr_psi_term )resid_aim->b;
00388     
00389   Traceline("currying %P\n",funct);
00390    
00391   push_goal(unify_noeval,funct,result,NULL);
00392   resid_aim=NULL;
00393 }
00394 
00395 
00396 
00397 /******** RELEASE_RESID(t)
00398   Release the residuations pending on the Residuation Variable T.
00399   This is done by simply pushing the residuated goals onto the goal-stack.
00400   A goal is not added if already present on the stack.
00401   Two versions of this routine exist: one which trails t and one which never
00402   trails t.
00403 */
00404 void release_resid_main(t,trailflag)
00405 ptr_psi_term t;
00406 long trailflag;
00407 {
00408   ptr_goal g;
00409   ptr_residuation r;
00410   
00411   if (r=t->resid) {
00412     if (trailflag) push_ptr_value(resid_ptr,&(t->resid));
00413     t->resid=NULL;
00414     
00415     while (r) {
00416       g=r->goal;
00417       if (g->pending) {
00418         
00419         push_ptr_value(int_ptr,&(g->pending));
00420         g->pending=FALSE;
00421         
00422         push_ptr_value(goal_ptr,&(g->next));
00423         
00424         g->next=goal_stack;
00425         goal_stack=g;
00426         
00427         Traceline("releasing %P\n",g->a);
00428       }
00429       r=r->next;
00430     }
00431   }
00432 }
00433 
00434 void release_resid(t)
00435 ptr_psi_term t;
00436 {
00437   release_resid_main(t,TRUE);
00438 }
00439 
00440 void release_resid_notrail(t)
00441 ptr_psi_term t;
00442 {
00443   release_resid_main(t,FALSE);
00444 }
00445 
00446 
00447 
00448 /******** APPEND_RESID(u,v)
00449   Append the residuations pending on V to U. This routine does not check that
00450   the same constraint is not present twice in the end on U. This doesn't matter
00451   since RELEASE_RESID ensures that the same constraint is not released more
00452   than once.
00453 */
00454 void append_resid(u,v)
00455 ptr_psi_term u,v;
00456 {
00457   ptr_residuation *g;
00458   
00459   g= &(u->resid);
00460   while (*g)
00461     g = &((*g)->next);
00462   
00463   push_ptr_value(resid_ptr,g);
00464   *g=v->resid;
00465 }
00466 
00467 
00468 
00469 /******** EVAL_AIM()
00470   Evaluate a function.
00471   This copies the current definition of the function and
00472   stacking the various goals that are necessary to evaluate the function
00473   correctly.
00474   It creates an extra psi-term (with value top) in which to write the result.
00475 */
00476 long eval_aim()
00477 {
00478   long success=TRUE;
00479   ptr_psi_term funct,result,head,body;
00480   ptr_pair_list rule;
00481   /* RESID */ ptr_resid_block rb;
00482   ptr_choice_point cutpt;
00483   ptr_psi_term match_date; /* 13.6 */
00484   
00485   funct=(ptr_psi_term )aim->a;
00486   deref_ptr(funct);
00487 
00488   /*  RM: Jun 18 1993  */
00489   push2_ptr_value(int_ptr,&(funct->status),(funct->status & SMASK));
00490   funct->status=4;
00491 
00492   
00493   /* if (!funct->type->evaluate_args) mark_quote(funct); 25.8 */ /* 18.2 PVR */
00494   result=(ptr_psi_term )aim->b;
00495   rule=(ptr_pair_list )aim->c;
00496 
00497   match_date=(ptr_psi_term )stack_pointer;
00498   cutpt=choice_stack; /* 13.6 */
00499 
00500   /* For currying and residuation */
00501   curried=FALSE;
00502   can_curry=TRUE;
00503   /* resid_aim=aim; */
00504   resid_vars=NULL;
00505   /* resid_limit=(ptr_goal )stack_pointer; 12.6 */
00506       
00507   if (rule) {
00508     Traceline("evaluate %P\n",funct);
00509     if ((unsigned long)rule<=MAX_BUILT_INS) {
00510       
00511       resid_aim=aim;
00512       success=c_rule[(unsigned long)rule]();
00513 
00514       if (curried)
00515         do_currying();
00516       else
00517         if (resid_vars)
00518           success=do_residuation(); /* 21.9 */
00519         else {
00520           /* resid_aim=NULL; */
00521         }
00522     }
00523     else {
00524       while (rule && (rule->a==NULL || rule->b==NULL)) {
00525         rule=rule->next;
00526         Traceline("alternative rule has been retracted\n");
00527       }
00528       if (rule) {
00529         /* push_choice_point(eval,funct,result,rule->next); */ /* 17.6 */
00530 
00531         resid_aim=aim;
00532         /* RESID */ rb = STACK_ALLOC(resid_block);
00533         /* RESID */ save_resid(rb,match_date);
00534         /* RESID */ /* resid_aim = NULL; */
00535 
00536         clear_copy();
00537 
00538         /*  RM: Jun 18 1993: no functions in head */
00539         /*  if (TRUE)
00540             head=eval_copy(rule->a,STACK);
00541             else */
00542         
00543         head=quote_copy(rule->a,STACK);
00544         body=eval_copy(rule->b,STACK);
00545         head->status=4;
00546         
00547         if (rule->next) /* 17.6 */
00548           push_choice_point(eval,funct,result,rule->next);
00549 
00550         push_goal(unify,body,result,NULL);
00551         /* RESID */ push_goal(eval_cut,body,cutpt,rb); /* 13.6 */
00552         /* RESID */ push_goal(match,funct,head,rb);
00553         /* eval_args(head->attr_list); */
00554       }
00555       else {
00556         success=FALSE;
00557         /* resid_aim=NULL; */
00558       }
00559     }
00560   }
00561   else {
00562     success=FALSE;
00563     /* resid_aim=NULL; */
00564   }
00565   resid_aim=NULL;
00566   /* match_date=NULL; */ /* 13.6 */
00567   return success;
00568 }
00569 
00570 
00571 
00572 /* Match the corresponding arguments */
00573 /* RESID */ match_attr1(u,v,rb)
00574 ptr_node *u,v;
00575 /* RESID */ ptr_resid_block rb;
00576 {
00577   long cmp;
00578   ptr_node temp;
00579   
00580   if (v) {
00581     if (*u==NULL)
00582       attr_missing=TRUE;
00583     else {
00584       cmp=featcmp((*u)->key,v->key);
00585       if(cmp==0) {
00586         ptr_psi_term t;
00587         /* RESID */ match_attr1(&((*u)->right),v->right,rb);
00588         t = (ptr_psi_term) (*u)->data;
00589         /* RESID */ push_goal(match,(*u)->data,v->data,rb);
00590         /* deref2_eval(t); */
00591         /* RESID */ match_attr1(&((*u)->left),v->left,rb);
00592       }
00593       else if (cmp>0) {
00594         temp=v->right;
00595         v->right=NULL;
00596         /* RESID */ match_attr1(u,temp,rb);
00597         /* RESID */ match_attr1(&((*u)->left),v,rb);
00598         v->right=temp;
00599       }
00600       else {
00601         temp=v->left;
00602         v->left=NULL;
00603         /* RESID */ match_attr1(&((*u)->right),v,rb);
00604         /* RESID */ match_attr1(u,temp,rb);
00605         v->left=temp;
00606       }
00607     }
00608   }
00609 }
00610 
00611 
00612 /* Evaluate the lone arguments (for lazy failure + eager success) */
00613 /* RESID */ match_attr2(u,v,rb)
00614 ptr_node *u,v;
00615 /* RESID */ ptr_resid_block rb;
00616 {
00617   long cmp;
00618   ptr_node temp;
00619   
00620   if (v) {
00621     if (*u==NULL) { /* PVR 12.03 */
00622       ptr_psi_term t;
00623       match_attr1(u,v->right,rb);
00624       t = (ptr_psi_term) v->data;
00625       deref2_rec_eval(t);
00626       match_attr1(u,v->left,rb);
00627     }
00628     else {
00629       cmp=featcmp((*u)->key,v->key);
00630       if(cmp==0) {
00631         /* RESID */ match_attr2(&((*u)->right),v->right,rb);
00632         /* RESID */ match_attr2(&((*u)->left),v->left,rb);
00633       }
00634       else if (cmp>0) {
00635         temp=v->right;
00636         v->right=NULL;
00637         /* RESID */ match_attr2(u,temp,rb);
00638         /* RESID */ match_attr2(&((*u)->left),v,rb);
00639         v->right=temp;
00640       }
00641       else {
00642         temp=v->left;
00643         v->left=NULL;
00644         /* RESID */ match_attr2(&((*u)->right),v,rb);
00645         /* RESID */ match_attr2(u,temp,rb);
00646         v->left=temp;
00647       }
00648     }
00649   }
00650   else if (*u!=NULL) {
00651     ptr_psi_term t /* , empty */ ;
00652     match_attr1(&((*u)->right),v,rb);
00653     t = (ptr_psi_term) (*u)->data;
00654     /* Create a new psi-term to put the (useless) result: */
00655     /* This is needed so that *all* arguments of a function call */
00656     /* are evaluated, which avoids incorrect 'Yes' answers.      */
00657     deref2_rec_eval(t); /* Assumes goal_stack is already restored. */
00658     match_attr1(&((*u)->left),v,rb);
00659   }
00660 }
00661 
00662 
00663 /* Evaluate the corresponding arguments */
00664 /* RESID */ match_attr3(u,v,rb)
00665 ptr_node *u,v;
00666 /* RESID */ ptr_resid_block rb;
00667 {
00668   long cmp;
00669   ptr_node temp;
00670   
00671   if (v) {
00672     if (*u==NULL)
00673       attr_missing=TRUE;
00674     else {
00675       cmp=featcmp((*u)->key,v->key);
00676       if(cmp==0) {
00677         ptr_psi_term t1,t2;
00678         /* RESID */ match_attr3(&((*u)->right),v->right,rb);
00679         t1 = (ptr_psi_term) (*u)->data;
00680         t2 = (ptr_psi_term) v->data;
00681         /* RESID */ /* push_goal(match,(*u)->data,v->data,rb); */
00682         deref2_eval(t1); /* Assumes goal_stack is already restored. */
00683         deref2_eval(t2); /* PVR 12.03 */
00684         /* RESID */ match_attr3(&((*u)->left),v->left,rb);
00685       }
00686       else if (cmp>0) {
00687         temp=v->right;
00688         v->right=NULL;
00689         /* RESID */ match_attr3(u,temp,rb);
00690         /* RESID */ match_attr3(&((*u)->left),v,rb);
00691         v->right=temp;
00692       }
00693       else {
00694         temp=v->left;
00695         v->left=NULL;
00696         /* RESID */ match_attr3(&((*u)->right),v,rb);
00697         /* RESID */ match_attr3(u,temp,rb);
00698         v->left=temp;
00699       }
00700     }
00701   }
00702 }
00703 
00704 
00705 
00706 /******** MATCH_ATTR(u,v)
00707   Match the attribute trees of psi_terms U and V.
00708   If V has an attribute that U doesn't then curry.
00709   U is the calling term, V is the definition.
00710   This routine is careful to push nested eval and match goals in
00711   descending order of feature names.
00712 */
00713 void match_attr(u,v,rb)
00714 ptr_node *u,v;
00715 ptr_resid_block rb;
00716 {
00717   match_attr1(u,v,rb); /* Match corresponding arguments (third) */
00718   match_attr2(u,v,rb); /* Evaluate lone arguments (second) */
00719   match_attr3(u,v,rb); /* Evaluate corresponding arguments (first) */
00720 }
00721 
00722 
00723 
00724 
00725 
00726 /******** MATCH_AIM()
00727   This is very similar to UNIFY_AIM, only matching cannot modify the calling
00728   psi_term.   The first argument is the calling term (which may not be changed)
00729   and the second argument is the function definition (which may be changed).
00730   Residuate the expression if the calling term is more general than the
00731   function definition.
00732 */
00733 long match_aim()
00734 {
00735   long success=TRUE;
00736   ptr_psi_term u,v,tmp;
00737   REAL r;
00738   long less,lesseq;
00739   ptr_resid_block rb;
00740   ptr_psi_term match_date;
00741   
00742   u=(ptr_psi_term )aim->a;
00743   v=(ptr_psi_term )aim->b;
00744   deref_ptr(u);
00745   deref_ptr(v);
00746   rb=(ptr_resid_block)aim->c;
00747   restore_resid(rb,&match_date);
00748   
00749   if (u!=v) {
00750     if (success=matches(u->type,v->type,&lesseq)) {
00751       if (lesseq) {
00752         if (u->type!=cut || v->type!=cut) { /* Ignore value field for cut! */
00753           if (v->value) {
00754             if (u->value) {
00755               if (overlap_type(v->type,real))
00756                 success=(*((REAL *)u->value)==(*((REAL *)v->value)));
00757               else if (overlap_type(v->type,quoted_string))
00758                 success=(strcmp((char *)u->value,(char *)v->value)==0);
00759               /* DENYS: BYTEDATA */
00760               else if (overlap_type(v->type,sys_bytedata)) {
00761                 unsigned long ulen = *((unsigned long *) u->value);
00762                 unsigned long vlen = *((unsigned long *) v->value);
00763                 success=(ulen==vlen && bcmp((char *)u->value,(char *)v->value,ulen)==0);
00764               }
00765             }
00766             else
00767               residuate_double(u,v);
00768           }
00769         }
00770       }
00771       else if (u->value) {
00772         /* Here we have U <| V but U and V have values which cannot match. */
00773         success=TRUE;
00774           
00775         if (v->value) {
00776           if (overlap_type(v->type,real))
00777             success=(*((REAL *)u->value)==(*((REAL *)v->value)));
00778         }
00779         else if (overlap_type(u->type,integer)) {
00780           r= *((REAL *)u->value);
00781           success=(r==floor(r));
00782         }
00783           
00784         if (success) residuate_double(u,v);
00785       } 
00786       else
00787         residuate_double(u,v);
00788                   
00789       if (success) {
00790         if (FUNC_ARG(u) && FUNC_ARG(v)) { /*  RM: Feb 10 1993  */
00791           /* residuate2(u,v); 21.9 */
00792           residuate_double(u,v); /* 21.9 */
00793           residuate_double(v,u); /* 21.9 */
00794         }
00795         else if (FUNC_ARG(v)) {  /*  RM: Feb 10 1993  */
00796           residuate_double(v,u); /* 21.9 */
00797         }
00798         else {
00799           v->coref=u;
00800         } /* 21.9 */
00801           attr_missing=FALSE;
00802           match_attr(&(u->attr_list),v->attr_list,rb);
00803           if (attr_missing) {
00804             if (can_curry)
00805               curried=TRUE;
00806             else
00807               residuate_double(u,v);
00808           }
00809         /* } 21.9 */
00810       }
00811     }
00812   }
00813 
00814   can_curry=FALSE;
00815   save_resid(rb,match_date); /* updated resid_block */
00816   /* This should be a useless statement: */
00817   resid_aim = NULL;
00818   
00819   return success;
00820 }
00821 
00822 
00823 
00824 /******************************************************************************
00825   The following routines prepare terms for unification, proof or matching.
00826   They deal with conjunctions, disjunctions, functions and arguments which
00827   have to be examined before the general proof can continue.
00828 */
00829 
00830 
00831 
00832 /* Forward declarations */
00833 long check_out();
00834 long eval_args();
00835 
00836 
00837 
00838 /******** EVAL_ARGS(n)
00839   N is an attribute tree, the attributes must be examined, if any reveal
00840   themselves to need evaluating then return FALSE.
00841 */
00842 long i_eval_args(n)
00843 ptr_node n;
00844 {
00845   check_func_flag=FALSE;
00846   return eval_args(n);
00847 }
00848 
00849 
00850 
00851 long eval_args(n)
00852 ptr_node n;
00853 {
00854   long flag=TRUE;
00855   
00856   if (n) {
00857     flag = eval_args(n->right);
00858     flag = check_out(n->data) && flag;
00859     flag = eval_args(n->left) && flag;
00860   }
00861   
00862   return flag;
00863 }
00864 
00865 
00866 
00867 /******** CHECK_DISJ(t)
00868   Deal with disjunctions.
00869 */
00870 void check_disj(t)
00871 ptr_psi_term t;
00872 {
00873   Traceline("push disjunction goal %P\n",t);
00874   if (t->value)
00875     push_goal(disj,t,t,(GENERIC)TRUE); /* 18.2 PVR */
00876   else
00877     push_goal(fail,NULL,NULL,NULL);
00878 }
00879 
00880 
00881 
00882 /******** CHECK_FUNC(t)
00883   Deal with an unevaluated function: push an 'eval' goal for it, which will
00884   cause it to be evaluated.
00885 */
00886 void check_func(t)
00887 ptr_psi_term t;
00888 {
00889   ptr_psi_term result,t1,copy;
00890 
00891   /* Check for embedded definitions
00892      RM: Dec 16 1992  Re-instated this check then disabled it again
00893      if (resid_aim) {
00894      Errorline("embedded functions appeared in %P.\n",resid_aim->a);
00895      fail_all();
00896      }
00897      else */ {
00898     
00899     Traceline("setting up function call %P\n",t);
00900     /* Create a psi-term to put the result */
00901     result = stack_psi_term(0);
00902     
00903     /* Make a partial copy of the calling term */
00904     copy=stack_copy_psi_term(*t);
00905     copy->status &= ~RMASK;
00906   
00907     /* Bind the calling term to the result */
00908     /* push_ptr_value(psi_term_ptr,&(t->coref)); */
00909     push_psi_ptr_value(t,&(t->coref));
00910     t->coref=result;
00911 
00912     /* Evaluate the copy of the calling term */
00913     push_goal(eval,copy,result,t->type->rule);
00914   
00915     /* Avoid evaluation for built-in functions with unevaluated arguments */
00916     /* (cond and such_that) */
00917     check_func_flag=TRUE;
00918     if (t->type==iff) {
00919       get_one_arg(t->attr_list,&t1);
00920       if (t1) {
00921         /* mark_eval(t1); 24.8 */
00922         check_out(t1);
00923       }
00924     }
00925     else if(t->type==disjunction) {
00926     }
00927     else if (t->type!=such_that) {
00928       if (t->type->evaluate_args)
00929         eval_args(t->attr_list);
00930       /* else mark_quote_tree(t->attr_list); 24.8 25.8 */
00931     }
00932   }
00933 }
00934 
00935 
00936 
00937 
00938 /******** CHECK_TYPE(t)
00939   Here we deal with a type which may need checking.
00940   This routine will have to be modified to deal with the infinite loops
00941   currently caused by definitions such as:
00942 
00943   :: H:husband(spouse => wife(spouse => H)).
00944   :: W:wife(spouse => husband(spouse => W)).
00945 
00946 */
00947 long check_type(t)
00948 ptr_psi_term t;
00949 {
00950   long flag=FALSE;
00951 
00952   push2_ptr_value(int_ptr,&(t->status),(t->status & SMASK));
00953   /* push_ptr_value(int_ptr,&(t->status)); */
00954   
00955   if (t->type->properties) {
00956     if (t->attr_list || t->type->always_check) {
00957       /* Check all constraints here: */
00958       fetch_def(t, TRUE); /* PVR 18.2.94 */
00959       /* t->status=(2 & SMASK) | (t->status & RMASK); PVR 18.2.94 */
00960 
00961       eval_args(t->attr_list);
00962       flag=FALSE;
00963     }
00964     else {
00965       /* definition pending on more information */
00966       t->status= (2 & SMASK) | (t->status & RMASK);
00967       flag=TRUE;
00968     }
00969   }
00970   else {
00971     
00972     /*  RM: Dec 15 1992  I don't know what this is for
00973         if (!ovverlap_type(t->type,alist))
00974         t->status= (4 & SMASK) | (t->status & RMASK);
00975         */
00976     
00977     flag=eval_args(t->attr_list);
00978   }
00979   
00980   return flag;
00981 }
00982 
00983 
00984   
00985 /******** CHECK_OUT(t)
00986   This routine checks out psi_term T.
00987   It deals with the following cases:
00988   - T is a conjunction,
00989   - T is a type which has properties to check.
00990   - The same for T's arguments.
00991   If any of the above holds then proof has to be suspended until the
00992   case has been dealt with.  This is done by pushing goals on the goal_stack
00993   to handle the case.  If all is dealt with then CHECK_OUT returns TRUE.
00994   I.e., CHECK_OUT returns TRUE iff it has not pushed any goals on the stack.
00995 
00996   Evaluation is *not* done here, but as a part of dereferencing when a value
00997   is needed.
00998 
00999   Of all the routines related to check_out, only i_check_out, check_func,
01000   i_eval_args, and the dereference routines are called from outside of this
01001   file (lefun.c).
01002   - i_check_out(t) checks out everything except functions.  When a function
01003     is encountered, check_out returns immediately without looking inside it.
01004   - f_check_out(t) checks out functions too.
01005   - i_eval_args(n) checks out all arguments, except functions.
01006   - check_func(t) checks out a function & all its arguments (including all
01007     nested functions.  This is done as part of dereferencing, which is part
01008     of unification, matching, built-ins, and user-defined routines.
01009 */
01010 long i_check_out(t)
01011 ptr_psi_term t;
01012 {
01013   check_func_flag=FALSE;
01014   return check_out(t);
01015 }
01016 
01017 long f_check_out(t)
01018 ptr_psi_term t;
01019 {
01020   check_func_flag=TRUE;
01021   return check_out(t);
01022 }
01023 
01024 long check_out(t)
01025 ptr_psi_term t;
01026 {
01027   long flag=FALSE;
01028   
01029   deref_ptr(t);
01030 
01031   /* Traceline("PVR: entering check_out with status %d and term %P\n",
01032             t->status,t); for brunobug.lf PVR 14.2.94 */
01033 
01034   if (t->status || (GENERIC)t>=heap_pointer) /*  RM: Feb  8 1993  */
01035     flag=TRUE;
01036   else {
01037     t->status |= RMASK;
01038 
01039     switch(t->type->type) { /*  RM: Feb  8 1993  */
01040       
01041     case function:
01042       if (check_func_flag) {
01043         check_func(t);
01044         flag=TRUE;
01045       }
01046       else {
01047         /* Function evaluation handled during matching and unification */
01048         flag=TRUE;
01049       }
01050       break;
01051 
01052     case type:
01053       flag=check_type(t);
01054       break;
01055 
01056     case global: /*  RM: Feb  8 1993  */
01057       eval_global_var(t);
01058       check_out(t);
01059       flag=FALSE;
01060       break;
01061       
01062     default:
01063       flag=eval_args(t->attr_list);
01064     }
01065     t->status &= ~RMASK;
01066   }
01067   return flag;  
01068 }
01069 
01070 
01071 
01072 /********************************************************************/
01073 /*                                                                  */
01074 /* New dereference routines for Wild_Life                           */
01075 /* These routines handle evaluation-by-need.  Check_out is changed  */
01076 /* to no longer call check_func, which is done in the new routines. */
01077 /* Functions inside of psi-terms are only evaluated if needed.  It  */
01078 /* is assumed that 'needed' is true when they are derefed.          */
01079 /*                                                                  */
01080 /* There are three new dereference routines:                        */
01081 /*    deref_eval(P)                                                 */
01082 /*       If the psi-term P is a function, call check_func to        */
01083 /*       push eval goals so that the function will be evaluated.    */
01084 /*       Then return TRUE so that the caller can itself return.     */
01085 /*       This only looks at the top level.                          */
01086 /*    deref_rec(P)                                                  */
01087 /*       If the psi-term P recursively contains any functions, then */
01088 /*       push eval goals to evaluate all of them.  Set a global     */
01089 /*       variable deref_flag if this is the case.                   */
01090 /*    deref_args(P,S)                                               */
01091 /*       Same as above, except does not look at the top level or at */
01092 /*       the arguments named in the set S.                          */
01093 /*       This is needed to guarantee evaluation of all arguments of */
01094 /*       a built-in, even those not used by the built-in.           */
01095 /*                                                                  */
01096 /* The original dereference macro is renamed to:                    */
01097 /*    deref_ptr(P) = while (P->coref) P=P->coref                    */
01098 /* There are three new macros:                                      */
01099 /*    deref(P)        = deref_ptr(P);                               */
01100 /*                      if (deref_eval(P)) then return TRUE         */
01101 /*    deref_rec(P)    = deref_ptr(P);                               */
01102 /*                      if (deref_rec_eval(P)) then return TRUE     */
01103 /*    deref_args(P,S) = deref_ptr(P);                               */
01104 /*                      if (deref_args_eval(P,S)) then return TRUE  */
01105 /*                                                                  */
01106 /********************************************************************/
01107 
01108 static long deref_flag;
01109 void deref_rec_body();
01110 void deref_rec_args();
01111 void deref_rec_args_exc();
01112 
01113 /* Ensure evaluation of top of psi-term */
01114 long deref_eval(t)
01115 ptr_psi_term t;
01116 {
01117   ptr_goal save=goal_stack;
01118 
01119   deref_flag=FALSE;
01120   goal_stack=aim;
01121 
01122   if (t->status==0) {
01123     if(t->type->type==function) {
01124       check_func(t);    /* Push eval goals to evaluate the function. */
01125       deref_flag=TRUE;  /* TRUE so that caller will return to main_prove. */
01126     }
01127     else
01128       if(t->type->type==global) { /*  RM: Feb 10 1993  */
01129         eval_global_var(t);
01130         deref_ptr(t);/*  RM: Jun 25 1993  */
01131         deref_flag=deref_eval(t);
01132       }
01133       else {
01134         if (t->status!=2) {
01135           if((GENERIC)t<heap_pointer)
01136             push_ptr_value(int_ptr,&(t->status)); /*  RM: Jul 15 1993  */
01137           t->status=4;
01138           deref_flag=FALSE;
01139         }
01140       }
01141   }
01142   else
01143     deref_flag=FALSE;
01144   
01145   if (!deref_flag) goal_stack=save;
01146   return (deref_flag);
01147 }
01148 
01149 /* Ensure evaluation of *all* of psi-term */
01150 long deref_rec_eval(t)
01151 ptr_psi_term t;
01152 {
01153   ptr_goal save=goal_stack;
01154 
01155   deref_flag=FALSE;
01156   goal_stack=aim;
01157   deref_rec_body(t);
01158   if (!deref_flag) goal_stack=save;
01159   return (deref_flag);
01160 }
01161 
01162 void deref_rec_body(t)
01163 ptr_psi_term t;
01164 {
01165   if (t->status==0) {
01166     if (t->type->type==function) {
01167       check_func(t);
01168       deref_flag=TRUE;
01169     }
01170     else
01171       if(t->type->type==global) { /*  RM: Feb 10 1993  */
01172         eval_global_var(t);
01173         deref_ptr(t);/*  RM: Jun 25 1993  */
01174         deref_rec_body(t);
01175       }
01176       else {
01177         /* if (t->status!=2) Tried adding this -- PVR 9.2.94 */
01178           if((GENERIC)t<heap_pointer)
01179             push_ptr_value(int_ptr,&(t->status));/*  RM: Jul 15 1993  */
01180           t->status=4;
01181           deref_rec_args(t->attr_list);
01182       }
01183   }
01184 }
01185 
01186 void deref_rec_args(n)
01187 ptr_node n;
01188 {
01189   ptr_psi_term t1;
01190   
01191   if (n) {
01192     deref_rec_args(n->right);
01193     t1 = (ptr_psi_term) (n->data);
01194     deref_ptr(t1);
01195     deref_rec_body(t1);
01196     deref_rec_args(n->left);
01197   }
01198 }
01199 
01200 /* Same as deref_rec_eval, but doesn't look at either the top level or */
01201 /* the arguments in the set. */
01202 long deref_args_eval(t,set)
01203 ptr_psi_term t;
01204 long set;
01205 {
01206   ptr_goal save = goal_stack;
01207   ptr_goal top = aim;
01208 
01209   deref_flag = FALSE;
01210   goal_stack = top;
01211   deref_rec_args_exc(t->attr_list,set);
01212   if (!deref_flag) goal_stack = save;
01213   return (deref_flag);
01214 }
01215 
01216 /* Return TRUE iff string (considered as number) is in the set */
01217 /* This routine only recognizes the strings "1", "2", "3",     */
01218 /* represented as numbers 1, 2, 4.                             */
01219 long in_set(str,set)
01220 char *str;
01221 long set;
01222 {
01223   if (set&1 && !featcmp(str,"1")) return TRUE;
01224   if (set&2 && !featcmp(str,"2")) return TRUE;
01225   if (set&4 && !featcmp(str,"3")) return TRUE;
01226   if (set&8 && !featcmp(str,"4")) return TRUE;
01227   return FALSE;
01228 }
01229 
01230 void deref_rec_args_exc(n,set)
01231 ptr_node n;
01232 long set;
01233 {
01234   ptr_psi_term t;
01235   
01236   if (n) {
01237     deref_rec_args_exc(n->right,set);
01238     if (!in_set(n->key,set)) {
01239       t = (ptr_psi_term) (n->data);
01240       deref_ptr(t);
01241       deref_rec_body(t);
01242     }
01243     deref_rec_args_exc(n->left,set);
01244   }
01245 }
01246 
01247 
01248 /* These two needed only for match_aim and match_attr: */
01249 
01250 /* Same as deref_eval, but assumes goal_stack already restored. */
01251 void deref2_eval(t)
01252 ptr_psi_term t;
01253 {
01254   deref_ptr(t);
01255   if (t->status==0) {
01256     if (t->type->type==function) {
01257       check_func(t);
01258     }
01259     else 
01260       if(t->type->type==global) { /*  RM: Feb 10 1993  */
01261         eval_global_var(t);
01262         deref_ptr(t);/*  RM: Jun 25 1993  */
01263         deref2_eval(t);
01264       }
01265       else {
01266         t->status=4;
01267       }
01268   }
01269 }
01270 
01271 /* Same as deref_rec_eval, but assumes goal_stack already restored. */
01272 void deref2_rec_eval(t)
01273 ptr_psi_term t;
01274 {
01275   deref_ptr(t);
01276   deref_rec_body(t);
01277 }
01278 
01279 /********************************************************************/
01280 
01281 /* Saving & restoring residuation information */
01282 
01283 void save_resid(rb,match_date)
01284 ptr_resid_block rb;
01285 ptr_psi_term match_date;
01286 {
01287    if (rb) {
01288       rb->cc_cr = (can_curry<<1) + curried; /* 11.9 */
01289       rb->ra = resid_aim;
01290       rb->rv = resid_vars;
01291       /* rb->cr = curried; 11.9 */
01292       /* rb->cc = can_curry; 11.9 */
01293       rb->md = match_date;
01294    }
01295 }
01296 
01297 void restore_resid(rb,match_date)
01298 ptr_resid_block rb;
01299 ptr_psi_term *match_date;
01300 {
01301    if (rb) {
01302       can_curry = (rb->cc_cr&2)?TRUE:FALSE; /* 11.9 */
01303       curried   = (rb->cc_cr&1)?TRUE:FALSE; /* 11.9 */
01304       resid_aim = rb->ra;
01305       resid_vars = rb->rv;
01306       /* curried = rb->cr; 11.9 */
01307       /* can_curry = rb->cc; 11.9 */
01308       *match_date = rb->md;
01309    }
01310 }
01311 
01312 
01313 
01314 /******** EVAL_GLOBAL_VAR(t)
01315   Dereference a global variable.
01316   */
01317 
01318 void eval_global_var(t)     /*  RM: Feb 10 1993  */
01319 
01320      ptr_psi_term t;
01321 {
01322   deref_ptr(t);
01323 
01324   /* Global variable (not persistent) */
01325 
01326   Traceline("dereferencing variable %P\n",t);
01327   
01328   /* Trails the heap RM: Nov 10 1993  */
01329   if(!t->type->global_value) {
01330 
01331     /* Trail the heap !! */
01332     {
01333       ptr_stack n;
01334       n=STACK_ALLOC(stack);
01335       n->type=psi_term_ptr;
01336       n->a= (GENERIC) &(t->type->global_value);
01337       n->b= NULL;
01338       n->next=undo_stack;
01339       undo_stack=n;
01340     }
01341 
01342 
01343     clear_copy();
01344     t->type->global_value=eval_copy(t->type->init_value,STACK);
01345 
01346   }
01347 
01348   /* var_occurred=TRUE; RM: Feb  4 1994  */
01349 
01350   if(t->type->type==global && t!=t->type->global_value) {
01351     /*Traceline("dereferencing variable %P\n",t);*/
01352     push_psi_ptr_value(t,&(t->coref));
01353     t->coref=t->type->global_value;
01354   }
01355 }
01356 
01357 
01358 
01359 
01360 /******** INIT_GLOBAL_VARS()
01361   Initialize all non-persistent global variables.
01362   */
01363 
01364 void init_global_vars()  /*  RM: Feb 15 1993  */
01365 
01366 {
01367   ptr_definition def;
01368 
01369   /* printf("initializing global vars...\n"); */
01370   
01371   /*
01372     for(def=first_definition;def;def=def->next) {
01373     if(def->type==global && ((GENERIC)def->global_value<heap_pointer)) {
01374     clear_copy();
01375     def->global_value=eval_copy(def->init_value,STACK); 
01376     }
01377     }
01378     */
01379 
01380   for(def=first_definition;def;def=def->next)
01381     if((GENERIC)(def->global_value)<(GENERIC)heap_pointer)
01382       def->global_value=NULL;
01383 }
01384 
01385 /********************************************************************/

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