home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lifeos2.zip / LIFE-1.02 / SOURCE / LEFUN.C < prev    next >
C/C++ Source or Header  |  1996-06-04  |  35KB  |  1,386 lines

  1. /* Copyright 1991 Digital Equipment Corporation.
  2. ** All Rights Reserved.
  3. *****************************************************************/
  4. /*     $Id: lefun.c,v 1.4 1995/01/14 00:24:55 duchier Exp $     */
  5.  
  6. #ifndef lint
  7. static char vcid[] = "$Id: lefun.c,v 1.4 1995/01/14 00:24:55 duchier Exp $";
  8. #endif /* lint */
  9.  
  10. #include "extern.h"
  11. #include "login.h"
  12. #include "copy.h"
  13. #include "trees.h"
  14. #include "parser.h"
  15. #include "print.h"
  16. #include "lefun.h"
  17. #include "token.h"
  18.  
  19.  
  20. ptr_goal resid_aim;
  21. ptr_resid_list resid_vars; /* 21.9 */
  22. /* ptr_goal resid_limit; 12.6 */
  23.  
  24. long curried;
  25. long can_curry;
  26.  
  27. /* ptr_psi_term match_date; 13.6 */
  28. /* ptr_choice_point cut_point; 13.6 */
  29.  
  30. static long attr_missing;
  31. static long check_func_flag;
  32.  
  33. void eval_global_var(); /*  RM: Feb 10 1993  */
  34.  
  35.  
  36. /* Create a new psi_term on the stack with value '@' (top) and no attributes. */
  37. ptr_psi_term stack_psi_term(stat)
  38. long stat;
  39. {
  40.   ptr_psi_term result;
  41.  
  42.   result=STACK_ALLOC(psi_term);
  43.   result->type=top;
  44.   result->status=stat;
  45.   result->flags=stat?QUOTED_TRUE:FALSE; /* 14.9 */
  46.   result->attr_list=NULL;
  47.   result->coref=NULL;
  48. #ifdef TS
  49.   result->time_stamp=global_time_stamp; /* 9.6 */
  50. #endif
  51.   result->resid=NULL;
  52.   result->value=NULL;
  53.  
  54.   return result;
  55. }
  56.  
  57.  
  58.  
  59. /* Create a new psi_term on the stack with a real number value. */
  60. ptr_psi_term real_stack_psi_term(stat,thereal)
  61. long stat;
  62. REAL thereal;
  63. {
  64.   ptr_psi_term result;
  65.  
  66.   result=STACK_ALLOC(psi_term);
  67.   result->type = (thereal==floor(thereal)) ? integer : real;
  68.   result->status=stat;
  69.   result->flags=stat?QUOTED_TRUE:FALSE; /* 14.9 */
  70.   result->attr_list=NULL;
  71.   result->coref=NULL;
  72. #ifdef TS
  73.   result->time_stamp=global_time_stamp; /* 9.6 */
  74. #endif
  75.   result->resid=NULL;
  76.   result->value=(GENERIC)heap_alloc(sizeof(REAL));
  77.   (* (REAL *)(result->value)) = thereal;
  78.  
  79.   return result;
  80. }
  81.  
  82.  
  83.  
  84. /* Create a new psi_term on the heap with value '@' (top) and no attributes. */
  85. ptr_psi_term heap_psi_term(stat)
  86. long stat;
  87. {
  88.   ptr_psi_term result;
  89.  
  90.   result=HEAP_ALLOC(psi_term);
  91.   result->type=top;
  92.   result->status=stat;
  93.   result->flags=stat?QUOTED_TRUE:FALSE; /* 14.9 */
  94.   result->attr_list=NULL;
  95.   result->coref=NULL;
  96. #ifdef TS
  97.   result->time_stamp=global_time_stamp; /* 9.6 */
  98. #endif
  99.   result->resid=NULL;
  100.   result->value=NULL;
  101.  
  102.   return result;
  103. }
  104.  
  105.  
  106.  
  107. /* Create an empty list on the stack,  wiped out by RM: Dec 14 1992  */
  108. /* ptr_psi_term stack_empty_list()  is now aliased to stack_nil()    */
  109.  
  110.  
  111.  
  112. /******** RESIDUATE_DOUBLE(t,u)
  113.   Residuate the current expression with T in the Residuation Variable set.
  114.   Also store the other variable, so that its sort can be used in the
  115.   'bestsort' calculation needed to implement disequality constraints.
  116. */
  117. void residuate_double(t,u) /* 21.9 */
  118. ptr_psi_term t,u;
  119. {
  120.   ptr_resid_list curr;
  121.  
  122.   curr=STACK_ALLOC(resid_list);
  123.   curr->var=t;
  124.   curr->othervar=u;
  125.   curr->next=resid_vars;
  126.   resid_vars=curr;
  127. }
  128.  
  129.  
  130.  
  131.  
  132. /******** RESIDUATE(t)
  133.   Residuate the current expression with T in the Residuation Variable set.
  134. */
  135. void residuate(t)
  136. ptr_psi_term t;
  137. {
  138.   ptr_resid_list curr;
  139.  
  140.   curr=STACK_ALLOC(resid_list);
  141.   curr->var=t;
  142.   curr->othervar=NULL; /* 21.9 */
  143.   curr->next=resid_vars;
  144.   resid_vars=curr;
  145. }
  146.  
  147.  
  148.  
  149. /******** RESIDUATE2(u,v)
  150.   Residuate the current function on the two variables U and V.
  151. */
  152. void residuate2(u,v)
  153. ptr_psi_term u,v;
  154. {
  155.   residuate(u);
  156.   if (v && u!=v) residuate(v);
  157. }
  158.  
  159.  
  160.  
  161. /******** RESIDUATE3(u,v,w)
  162.   Residuate the current function on the three variables U, V, and W.
  163. */
  164. void residuate3(u,v,w)
  165. ptr_psi_term u,v,w;
  166. {
  167.   residuate(u);
  168.   if (v && u!=v) residuate(v);
  169.   if (w && u!=w && v!=w) residuate(w);
  170.  
  171.  
  172.  
  173. /******** CURRY()
  174.   Decide that the current function will have to be curried.
  175.   This has become so simple it could be a MACRO.
  176.   The real work is done by DO_CURRY.
  177. */
  178. void curry()
  179. {
  180.   if (can_curry)
  181.     curried=TRUE;
  182. }
  183.  
  184.  
  185.  
  186.  
  187. /******** RESIDUATEGOALONVAR(g,var,othervar)
  188.   Add the goal to the variable's residuation list.
  189.   Also update the residuation's 'bestsort' field if it exists (needed to
  190.   implement complete disequality semantics).  The 'othervar' parameter
  191.   is needed for this.
  192. */
  193. long residuateGoalOnVar(g, var, othervar)
  194. ptr_goal g;
  195. ptr_psi_term var,othervar;
  196. {
  197.   long result;
  198.   long resflag,resflag2;
  199.   GENERIC rescode,rescode2,resvalue,resvalue2;
  200.   /* Set to FALSE if the goal is already residuated on the var: */
  201.   long not_found = TRUE;
  202.   /* Points to a pointer to a residuation structure.  Used so we can */
  203.   /* add the goal to the end of the residuation list, so that it can */
  204.   /* can be undone later if backtracking happens.  See the call to   */
  205.   /* push_ptr_value.  */
  206.   ptr_residuation *r;
  207.     
  208.   /* 5.8 PVR */
  209.   if ((GENERIC)var>=heap_pointer) {
  210.     Errorline("attempt to residuate on psi-term %P in the heap.\n",var);
  211.  
  212.     return FALSE;
  213.   }
  214.  
  215.   r= &(var->resid);
  216.     
  217.   while (not_found && *r) {
  218.     if ((*r)->goal == g) { /* This goal is already attached */
  219.       /* Keep track of best sort so far */
  220.       /* Glb_code(..) tries to keep 'sortflag' TRUE if possible. */
  221.       result=glb_code((*r)->sortflag,(*r)->bestsort,
  222.               TRUE,var->type,&resflag,&rescode);
  223.       result=glb_value(result,resflag,rescode,(*r)->value,var->value,
  224.                &resvalue); /* 6.10 */
  225.       if (!result)
  226.         return FALSE; /* 21.9 */
  227.       else if (othervar) {
  228.     result=glb_code(resflag,rescode,TRUE,othervar->type,
  229.             &resflag2,&rescode2);
  230.         result=glb_value(result,resflag2,rescode2,resvalue,othervar->value,
  231.              &resvalue2); /* 6.10 */
  232.         if (!result) {
  233.           return FALSE;
  234.         }
  235.         else {
  236.       /* The value field only has to be trailed once, since its value */
  237.       /* does not change, once given. */
  238.       if ((*r)->value==NULL && resvalue2!=NULL) { /* 6.10 */
  239.         push_ptr_value(int_ptr,&((*r)->value));
  240.       }
  241.       if ((*r)->bestsort!=rescode2) {
  242.             push_ptr_value(((*r)->sortflag?def_ptr:code_ptr),
  243.                &((*r)->bestsort));
  244.             (*r)->bestsort=rescode2; /* 21.9 */
  245.       }
  246.       if ((*r)->sortflag!=resflag2) {
  247.             push_ptr_value(int_ptr,&((*r)->sortflag));
  248.             (*r)->sortflag=resflag2; /* 21.9 */
  249.       }
  250.     }
  251.       }
  252.       else {
  253.     if ((*r)->value==NULL && resvalue!=NULL) { /* 6.10 */
  254.       push_ptr_value(int_ptr,&((*r)->value));
  255.     }
  256.     if ((*r)->bestsort!=rescode) {
  257.           push_ptr_value(((*r)->sortflag?def_ptr:code_ptr),
  258.                      &((*r)->bestsort));
  259.           (*r)->bestsort=rescode; /* 21.9 */
  260.     }
  261.     if ((*r)->sortflag!=resflag) {
  262.           push_ptr_value(int_ptr,&((*r)->sortflag));
  263.           (*r)->sortflag=resflag; /* 21.9 */
  264.     }
  265.       }
  266.       not_found = FALSE;
  267.     }
  268.     else
  269.       r= &((*r)->next);  /* look at the next one */
  270.   }
  271.   
  272.   if (not_found) {
  273.     /* We must attach this goal & the variable's sort onto this variable */
  274.     
  275.     push_ptr_value(resid_ptr,r);
  276.     *r=STACK_ALLOC(residuation);
  277.     if (othervar) {
  278.       result=glb_code(TRUE,var->type,TRUE,othervar->type,&resflag,&rescode);
  279.       result=glb_value(result,resflag,rescode,var->value,othervar->value,
  280.                &resvalue); /* 6.10 */
  281.       if (!result) {
  282.         return FALSE;
  283.       }
  284.       else {
  285.     (*r)->sortflag=resflag;
  286.         (*r)->bestsort=rescode; /* 21.9 */
  287.     (*r)->value=resvalue; /* 6.10 */
  288.       }
  289.     }
  290.     else {
  291.       (*r)->sortflag=TRUE;
  292.       (*r)->bestsort=(GENERIC)var->type; /* 21.9 */
  293.       (*r)->value=(GENERIC)var->value; /* 6.10 */
  294.     }
  295.     (*r)->goal=g;
  296.     (*r)->next=NULL;
  297.   }
  298.   
  299.   if (!(g->pending)) {
  300.     /* this goal is not pending, so make sure it will be put on the goal
  301.      * stack later
  302.      */
  303.     push_ptr_value(int_ptr,&(g->pending));
  304.     g->pending=TRUE;
  305.   }
  306.   
  307.   return TRUE; /* 21.9 */
  308. }
  309.  
  310.  
  311.  
  312. /******** DO_RESIDUATION()
  313.   Undo anything that matching may have done, then
  314.   create a residuated expression. Check that the same constraint does not
  315.   hang several times on the same variable.
  316.  
  317.   This routine takes time proportional to the square of the number of
  318.   residuations.  This is too slow; eventually it should be sped up, 
  319.   especially if equality constraints are often used.
  320. */
  321. long do_residuation(); /* forward declaration */
  322.  
  323. /* LIFE-defined routines reset the goal stack to what it was */
  324. /* before the function call. */
  325. long do_residuation_user()
  326. {
  327.   goal_stack=resid_aim->next; /* reset goal stack */
  328.   return do_residuation();
  329. }
  330.  
  331. /* C-defined routines do all stack manipulation themselves */
  332. long do_residuation()
  333. {
  334.   long success;
  335.   ptr_psi_term t,u;
  336.   ptr_goal *gs;
  337.   
  338.   /* This undoes perfectly valid work! */
  339.   /* The old version of Wild_Life did not trail anything
  340.      during matching, so I think this was a nop for it. */
  341.   /* PVR 11.5 undo(resid_limit); */
  342.   /* PVR 11.5 choice_stack=cut_point; */
  343.  
  344.   /* PVR 9.2.94 */
  345.   /* goal_stack=resid_aim->next; */
  346.  
  347.   if (trace) {
  348.     tracing();
  349.     print_resid_message(resid_aim->a,resid_vars);
  350.   }
  351.  
  352.   while (resid_vars) {
  353.     
  354.     t=resid_vars->var; /* 21.9 */
  355.     u=resid_vars->othervar; /* 21.9 */
  356.     /* PVR */ deref_ptr(t);
  357.     resid_vars=resid_vars->next;
  358.     Traceline("residuating on %P (other = %P)\n",t,u);
  359.     
  360.     success=residuateGoalOnVar(resid_aim, t, u); /* 21.9 */
  361.     if (!success) { /* 21.9 */
  362.       Traceline("failure because of disentailment\n");
  363.       return FALSE;
  364.     }
  365.   }
  366.   
  367.   Traceline("no failure because of disentailment\n");
  368.   return TRUE; /* 21.9 */
  369. }
  370.  
  371.  
  372.  
  373. /********* DO_CURRYING()
  374.   This performs CURRYing: all that needs to be done is to yield the calling
  375.   term as the result after having given up on evaluation. In effect the calling
  376.   psi-term is left intact.
  377. */
  378. void do_currying()
  379. {
  380.   ptr_psi_term funct,result;
  381.  
  382.   /* PVR 5.11 undo(resid_limit); */
  383.   /* PVR 5.11 choice_stack=cut_point; */
  384.   goal_stack=resid_aim->next;
  385.   funct=(ptr_psi_term )resid_aim->a;
  386.   result=(ptr_psi_term )resid_aim->b;
  387.     
  388.   Traceline("currying %P\n",funct);
  389.    
  390.   push_goal(unify_noeval,funct,result,NULL);
  391.   resid_aim=NULL;
  392. }
  393.  
  394.  
  395.  
  396. /******** RELEASE_RESID(t)
  397.   Release the residuations pending on the Residuation Variable T.
  398.   This is done by simply pushing the residuated goals onto the goal-stack.
  399.   A goal is not added if already present on the stack.
  400.   Two versions of this routine exist: one which trails t and one which never
  401.   trails t.
  402. */
  403. void release_resid_main(t,trailflag)
  404. ptr_psi_term t;
  405. long trailflag;
  406. {
  407.   ptr_goal g;
  408.   ptr_residuation r;
  409.   
  410.   if (r=t->resid) {
  411.     if (trailflag) push_ptr_value(resid_ptr,&(t->resid));
  412.     t->resid=NULL;
  413.     
  414.     while (r) {
  415.       g=r->goal;
  416.       if (g->pending) {
  417.     
  418.     push_ptr_value(int_ptr,&(g->pending));
  419.     g->pending=FALSE;
  420.     
  421.     push_ptr_value(goal_ptr,&(g->next));
  422.     
  423.     g->next=goal_stack;
  424.     goal_stack=g;
  425.     
  426.         Traceline("releasing %P\n",g->a);
  427.       }
  428.       r=r->next;
  429.     }
  430.   }
  431. }
  432.  
  433. void release_resid(t)
  434. ptr_psi_term t;
  435. {
  436.   release_resid_main(t,TRUE);
  437. }
  438.  
  439. void release_resid_notrail(t)
  440. ptr_psi_term t;
  441. {
  442.   release_resid_main(t,FALSE);
  443. }
  444.  
  445.  
  446.  
  447. /******** APPEND_RESID(u,v)
  448.   Append the residuations pending on V to U. This routine does not check that
  449.   the same constraint is not present twice in the end on U. This doesn't matter
  450.   since RELEASE_RESID ensures that the same constraint is not released more
  451.   than once.
  452. */
  453. void append_resid(u,v)
  454. ptr_psi_term u,v;
  455. {
  456.   ptr_residuation *g;
  457.   
  458.   g= &(u->resid);
  459.   while (*g)
  460.     g = &((*g)->next);
  461.   
  462.   push_ptr_value(resid_ptr,g);
  463.   *g=v->resid;
  464. }
  465.  
  466.  
  467.  
  468. /******** EVAL_AIM()
  469.   Evaluate a function.
  470.   This copies the current definition of the function and
  471.   stacking the various goals that are necessary to evaluate the function
  472.   correctly.
  473.   It creates an extra psi-term (with value top) in which to write the result.
  474. */
  475. long eval_aim()
  476. {
  477.   long success=TRUE;
  478.   ptr_psi_term funct,result,head,body;
  479.   ptr_pair_list rule;
  480.   /* RESID */ ptr_resid_block rb;
  481.   ptr_choice_point cutpt;
  482.   ptr_psi_term match_date; /* 13.6 */
  483.   
  484.   funct=(ptr_psi_term )aim->a;
  485.   deref_ptr(funct);
  486.  
  487.   /*  RM: Jun 18 1993  */
  488.   push2_ptr_value(int_ptr,&(funct->status),(funct->status & SMASK));
  489.   funct->status=4;
  490.  
  491.   
  492.   /* if (!funct->type->evaluate_args) mark_quote(funct); 25.8 */ /* 18.2 PVR */
  493.   result=(ptr_psi_term )aim->b;
  494.   rule=(ptr_pair_list )aim->c;
  495.  
  496.   match_date=(ptr_psi_term )stack_pointer;
  497.   cutpt=choice_stack; /* 13.6 */
  498.  
  499.   /* For currying and residuation */
  500.   curried=FALSE;
  501.   can_curry=TRUE;
  502.   /* resid_aim=aim; */
  503.   resid_vars=NULL;
  504.   /* resid_limit=(ptr_goal )stack_pointer; 12.6 */
  505.       
  506.   if (rule) {
  507.     Traceline("evaluate %P\n",funct);
  508.     if ((unsigned long)rule<=MAX_BUILT_INS) {
  509.       
  510.       resid_aim=aim;
  511.       success=c_rule[(unsigned long)rule]();
  512.  
  513.       if (curried)
  514.     do_currying();
  515.       else
  516.     if (resid_vars)
  517.       success=do_residuation(); /* 21.9 */
  518.     else {
  519.       /* resid_aim=NULL; */
  520.         }
  521.     }
  522.     else {
  523.       while (rule && (rule->a==NULL || rule->b==NULL)) {
  524.         rule=rule->next;
  525.         Traceline("alternative rule has been retracted\n");
  526.       }
  527.       if (rule) {
  528.         /* push_choice_point(eval,funct,result,rule->next); */ /* 17.6 */
  529.  
  530.         resid_aim=aim;
  531.         /* RESID */ rb = STACK_ALLOC(resid_block);
  532.         /* RESID */ save_resid(rb,match_date);
  533.         /* RESID */ /* resid_aim = NULL; */
  534.  
  535.         clear_copy();
  536.  
  537.     /*  RM: Jun 18 1993: no functions in head */
  538.     /*  if (TRUE)
  539.         head=eval_copy(rule->a,STACK);
  540.         else */
  541.     
  542.     head=quote_copy(rule->a,STACK);
  543.         body=eval_copy(rule->b,STACK);
  544.     head->status=4;
  545.     
  546.         if (rule->next) /* 17.6 */
  547.           push_choice_point(eval,funct,result,rule->next);
  548.  
  549.         push_goal(unify,body,result,NULL);
  550.         /* RESID */ push_goal(eval_cut,body,cutpt,rb); /* 13.6 */
  551.         /* RESID */ push_goal(match,funct,head,rb);
  552.         /* eval_args(head->attr_list); */
  553.       }
  554.       else {
  555.         success=FALSE;
  556.         /* resid_aim=NULL; */
  557.       }
  558.     }
  559.   }
  560.   else {
  561.     success=FALSE;
  562.     /* resid_aim=NULL; */
  563.   }
  564.   resid_aim=NULL;
  565.   /* match_date=NULL; */ /* 13.6 */
  566.   return success;
  567. }
  568.  
  569.  
  570.  
  571. /* Match the corresponding arguments */
  572. /* RESID */ match_attr1(u,v,rb)
  573. ptr_node *u,v;
  574. /* RESID */ ptr_resid_block rb;
  575. {
  576.   long cmp;
  577.   ptr_node temp;
  578.   
  579.   if (v) {
  580.     if (*u==NULL)
  581.       attr_missing=TRUE;
  582.     else {
  583.       cmp=featcmp((*u)->key,v->key);
  584.       if(cmp==0) {
  585.         ptr_psi_term t;
  586.       /* RESID */ match_attr1(&((*u)->right),v->right,rb);
  587.         t = (ptr_psi_term) (*u)->data;
  588.       /* RESID */ push_goal(match,(*u)->data,v->data,rb);
  589.         /* deref2_eval(t); */
  590.       /* RESID */ match_attr1(&((*u)->left),v->left,rb);
  591.       }
  592.       else if (cmp>0) {
  593.         temp=v->right;
  594.         v->right=NULL;
  595.       /* RESID */ match_attr1(u,temp,rb);
  596.       /* RESID */ match_attr1(&((*u)->left),v,rb);
  597.       v->right=temp;
  598.       }
  599.       else {
  600.       temp=v->left;
  601.       v->left=NULL;
  602.       /* RESID */ match_attr1(&((*u)->right),v,rb);
  603.       /* RESID */ match_attr1(u,temp,rb);
  604.       v->left=temp;
  605.       }
  606.     }
  607.   }
  608. }
  609.  
  610.  
  611. /* Evaluate the lone arguments (for lazy failure + eager success) */
  612. /* RESID */ match_attr2(u,v,rb)
  613. ptr_node *u,v;
  614. /* RESID */ ptr_resid_block rb;
  615. {
  616.   long cmp;
  617.   ptr_node temp;
  618.   
  619.   if (v) {
  620.     if (*u==NULL) { /* PVR 12.03 */
  621.       ptr_psi_term t;
  622.       match_attr1(u,v->right,rb);
  623.       t = (ptr_psi_term) v->data;
  624.       deref2_rec_eval(t);
  625.       match_attr1(u,v->left,rb);
  626.     }
  627.     else {
  628.       cmp=featcmp((*u)->key,v->key);
  629.       if(cmp==0) {
  630.       /* RESID */ match_attr2(&((*u)->right),v->right,rb);
  631.       /* RESID */ match_attr2(&((*u)->left),v->left,rb);
  632.       }
  633.       else if (cmp>0) {
  634.         temp=v->right;
  635.         v->right=NULL;
  636.       /* RESID */ match_attr2(u,temp,rb);
  637.       /* RESID */ match_attr2(&((*u)->left),v,rb);
  638.       v->right=temp;
  639.       }
  640.       else {
  641.       temp=v->left;
  642.       v->left=NULL;
  643.       /* RESID */ match_attr2(&((*u)->right),v,rb);
  644.       /* RESID */ match_attr2(u,temp,rb);
  645.       v->left=temp;
  646.       }
  647.     }
  648.   }
  649.   else if (*u!=NULL) {
  650.     ptr_psi_term t /* , empty */ ;
  651.     match_attr1(&((*u)->right),v,rb);
  652.     t = (ptr_psi_term) (*u)->data;
  653.     /* Create a new psi-term to put the (useless) result: */
  654.     /* This is needed so that *all* arguments of a function call */
  655.     /* are evaluated, which avoids incorrect 'Yes' answers.      */
  656.     deref2_rec_eval(t); /* Assumes goal_stack is already restored. */
  657.     match_attr1(&((*u)->left),v,rb);
  658.   }
  659. }
  660.  
  661.  
  662. /* Evaluate the corresponding arguments */
  663. /* RESID */ match_attr3(u,v,rb)
  664. ptr_node *u,v;
  665. /* RESID */ ptr_resid_block rb;
  666. {
  667.   long cmp;
  668.   ptr_node temp;
  669.   
  670.   if (v) {
  671.     if (*u==NULL)
  672.       attr_missing=TRUE;
  673.     else {
  674.       cmp=featcmp((*u)->key,v->key);
  675.       if(cmp==0) {
  676.         ptr_psi_term t1,t2;
  677.       /* RESID */ match_attr3(&((*u)->right),v->right,rb);
  678.         t1 = (ptr_psi_term) (*u)->data;
  679.         t2 = (ptr_psi_term) v->data;
  680.       /* RESID */ /* push_goal(match,(*u)->data,v->data,rb); */
  681.         deref2_eval(t1); /* Assumes goal_stack is already restored. */
  682.         deref2_eval(t2); /* PVR 12.03 */
  683.       /* RESID */ match_attr3(&((*u)->left),v->left,rb);
  684.       }
  685.       else if (cmp>0) {
  686.         temp=v->right;
  687.         v->right=NULL;
  688.       /* RESID */ match_attr3(u,temp,rb);
  689.       /* RESID */ match_attr3(&((*u)->left),v,rb);
  690.       v->right=temp;
  691.       }
  692.       else {
  693.       temp=v->left;
  694.       v->left=NULL;
  695.       /* RESID */ match_attr3(&((*u)->right),v,rb);
  696.       /* RESID */ match_attr3(u,temp,rb);
  697.       v->left=temp;
  698.       }
  699.     }
  700.   }
  701. }
  702.  
  703.  
  704.  
  705. /******** MATCH_ATTR(u,v)
  706.   Match the attribute trees of psi_terms U and V.
  707.   If V has an attribute that U doesn't then curry.
  708.   U is the calling term, V is the definition.
  709.   This routine is careful to push nested eval and match goals in
  710.   descending order of feature names.
  711. */
  712. void match_attr(u,v,rb)
  713. ptr_node *u,v;
  714. ptr_resid_block rb;
  715. {
  716.   match_attr1(u,v,rb); /* Match corresponding arguments (third) */
  717.   match_attr2(u,v,rb); /* Evaluate lone arguments (second) */
  718.   match_attr3(u,v,rb); /* Evaluate corresponding arguments (first) */
  719. }
  720.  
  721.  
  722.  
  723.  
  724.  
  725. /******** MATCH_AIM()
  726.   This is very similar to UNIFY_AIM, only matching cannot modify the calling
  727.   psi_term.   The first argument is the calling term (which may not be changed)
  728.   and the second argument is the function definition (which may be changed).
  729.   Residuate the expression if the calling term is more general than the
  730.   function definition.
  731. */
  732. long match_aim()
  733. {
  734.   long success=TRUE;
  735.   ptr_psi_term u,v,tmp;
  736.   REAL r;
  737.   long less,lesseq;
  738.   ptr_resid_block rb;
  739.   ptr_psi_term match_date;
  740.   
  741.   u=(ptr_psi_term )aim->a;
  742.   v=(ptr_psi_term )aim->b;
  743.   deref_ptr(u);
  744.   deref_ptr(v);
  745.   rb=(ptr_resid_block)aim->c;
  746.   restore_resid(rb,&match_date);
  747.   
  748.   if (u!=v) {
  749.     if (success=matches(u->type,v->type,&lesseq)) {
  750.       if (lesseq) {
  751.         if (u->type!=cut || v->type!=cut) { /* Ignore value field for cut! */
  752.           if (v->value) {
  753.             if (u->value) {
  754.               if (overlap_type(v->type,real))
  755.                 success=(*((REAL *)u->value)==(*((REAL *)v->value)));
  756.               else if (overlap_type(v->type,quoted_string))
  757.                 success=(strcmp((char *)u->value,(char *)v->value)==0);
  758.           /* DENYS: BYTEDATA */
  759.               else if (overlap_type(v->type,sys_bytedata)) {
  760.         unsigned long ulen = *((unsigned long *) u->value);
  761.         unsigned long vlen = *((unsigned long *) v->value);
  762.                 success=(ulen==vlen && bcmp((char *)u->value,(char *)v->value,ulen)==0);
  763.           }
  764.             }
  765.             else
  766.               residuate_double(u,v);
  767.           }
  768.         }
  769.       }
  770.       else if (u->value) {
  771.         /* Here we have U <| V but U and V have values which cannot match. */
  772.         success=TRUE;
  773.           
  774.         if (v->value) {
  775.           if (overlap_type(v->type,real))
  776.             success=(*((REAL *)u->value)==(*((REAL *)v->value)));
  777.         }
  778.         else if (overlap_type(u->type,integer)) {
  779.           r= *((REAL *)u->value);
  780.           success=(r==floor(r));
  781.         }
  782.           
  783.         if (success) residuate_double(u,v);
  784.       } 
  785.       else
  786.         residuate_double(u,v);
  787.                   
  788.       if (success) {
  789.         if (FUNC_ARG(u) && FUNC_ARG(v)) { /*  RM: Feb 10 1993  */
  790.           /* residuate2(u,v); 21.9 */
  791.           residuate_double(u,v); /* 21.9 */
  792.           residuate_double(v,u); /* 21.9 */
  793.     }
  794.         else if (FUNC_ARG(v)) {  /*  RM: Feb 10 1993  */
  795.           residuate_double(v,u); /* 21.9 */
  796.         }
  797.         else {
  798.           v->coref=u;
  799.         } /* 21.9 */
  800.       attr_missing=FALSE;
  801.       match_attr(&(u->attr_list),v->attr_list,rb);
  802.       if (attr_missing) {
  803.             if (can_curry)
  804.               curried=TRUE;
  805.             else
  806.               residuate_double(u,v);
  807.           }
  808.         /* } 21.9 */
  809.       }
  810.     }
  811.   }
  812.  
  813.   can_curry=FALSE;
  814.   save_resid(rb,match_date); /* updated resid_block */
  815.   /* This should be a useless statement: */
  816.   resid_aim = NULL;
  817.   
  818.   return success;
  819. }
  820.  
  821.  
  822.  
  823. /******************************************************************************
  824.   The following routines prepare terms for unification, proof or matching.
  825.   They deal with conjunctions, disjunctions, functions and arguments which
  826.   have to be examined before the general proof can continue.
  827. */
  828.  
  829.  
  830.  
  831. /* Forward declarations */
  832. long check_out();
  833. long eval_args();
  834.  
  835.  
  836.  
  837. /******** EVAL_ARGS(n)
  838.   N is an attribute tree, the attributes must be examined, if any reveal
  839.   themselves to need evaluating then return FALSE.
  840. */
  841. long i_eval_args(n)
  842. ptr_node n;
  843. {
  844.   check_func_flag=FALSE;
  845.   return eval_args(n);
  846. }
  847.  
  848.  
  849.  
  850. long eval_args(n)
  851. ptr_node n;
  852. {
  853.   long flag=TRUE;
  854.   
  855.   if (n) {
  856.     flag = eval_args(n->right);
  857.     flag = check_out(n->data) && flag;
  858.     flag = eval_args(n->left) && flag;
  859.   }
  860.   
  861.   return flag;
  862. }
  863.  
  864.  
  865.  
  866. /******** CHECK_DISJ(t)
  867.   Deal with disjunctions.
  868. */
  869. void check_disj(t)
  870. ptr_psi_term t;
  871. {
  872.   Traceline("push disjunction goal %P\n",t);
  873.   if (t->value)
  874.     push_goal(disj,t,t,(GENERIC)TRUE); /* 18.2 PVR */
  875.   else
  876.     push_goal(fail,NULL,NULL,NULL);
  877. }
  878.  
  879.  
  880.  
  881. /******** CHECK_FUNC(t)
  882.   Deal with an unevaluated function: push an 'eval' goal for it, which will
  883.   cause it to be evaluated.
  884. */
  885. void check_func(t)
  886. ptr_psi_term t;
  887. {
  888.   ptr_psi_term result,t1,copy;
  889.  
  890.   /* Check for embedded definitions
  891.      RM: Dec 16 1992  Re-instated this check then disabled it again
  892.      if (resid_aim) {
  893.      Errorline("embedded functions appeared in %P.\n",resid_aim->a);
  894.      fail_all();
  895.      }
  896.      else */ {
  897.     
  898.     Traceline("setting up function call %P\n",t);
  899.     /* Create a psi-term to put the result */
  900.     result = stack_psi_term(0);
  901.     
  902.     /* Make a partial copy of the calling term */
  903.     copy=stack_copy_psi_term(*t);
  904.     copy->status &= ~RMASK;
  905.   
  906.     /* Bind the calling term to the result */
  907.     /* push_ptr_value(psi_term_ptr,&(t->coref)); */
  908.     push_psi_ptr_value(t,&(t->coref));
  909.     t->coref=result;
  910.  
  911.     /* Evaluate the copy of the calling term */
  912.     push_goal(eval,copy,result,t->type->rule);
  913.   
  914.     /* Avoid evaluation for built-in functions with unevaluated arguments */
  915.     /* (cond and such_that) */
  916.     check_func_flag=TRUE;
  917.     if (t->type==iff) {
  918.       get_one_arg(t->attr_list,&t1);
  919.       if (t1) {
  920.     /* mark_eval(t1); 24.8 */
  921.         check_out(t1);
  922.       }
  923.     }
  924.     else if(t->type==disjunction) {
  925.     }
  926.     else if (t->type!=such_that) {
  927.       if (t->type->evaluate_args)
  928.         eval_args(t->attr_list);
  929.       /* else mark_quote_tree(t->attr_list); 24.8 25.8 */
  930.     }
  931.   }
  932. }
  933.  
  934.  
  935.  
  936.  
  937. /******** CHECK_TYPE(t)
  938.   Here we deal with a type which may need checking.
  939.   This routine will have to be modified to deal with the infinite loops
  940.   currently caused by definitions such as:
  941.  
  942.   :: H:husband(spouse => wife(spouse => H)).
  943.   :: W:wife(spouse => husband(spouse => W)).
  944.  
  945. */
  946. long check_type(t)
  947. ptr_psi_term t;
  948. {
  949.   long flag=FALSE;
  950.  
  951.   push2_ptr_value(int_ptr,&(t->status),(t->status & SMASK));
  952.   /* push_ptr_value(int_ptr,&(t->status)); */
  953.   
  954.   if (t->type->properties) {
  955.     if (t->attr_list || t->type->always_check) {
  956.       /* Check all constraints here: */
  957.       fetch_def(t, TRUE); /* PVR 18.2.94 */
  958.       /* t->status=(2 & SMASK) | (t->status & RMASK); PVR 18.2.94 */
  959.  
  960.       eval_args(t->attr_list);
  961.       flag=FALSE;
  962.     }
  963.     else {
  964.       /* definition pending on more information */
  965.       t->status= (2 & SMASK) | (t->status & RMASK);
  966.       flag=TRUE;
  967.     }
  968.   }
  969.   else {
  970.     
  971.     /*  RM: Dec 15 1992  I don't know what this is for
  972.     if (!ovverlap_type(t->type,alist))
  973.     t->status= (4 & SMASK) | (t->status & RMASK);
  974.     */
  975.     
  976.     flag=eval_args(t->attr_list);
  977.   }
  978.   
  979.   return flag;
  980. }
  981.  
  982.  
  983.   
  984. /******** CHECK_OUT(t)
  985.   This routine checks out psi_term T.
  986.   It deals with the following cases:
  987.   - T is a conjunction,
  988.   - T is a type which has properties to check.
  989.   - The same for T's arguments.
  990.   If any of the above holds then proof has to be suspended until the
  991.   case has been dealt with.  This is done by pushing goals on the goal_stack
  992.   to handle the case.  If all is dealt with then CHECK_OUT returns TRUE.
  993.   I.e., CHECK_OUT returns TRUE iff it has not pushed any goals on the stack.
  994.  
  995.   Evaluation is *not* done here, but as a part of dereferencing when a value
  996.   is needed.
  997.  
  998.   Of all the routines related to check_out, only i_check_out, check_func,
  999.   i_eval_args, and the dereference routines are called from outside of this
  1000.   file (lefun.c).
  1001.   - i_check_out(t) checks out everything except functions.  When a function
  1002.     is encountered, check_out returns immediately without looking inside it.
  1003.   - f_check_out(t) checks out functions too.
  1004.   - i_eval_args(n) checks out all arguments, except functions.
  1005.   - check_func(t) checks out a function & all its arguments (including all
  1006.     nested functions.  This is done as part of dereferencing, which is part
  1007.     of unification, matching, built-ins, and user-defined routines.
  1008. */
  1009. long i_check_out(t)
  1010. ptr_psi_term t;
  1011. {
  1012.   check_func_flag=FALSE;
  1013.   return check_out(t);
  1014. }
  1015.  
  1016. long f_check_out(t)
  1017. ptr_psi_term t;
  1018. {
  1019.   check_func_flag=TRUE;
  1020.   return check_out(t);
  1021. }
  1022.  
  1023. long check_out(t)
  1024. ptr_psi_term t;
  1025. {
  1026.   long flag=FALSE;
  1027.   
  1028.   deref_ptr(t);
  1029.  
  1030.   /* Traceline("PVR: entering check_out with status %d and term %P\n",
  1031.             t->status,t); for brunobug.lf PVR 14.2.94 */
  1032.  
  1033.   if (t->status || (GENERIC)t>=heap_pointer) /*  RM: Feb  8 1993  */
  1034.     flag=TRUE;
  1035.   else {
  1036.     t->status |= RMASK;
  1037.  
  1038.     switch(t->type->type) { /*  RM: Feb  8 1993  */
  1039.       
  1040.     case function:
  1041.       if (check_func_flag) {
  1042.     check_func(t);
  1043.     flag=TRUE;
  1044.       }
  1045.       else {
  1046.     /* Function evaluation handled during matching and unification */
  1047.     flag=TRUE;
  1048.       }
  1049.       break;
  1050.  
  1051.     case type:
  1052.       flag=check_type(t);
  1053.       break;
  1054.  
  1055.     case global: /*  RM: Feb  8 1993  */
  1056.       eval_global_var(t);
  1057.       check_out(t);
  1058.       flag=FALSE;
  1059.       break;
  1060.       
  1061.     default:
  1062.       flag=eval_args(t->attr_list);
  1063.     }
  1064.     t->status &= ~RMASK;
  1065.   }
  1066.   return flag;    
  1067. }
  1068.  
  1069.  
  1070.  
  1071. /********************************************************************/
  1072. /*                                                                  */
  1073. /* New dereference routines for Wild_Life                           */
  1074. /* These routines handle evaluation-by-need.  Check_out is changed  */
  1075. /* to no longer call check_func, which is done in the new routines. */
  1076. /* Functions inside of psi-terms are only evaluated if needed.  It  */
  1077. /* is assumed that 'needed' is true when they are derefed.          */
  1078. /*                                                                  */
  1079. /* There are three new dereference routines:                        */
  1080. /*    deref_eval(P)                                                 */
  1081. /*       If the psi-term P is a function, call check_func to        */
  1082. /*       push eval goals so that the function will be evaluated.    */
  1083. /*       Then return TRUE so that the caller can itself return.     */
  1084. /*       This only looks at the top level.                          */
  1085. /*    deref_rec(P)                                                  */
  1086. /*       If the psi-term P recursively contains any functions, then */
  1087. /*       push eval goals to evaluate all of them.  Set a global     */
  1088. /*       variable deref_flag if this is the case.                   */
  1089. /*    deref_args(P,S)                                               */
  1090. /*       Same as above, except does not look at the top level or at */
  1091. /*       the arguments named in the set S.                          */
  1092. /*       This is needed to guarantee evaluation of all arguments of */
  1093. /*       a built-in, even those not used by the built-in.           */
  1094. /*                                                                  */
  1095. /* The original dereference macro is renamed to:                    */
  1096. /*    deref_ptr(P) = while (P->coref) P=P->coref                    */
  1097. /* There are three new macros:                                      */
  1098. /*    deref(P)        = deref_ptr(P);                               */
  1099. /*                      if (deref_eval(P)) then return TRUE         */
  1100. /*    deref_rec(P)    = deref_ptr(P);                               */
  1101. /*                      if (deref_rec_eval(P)) then return TRUE     */
  1102. /*    deref_args(P,S) = deref_ptr(P);                               */
  1103. /*                      if (deref_args_eval(P,S)) then return TRUE  */
  1104. /*                                                                  */
  1105. /********************************************************************/
  1106.  
  1107. static long deref_flag;
  1108. void deref_rec_body();
  1109. void deref_rec_args();
  1110. void deref_rec_args_exc();
  1111.  
  1112. /* Ensure evaluation of top of psi-term */
  1113. long deref_eval(t)
  1114. ptr_psi_term t;
  1115. {
  1116.   ptr_goal save=goal_stack;
  1117.  
  1118.   deref_flag=FALSE;
  1119.   goal_stack=aim;
  1120.  
  1121.   if (t->status==0) {
  1122.     if(t->type->type==function) {
  1123.       check_func(t);    /* Push eval goals to evaluate the function. */
  1124.       deref_flag=TRUE;  /* TRUE so that caller will return to main_prove. */
  1125.     }
  1126.     else
  1127.       if(t->type->type==global) { /*  RM: Feb 10 1993  */
  1128.     eval_global_var(t);
  1129.     deref_ptr(t);/*  RM: Jun 25 1993  */
  1130.     deref_flag=deref_eval(t);
  1131.       }
  1132.       else {
  1133.     if (t->status!=2) {
  1134.       if((GENERIC)t<heap_pointer)
  1135.         push_ptr_value(int_ptr,&(t->status)); /*  RM: Jul 15 1993  */
  1136.       t->status=4;
  1137.       deref_flag=FALSE;
  1138.     }
  1139.       }
  1140.   }
  1141.   else
  1142.     deref_flag=FALSE;
  1143.   
  1144.   if (!deref_flag) goal_stack=save;
  1145.   return (deref_flag);
  1146. }
  1147.  
  1148. /* Ensure evaluation of *all* of psi-term */
  1149. long deref_rec_eval(t)
  1150. ptr_psi_term t;
  1151. {
  1152.   ptr_goal save=goal_stack;
  1153.  
  1154.   deref_flag=FALSE;
  1155.   goal_stack=aim;
  1156.   deref_rec_body(t);
  1157.   if (!deref_flag) goal_stack=save;
  1158.   return (deref_flag);
  1159. }
  1160.  
  1161. void deref_rec_body(t)
  1162. ptr_psi_term t;
  1163. {
  1164.   if (t->status==0) {
  1165.     if (t->type->type==function) {
  1166.       check_func(t);
  1167.       deref_flag=TRUE;
  1168.     }
  1169.     else
  1170.       if(t->type->type==global) { /*  RM: Feb 10 1993  */
  1171.     eval_global_var(t);
  1172.     deref_ptr(t);/*  RM: Jun 25 1993  */
  1173.     deref_rec_body(t);
  1174.       }
  1175.       else {
  1176.     /* if (t->status!=2) Tried adding this -- PVR 9.2.94 */
  1177.       if((GENERIC)t<heap_pointer)
  1178.         push_ptr_value(int_ptr,&(t->status));/*  RM: Jul 15 1993  */
  1179.       t->status=4;
  1180.       deref_rec_args(t->attr_list);
  1181.       }
  1182.   }
  1183. }
  1184.  
  1185. void deref_rec_args(n)
  1186. ptr_node n;
  1187. {
  1188.   ptr_psi_term t1;
  1189.   
  1190.   if (n) {
  1191.     deref_rec_args(n->right);
  1192.     t1 = (ptr_psi_term) (n->data);
  1193.     deref_ptr(t1);
  1194.     deref_rec_body(t1);
  1195.     deref_rec_args(n->left);
  1196.   }
  1197. }
  1198.  
  1199. /* Same as deref_rec_eval, but doesn't look at either the top level or */
  1200. /* the arguments in the set. */
  1201. long deref_args_eval(t,set)
  1202. ptr_psi_term t;
  1203. long set;
  1204. {
  1205.   ptr_goal save = goal_stack;
  1206.   ptr_goal top = aim;
  1207.  
  1208.   deref_flag = FALSE;
  1209.   goal_stack = top;
  1210.   deref_rec_args_exc(t->attr_list,set);
  1211.   if (!deref_flag) goal_stack = save;
  1212.   return (deref_flag);
  1213. }
  1214.  
  1215. /* Return TRUE iff string (considered as number) is in the set */
  1216. /* This routine only recognizes the strings "1", "2", "3",     */
  1217. /* represented as numbers 1, 2, 4.                             */
  1218. long in_set(str,set)
  1219. char *str;
  1220. long set;
  1221. {
  1222.   if (set&1 && !featcmp(str,"1")) return TRUE;
  1223.   if (set&2 && !featcmp(str,"2")) return TRUE;
  1224.   if (set&4 && !featcmp(str,"3")) return TRUE;
  1225.   if (set&8 && !featcmp(str,"4")) return TRUE;
  1226.   return FALSE;
  1227. }
  1228.  
  1229. void deref_rec_args_exc(n,set)
  1230. ptr_node n;
  1231. long set;
  1232. {
  1233.   ptr_psi_term t;
  1234.   
  1235.   if (n) {
  1236.     deref_rec_args_exc(n->right,set);
  1237.     if (!in_set(n->key,set)) {
  1238.       t = (ptr_psi_term) (n->data);
  1239.       deref_ptr(t);
  1240.       deref_rec_body(t);
  1241.     }
  1242.     deref_rec_args_exc(n->left,set);
  1243.   }
  1244. }
  1245.  
  1246.  
  1247. /* These two needed only for match_aim and match_attr: */
  1248.  
  1249. /* Same as deref_eval, but assumes goal_stack already restored. */
  1250. void deref2_eval(t)
  1251. ptr_psi_term t;
  1252. {
  1253.   deref_ptr(t);
  1254.   if (t->status==0) {
  1255.     if (t->type->type==function) {
  1256.       check_func(t);
  1257.     }
  1258.     else 
  1259.       if(t->type->type==global) { /*  RM: Feb 10 1993  */
  1260.           eval_global_var(t);
  1261.     deref_ptr(t);/*  RM: Jun 25 1993  */
  1262.     deref2_eval(t);
  1263.       }
  1264.       else {
  1265.     t->status=4;
  1266.       }
  1267.   }
  1268. }
  1269.  
  1270. /* Same as deref_rec_eval, but assumes goal_stack already restored. */
  1271. void deref2_rec_eval(t)
  1272. ptr_psi_term t;
  1273. {
  1274.   deref_ptr(t);
  1275.   deref_rec_body(t);
  1276. }
  1277.  
  1278. /********************************************************************/
  1279.  
  1280. /* Saving & restoring residuation information */
  1281.  
  1282. void save_resid(rb,match_date)
  1283. ptr_resid_block rb;
  1284. ptr_psi_term match_date;
  1285. {
  1286.    if (rb) {
  1287.       rb->cc_cr = (can_curry<<1) + curried; /* 11.9 */
  1288.       rb->ra = resid_aim;
  1289.       rb->rv = resid_vars;
  1290.       /* rb->cr = curried; 11.9 */
  1291.       /* rb->cc = can_curry; 11.9 */
  1292.       rb->md = match_date;
  1293.    }
  1294. }
  1295.  
  1296. void restore_resid(rb,match_date)
  1297. ptr_resid_block rb;
  1298. ptr_psi_term *match_date;
  1299. {
  1300.    if (rb) {
  1301.       can_curry = (rb->cc_cr&2)?TRUE:FALSE; /* 11.9 */
  1302.       curried   = (rb->cc_cr&1)?TRUE:FALSE; /* 11.9 */
  1303.       resid_aim = rb->ra;
  1304.       resid_vars = rb->rv;
  1305.       /* curried = rb->cr; 11.9 */
  1306.       /* can_curry = rb->cc; 11.9 */
  1307.       *match_date = rb->md;
  1308.    }
  1309. }
  1310.  
  1311.  
  1312.  
  1313. /******** EVAL_GLOBAL_VAR(t)
  1314.   Dereference a global variable.
  1315.   */
  1316.  
  1317. void eval_global_var(t)     /*  RM: Feb 10 1993  */
  1318.  
  1319.      ptr_psi_term t;
  1320. {
  1321.   deref_ptr(t);
  1322.  
  1323.   /* Global variable (not persistent) */
  1324.  
  1325.   Traceline("dereferencing variable %P\n",t);
  1326.   
  1327.   /* Trails the heap RM: Nov 10 1993  */
  1328.   if(!t->type->global_value) {
  1329.  
  1330.     /* Trail the heap !! */
  1331.     {
  1332.       ptr_stack n;
  1333.       n=STACK_ALLOC(stack);
  1334.       n->type=psi_term_ptr;
  1335.       n->a= (GENERIC) &(t->type->global_value);
  1336.       n->b= NULL;
  1337.       n->next=undo_stack;
  1338.       undo_stack=n;
  1339.     }
  1340.  
  1341.  
  1342.     clear_copy();
  1343.     t->type->global_value=eval_copy(t->type->init_value,STACK);
  1344.  
  1345.   }
  1346.  
  1347.   /* var_occurred=TRUE; RM: Feb  4 1994  */
  1348.  
  1349.   if(t->type->type==global && t!=t->type->global_value) {
  1350.     /*Traceline("dereferencing variable %P\n",t);*/
  1351.     push_psi_ptr_value(t,&(t->coref));
  1352.     t->coref=t->type->global_value;
  1353.   }
  1354. }
  1355.  
  1356.  
  1357.  
  1358.  
  1359. /******** INIT_GLOBAL_VARS()
  1360.   Initialize all non-persistent global variables.
  1361.   */
  1362.  
  1363. void init_global_vars()  /*  RM: Feb 15 1993  */
  1364.  
  1365. {
  1366.   ptr_definition def;
  1367.  
  1368.   /* printf("initializing global vars...\n"); */
  1369.   
  1370.   /*
  1371.     for(def=first_definition;def;def=def->next) {
  1372.     if(def->type==global && ((GENERIC)def->global_value<heap_pointer)) {
  1373.     clear_copy();
  1374.     def->global_value=eval_copy(def->init_value,STACK); 
  1375.     }
  1376.     }
  1377.     */
  1378.  
  1379.   for(def=first_definition;def;def=def->next)
  1380.     if((GENERIC)(def->global_value)<(GENERIC)heap_pointer)
  1381.       def->global_value=NULL;
  1382. }
  1383.  
  1384. /********************************************************************/
  1385.