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

Go to the documentation of this file.
00001 /* Copyright 1991 Digital Equipment Corporation.
00002 ** All Rights Reserved.
00003 *****************************************************************/
00004 /*      $Id: built_ins.c,v 1.14 1995/07/27 21:26:28 duchier Exp $        */
00005 
00006 #ifndef lint
00007 static char vcid[] = "$Id: built_ins.c,v 1.14 1995/07/27 21:26:28 duchier Exp $";
00008 #endif /* lint */
00009 #ifdef OS2_PORT_2
00010 #include <direct.h>
00011 #endif
00012 #include "extern.h"
00013 #include "trees.h"
00014 #include "login.h"
00015 #include "types.h"
00016 #include "parser.h"
00017 #include "copy.h"
00018 #include "token.h"
00019 #include "print.h"
00020 #include "lefun.h"
00021 #include "memory.h"
00022 #ifndef OS2_PORT
00023 #include "built_ins.h"
00024 #else
00025 #include "built_in.h"
00026 #endif
00027 #include "error.h" 
00028 #include "modules.h"  /*  RM: Jan  8 1993  */
00029 
00030 #ifdef X11
00031 #include "xpred.h"
00032 #endif
00033 
00034 #ifdef SOLARIS
00035 #include <stdlib.h>
00036 static unsigned int randomseed;
00037 #endif
00038 
00039 
00040 long (* c_rule[MAX_BUILT_INS])();
00041 
00042 ptr_definition abortsym; /* 26.1 */
00043 ptr_definition aborthooksym; /* 26.1 */
00044 
00045 ptr_definition add_module1;  /*  RM: Mar 12 1993  */
00046 ptr_definition add_module2;
00047 ptr_definition add_module3;
00048 
00049 ptr_definition and;
00050 ptr_definition apply;
00051 ptr_definition boolean;
00052 ptr_definition boolpredsym;
00053 ptr_definition built_in;
00054 ptr_definition calloncesym;
00055 ptr_definition colonsym;
00056 ptr_definition commasym;
00057 ptr_definition comment;
00058 /* ptr_definition conjunction; 19.8 */
00059 ptr_definition constant;
00060 ptr_definition cut;
00061 ptr_definition disjunction;
00062 ptr_definition disj_nil;/*  RM: Feb  1 1993  */
00063 ptr_definition eof;
00064 ptr_definition eqsym;
00065 ptr_definition leftarrowsym;
00066 ptr_definition false;
00067 ptr_definition funcsym;
00068 ptr_definition functor;
00069 ptr_definition iff;
00070 ptr_definition integer;
00071 ptr_definition alist;
00072 ptr_definition life_or; /*  RM: Apr  6 1993  */
00073 ptr_definition minus_symbol; /*  RM: Jun 21 1993  */
00074 ptr_definition nil; /*** RM 9 Dec 1992 ***/
00075 ptr_definition nothing;
00076 ptr_definition predsym;
00077 ptr_definition quote;
00078 ptr_definition quoted_string;
00079 ptr_definition real;
00080 ptr_definition stream;
00081 ptr_definition succeed;
00082 ptr_definition such_that;
00083 ptr_definition top;
00084 ptr_definition true;
00085 ptr_definition timesym;
00086 ptr_definition tracesym; /* 26.1 */
00087 ptr_definition typesym;
00088 ptr_definition variable;
00089 ptr_definition opsym;
00090 ptr_definition loadsym;
00091 ptr_definition dynamicsym;
00092 ptr_definition staticsym;
00093 ptr_definition encodesym;
00094 ptr_definition listingsym;
00095 /* ptr_definition provesym; */
00096 ptr_definition delay_checksym;
00097 ptr_definition eval_argsym;
00098 ptr_definition inputfilesym;
00099 ptr_definition call_handlersym;
00100 ptr_definition xf_sym;
00101 ptr_definition fx_sym;
00102 ptr_definition yf_sym;
00103 ptr_definition fy_sym;
00104 ptr_definition xfx_sym;
00105 ptr_definition xfy_sym;
00106 ptr_definition yfx_sym;
00107 ptr_definition nullsym;
00108 
00109 
00110 /*  RM: Jul  7 1993  */
00111 ptr_definition final_dot;
00112 ptr_definition final_question;
00113 
00114 
00115 ptr_psi_term null_psi_term;
00116 
00117 char *one;
00118 char *two;
00119 char *three;
00120 char *year_attr;
00121 char *month_attr;
00122 char *day_attr;
00123 char *hour_attr;
00124 char *minute_attr;
00125 char *second_attr;
00126 char *weekday_attr;
00127 
00128 static long built_in_index=0;
00129 
00130 int all_public_symbols();  /* RM: Jan 28 1994  */
00131 
00132 /*  RM: Sep 20 1993  */
00133 int arg_c;
00134 char **arg_v;
00135 
00136 
00137 
00138 /***  RM: Dec  9 1992  (START) ***/
00139 
00140 /********* STACK_NIL
00141   Create the NIL object on the stack.
00142   */
00143 
00144 ptr_psi_term stack_nil()
00145 
00146 {
00147   ptr_psi_term empty;
00148 
00149   
00150   empty=stack_psi_term(4);
00151   empty->type=nil;
00152 
00153   return empty;
00154 }
00155 
00156 
00157 
00158 /******** STACK_CONS(head,tail)
00159   Create a CONS object.
00160   */
00161 
00162 ptr_psi_term stack_cons(head,tail)
00163      ptr_psi_term head;
00164      ptr_psi_term tail;
00165 {
00166   ptr_psi_term cons;
00167 
00168   cons=stack_psi_term(4);
00169   cons->type=alist;
00170   if(head)
00171     stack_insert(featcmp,one,&(cons->attr_list),head);
00172   if(tail)
00173     stack_insert(featcmp,two,&(cons->attr_list),tail);
00174 
00175   return cons;
00176 }
00177 
00178 /********* STACK_PAIR(left,right)
00179   create a PAIR object.
00180   */
00181 
00182 ptr_psi_term stack_pair(left,right)
00183      ptr_psi_term left;
00184      ptr_psi_term right;
00185 {
00186   ptr_psi_term pair;
00187 
00188   pair=stack_psi_term(4);
00189   pair->type=and;
00190   if(left)
00191     stack_insert(featcmp,one,&(pair->attr_list),left);
00192   if(right)
00193     stack_insert(featcmp,two,&(pair->attr_list),right);
00194 
00195   return pair;
00196 }
00197 
00198 /********* STACK_INT(n)
00199   create an INT object
00200   */
00201 
00202 ptr_psi_term stack_int(n)
00203      long n;
00204 {
00205   ptr_psi_term m;
00206   m=stack_psi_term(4);
00207   m->type=integer;
00208   m->value=heap_alloc(sizeof(REAL));
00209   *(REAL *)m->value=(REAL)n;
00210   return m;
00211 }
00212 
00213 /********* STACK_STRING(s)
00214   create a STRING object
00215   */
00216 
00217 ptr_psi_term stack_string(s)
00218      char *s;
00219 {
00220   ptr_psi_term t = stack_psi_term(4);
00221   t->type = quoted_string;
00222   t->value=(GENERIC)heap_copy_string(s);
00223   return t;
00224 }
00225 
00226 /***  RM: Dec  9 1992  (END) ***/
00227 
00228 /********* STACK_BYTES(s,n)
00229   create a STRING object given a sequence of bytes
00230   */
00231 
00232 ptr_psi_term stack_bytes(s,n)
00233      char *s;
00234      int n;
00235 {
00236   ptr_psi_term t = stack_psi_term(4);
00237   t->type = quoted_string;
00238   t->value=(GENERIC)heap_ncopy_string(s,n);
00239   return t;
00240 }
00241 
00242   
00243 
00244 /********* PSI_TO_STRING(t,fn)
00245   Get the value of a Life string, or the name of a non-string psi-term.
00246   Return TRUE iff a valid string is found.
00247 */
00248 long psi_to_string(t, fn)
00249 ptr_psi_term t;
00250 char **fn;
00251 {
00252   if (equal_types(t->type,quoted_string)) {
00253     if (t->value) {
00254       *fn = (char *) t->value;
00255       return TRUE;
00256     }
00257     else {
00258       *fn = quoted_string->keyword->symbol;
00259       return TRUE;
00260     }
00261   }
00262   else {
00263     *fn = t->type->keyword->symbol;
00264     return TRUE;
00265   }
00266 }
00267 
00268 
00269 /***  RM: Dec  9 1992  (START) ***/
00270 
00271 ptr_psi_term make_feature_list(tree,tail,module,val)
00272      
00273      ptr_node tree;
00274      ptr_psi_term tail;
00275      ptr_module module;
00276      int val;
00277      
00278 {
00279   ptr_psi_term new;
00280   ptr_definition def;
00281   double d, strtod();
00282   
00283   
00284   if(tree) {
00285     if(tree->right)
00286       tail=make_feature_list(tree->right,tail,module,val);
00287 
00288     /* Insert the feature name into the list */
00289     
00290     d=str_to_int(tree->key);
00291     if (d== -1) { /* Feature is not a number */
00292       def=update_feature(module,tree->key); /* Extract module RM: Feb 3 1993 */
00293       if(def) {
00294         if(val) /* RM: Mar  3 1994 Distinguish between features & values */
00295           tail=stack_cons(tree->data,tail);
00296         else {
00297           new=stack_psi_term(4);      
00298           new->type=def;
00299           tail=stack_cons(new,tail);
00300         }
00301       }
00302     }
00303     else { /* Feature is a number */
00304       if(val) /* RM: Mar  3 1994 Distinguish between features & values */
00305         tail=stack_cons(tree->data,tail);
00306       else {
00307         new=stack_psi_term(4);      
00308         new->type=(d==floor(d))?integer:real;
00309         new->value=heap_alloc(sizeof(REAL));
00310         *(REAL *)new->value=(REAL)d;
00311         tail=stack_cons(new,tail);
00312       }
00313     }
00314     
00315     if(tree->left)
00316       tail=make_feature_list(tree->left,tail,module,val);
00317   }
00318   
00319   return tail;
00320 }
00321 
00322 /***  RM: Dec  9 1992  (END) ***/
00323 
00324 
00325 
00326 
00327 
00328 
00329 /******** CHECK_REAL(t,v,n)
00330   Like get_real_value, but does not force the type of T to be real.
00331 */
00332 long check_real(t,v,n)
00333 ptr_psi_term t;
00334 REAL *v;
00335 long *n;
00336 {
00337   long success=FALSE;
00338   long smaller;
00339 
00340   if (t) {
00341     success=matches(t->type,real,&smaller);
00342     if (success) {
00343       *n=FALSE;
00344       if (smaller && t->value) {
00345         *v= *(REAL *)t->value;
00346         *n=TRUE;
00347       }
00348     }
00349   }
00350   return success;
00351 }
00352 
00353 
00354 
00355 /******** GET_REAL_VALUE(t,v,n)
00356   Check if psi_term T is a real number.  Return N=TRUE iff T <| REAL.
00357   If T has a real value then set V to that value.
00358   Also force the type of T to REAL if REAL <| T.
00359   This is used in all the arithmetic built-in functions to get their arguments.
00360 */
00361 long get_real_value(t,v,n)
00362 ptr_psi_term t;
00363 REAL *v;
00364 long *n;
00365 {
00366   long success=FALSE;
00367   long smaller;
00368   
00369   if (t) {
00370     success=matches(t->type,real,&smaller);
00371     if (success) {
00372       *n=FALSE;
00373       if (smaller) {
00374         if (t->value) {
00375           *v= *(REAL *)t->value;
00376           *n=TRUE;
00377         }
00378       }
00379       else {
00380         if((GENERIC)t<heap_pointer) { /*  RM: Jun  8 1993  */
00381           push_ptr_value(def_ptr,&(t->type));
00382           push_ptr_value(int_ptr,&(t->status));
00383           t->type=real;
00384           t->status=0;
00385           i_check_out(t);
00386         }
00387       }
00388     }
00389   }
00390   return success;
00391 }
00392 
00393 
00394 
00395 /******** GET_BOOL_VALUE(t,v,n)
00396   This is identical in nature to
00397   GET_REAL_VALUE. The values handled here have to be booleans.
00398   Check if psi_term T is a boolean. V <- TRUE or FALSE value of T.
00399 */
00400 static long get_bool_value(t,v,n)
00401 ptr_psi_term t;
00402 REAL *v;
00403 long *n;
00404 {
00405   long success=FALSE;
00406   long smaller;
00407   
00408   
00409   if(t) {
00410     success=matches(t->type,boolean,&smaller);
00411     if(success) {
00412       *n=FALSE;
00413       if(smaller) {
00414         if(matches(t->type,false,&smaller) && smaller) {
00415           *v= 0;
00416           *n=TRUE;
00417         }
00418         else
00419           if(matches(t->type,true,&smaller) && smaller) {
00420             *v= 1;
00421             *n=TRUE;
00422           }
00423       }
00424       else {
00425         if((GENERIC)t<heap_pointer) { /*  RM: Jun  8 1993  */
00426           push_ptr_value(def_ptr,&(t->type));
00427           push_ptr_value(int_ptr,&(t->status));
00428           t->type=boolean;
00429           t->status=0;
00430           i_check_out(t);
00431         }
00432       }      
00433     }
00434   }
00435   
00436   return success;
00437 }
00438 
00439 
00440 
00441 /******** UNIFY_BOOL_RESULT(t,v)
00442   Unify psi_term T to the boolean value V = TRUE or FALSE.
00443   This is used by built-in logical functions to return their result.
00444 */
00445 void unify_bool_result(t,v)
00446 ptr_psi_term t;
00447 long v;
00448 {
00449   ptr_psi_term u;
00450 
00451   u=stack_psi_term(4);
00452   u->type=v?true:false;
00453   push_goal(unify,t,u,NULL);
00454   
00455   /* Completely commented out by Richard on Nov 25th 1993
00456      What's *your* Birthday? Maybe you'd like a Birthday-Bug-Card!
00457      
00458   if((GENERIC)t<heap_pointer) {
00459     push_ptr_value(def_ptr,&(t->type));
00460     if (v) {
00461       t->type=true;
00462       t->status=0;
00463     }
00464     else {
00465       t->type=false;
00466       t->status=0;
00467     }
00468   
00469     i_check_out(t);
00470     if (t->resid)
00471       release_resid(t);
00472   }
00473   else {
00474     Warningline("the persistent term '%P' appears in a boolean constraint and cannot be refined\n",t);
00475     }
00476     */
00477 }
00478 
00479 
00480 
00481 
00482 /******** UNIFY_REAL_RESULT(t,v)
00483   Unify psi_term T to the real value V.
00484   This is used by built-in arithmetic functions to return their result.
00485 */
00486 long unify_real_result(t,v)
00487 ptr_psi_term t;
00488 REAL v;
00489 {
00490   long smaller;
00491   long success=TRUE;
00492 
00493 #ifdef prlDEBUG
00494   if (t->value) {
00495     printf("*** BUG: value already present in UNIFY_REAL_RESULT\n");
00496   }
00497 #endif
00498 
00499   if((GENERIC)t<heap_pointer) { /*  RM: Jun  8 1993  */
00500     deref_ptr(t);
00501     assert(t->value==NULL); /* 10.6 */
00502     push_ptr_value(int_ptr,&(t->value));
00503     t->value=heap_alloc(sizeof(REAL)); /* 12.5 */
00504     *(REAL *)t->value = v;
00505     
00506     matches(t->type,integer,&smaller);
00507     
00508     if (v==floor(v)){
00509       if (!smaller) {
00510         push_ptr_value(def_ptr,&(t->type));
00511         t->type=integer;
00512         t->status=0;
00513       }
00514     }
00515     else
00516       if (smaller)
00517         success=FALSE;
00518     
00519     if (success) {
00520       i_check_out(t);
00521       if (t->resid)
00522         release_resid(t);
00523     }
00524   }
00525   else {
00526     Warningline("the persistent term '%P' appears in an arithmetic constraint and cannot be refined\n",t);
00527   }
00528   
00529   return success;
00530 }
00531 
00532 
00533 
00534 /******** C_GT
00535   Greater than.
00536 */
00537 static long c_gt()
00538 {
00539   long success=TRUE;
00540   ptr_psi_term arg1,arg2,arg3,t;
00541   long num1,num2,num3;
00542   REAL val1,val2,val3;
00543   
00544   t=aim->a;
00545   deref_ptr(t);
00546   get_two_args(t->attr_list,&arg1,&arg2);
00547   arg3=aim->b;
00548   
00549   if (arg1) {
00550     deref(arg1);
00551     success=get_real_value(arg1,&val1,&num1);
00552     if(success && arg2) {
00553       deref(arg2);
00554       deref_args(t,set_1_2);
00555       success=get_real_value(arg2,&val2,&num2);
00556     }
00557   }
00558   
00559   if(success)
00560     if(arg1 && arg2) {
00561       deref(arg3);
00562       success=get_bool_value(arg3,&val3,&num3);
00563       if(success)
00564         switch(num1+num2*2+num3*4) {
00565         case 0:
00566           residuate2(arg1,arg2);
00567           break;
00568         case 1:
00569           residuate(arg2);
00570           break;
00571         case 2:
00572           residuate(arg1);
00573           break;
00574         case 3:
00575           unify_bool_result(arg3,(val1>val2));
00576           break;
00577         case 4:
00578           residuate2(arg1,arg2);
00579           break;
00580         case 5:
00581           residuate(arg2);
00582           break;
00583         case 6:
00584           residuate(arg1);
00585           break;
00586         case 7:
00587           success=(val3==(REAL)(val1>val2));
00588           break;
00589         } 
00590     }
00591     else
00592       curry();
00593   
00594   nonnum_warning(t,arg1,arg2);
00595   return success;
00596 }
00597 
00598 
00599 
00600 /******** C_EQUAL
00601   Arithmetic equality.
00602 */
00603 static long c_equal()
00604 {
00605   long success=TRUE;
00606   ptr_psi_term arg1,arg2,arg3,t;
00607   long num1,num2,num3;
00608   REAL val1,val2,val3;
00609   
00610   t=aim->a;
00611   deref_ptr(t);
00612   get_two_args(t->attr_list,&arg1,&arg2);
00613   arg3=aim->b;
00614   
00615   if(arg1) {
00616     deref(arg1);
00617     success=get_real_value(arg1,&val1,&num1);
00618     if(success && arg2) {
00619       deref(arg2);
00620       deref_args(t,set_1_2);
00621       success=get_real_value(arg2,&val2,&num2);
00622     }
00623   }
00624   
00625   if(success)
00626     if(arg1 && arg2) {
00627       deref(arg3);
00628       success=get_bool_value(arg3,&val3,&num3);
00629       if(success)
00630         switch(num1+2*num2+4*num3) {
00631         case 0:
00632           if(arg1==arg2)
00633             unify_bool_result(arg3,TRUE);
00634           else
00635             residuate2(arg1,arg2);
00636           break;
00637         case 1:
00638           residuate2(arg2,arg3);
00639           break;
00640         case 2:
00641           residuate2(arg1,arg3);
00642           break;
00643         case 3:
00644           unify_bool_result(arg3,(val1==val2));
00645           break;
00646         case 4:
00647           if(arg1==arg2 && !val3)
00648             success=FALSE;
00649           else
00650             residuate2(arg1,arg2);
00651           break;
00652         case 5:
00653           if(!val3)
00654             residuate(arg2);
00655           else
00656             success=unify_real_result(arg2,val1);
00657           break;
00658         case 6:
00659           if(!val3)
00660             residuate(arg1);
00661           else
00662             success=unify_real_result(arg1,val2);
00663           break;
00664         case 7:
00665           success=(val3==(REAL)(val1==val2));
00666           break;
00667         }
00668     }
00669     else
00670       curry();
00671   
00672   nonnum_warning(t,arg1,arg2);
00673   return success;
00674 }
00675 
00676 
00677 
00678 /*** RM: 9 Dec 1992 (START) ***/
00679 
00680 /******** C_EVAL_DISJUNCTION
00681   Evaluate a disjunction.
00682   */
00683 
00684 static long c_eval_disjunction()
00685      
00686 {
00687   ptr_psi_term arg1,arg2,funct,result;
00688 
00689   
00690   funct=aim->a;
00691   deref_ptr(funct);
00692   result=aim->b;
00693   get_two_args(funct->attr_list,&arg1,&arg2);
00694 
00695   /* deref_args(funct,set_1_2); Don't know about this */
00696   
00697   if (arg1 && arg2) {
00698     deref_ptr(arg1);
00699     deref_ptr(arg2);
00700 
00701     resid_aim=NULL; /* Function evaluation is over */
00702 
00703     if(arg2->type!=disj_nil) /*  RM: Feb  1 1993  */
00704       /* Create the alternative */
00705       push_choice_point(eval,arg2,result,funct->type->rule);
00706     
00707     /* Unify the result with the first argument */
00708     push_goal(unify,result,arg1,NULL);
00709     i_check_out(arg1);
00710   }
00711   else {
00712     Errorline("malformed disjunction '%P'\n",funct);
00713     return (c_abort());
00714   }
00715   
00716   return TRUE;
00717 }
00718 
00719 /*** RM: 9 Dec 1992 (END) ***/
00720 
00721   
00722 
00723 
00724   
00725 /******** C_LT
00726   Less than.
00727 */
00728 static long c_lt()
00729 {
00730   long success=TRUE;
00731   ptr_psi_term arg1,arg2,arg3,t;
00732   long num1,num2,num3;
00733   REAL val1,val2,val3;
00734   
00735   t=aim->a;
00736   deref_ptr(t);
00737   get_two_args(t->attr_list,&arg1,&arg2);
00738   arg3=aim->b;
00739   
00740   if(arg1) {
00741     deref(arg1);
00742     success=get_real_value(arg1,&val1,&num1);
00743     if(success && arg2) {
00744       deref(arg2);
00745       deref_args(t,set_1_2);
00746       success=get_real_value(arg2,&val2,&num2);
00747     }
00748   }
00749   
00750   if(success)
00751     if(arg1 && arg2) {
00752       deref(arg3);
00753       success=get_bool_value(arg3,&val3,&num3);
00754       if(success)
00755         switch(num1+num2*2+num3*4) {
00756         case 0:
00757           residuate2(arg1,arg2);
00758           break;
00759         case 1:
00760           residuate(arg2);
00761           break;
00762         case 2:
00763           residuate(arg1);
00764           break;
00765         case 3:
00766           unify_bool_result(arg3,(val1<val2));
00767           break;
00768         case 4:
00769           residuate2(arg1,arg2);
00770           break;
00771         case 5:
00772           residuate(arg2);
00773           break;
00774         case 6:
00775           residuate(arg1);
00776           break;
00777         case 7:
00778           success=(val3==(REAL)(val1<val2));
00779           break;
00780         }
00781     }
00782     else
00783       curry();
00784   
00785   nonnum_warning(t,arg1,arg2);
00786   return success;
00787 }
00788 
00789 
00790 
00791 
00792 /******** C_GTOE
00793   Greater than or equal.
00794 */
00795 static long c_gtoe()
00796 {
00797   long success=TRUE;
00798   ptr_psi_term arg1,arg2,arg3,t;
00799   long num1,num2,num3;
00800   REAL val1,val2,val3;
00801   
00802   t=aim->a;
00803   deref_ptr(t);
00804   get_two_args(t->attr_list,&arg1,&arg2);
00805   arg3=aim->b;
00806   
00807   if(arg1) {
00808     deref(arg1);
00809     success=get_real_value(arg1,&val1,&num1);
00810     if(success && arg2) {
00811       deref(arg2);
00812       deref_args(t,set_1_2);
00813       success=get_real_value(arg2,&val2,&num2);
00814     }
00815   }
00816   
00817   if(success)
00818     if(arg1 && arg2) {
00819       deref(arg3);
00820       success=get_bool_value(arg3,&val3,&num3);
00821       if(success)
00822         switch(num1+num2*2+num3*4) {
00823         case 0:
00824           residuate2(arg1,arg2);
00825           break;
00826         case 1:
00827           residuate(arg2);
00828           break;
00829         case 2:
00830           residuate(arg1);
00831           break;
00832         case 3:
00833           unify_bool_result(arg3,(val1>=val2));
00834           break;
00835         case 4:
00836           residuate2(arg1,arg2);
00837           break;
00838         case 5:
00839           residuate(arg2);
00840           break;
00841         case 6:
00842           residuate(arg1);
00843           break;
00844         case 7:
00845           success=(val3==(REAL)(val1>=val2));
00846           break;
00847         }      
00848     }
00849     else
00850       curry();
00851   
00852   nonnum_warning(t,arg1,arg2);
00853   return success;
00854 }
00855 
00856 
00857 
00858 /******** C_LTOE
00859   Less than or equal.
00860 */
00861 static long c_ltoe()
00862 {
00863   long success=TRUE;
00864   ptr_psi_term arg1,arg2,arg3,t;
00865   long num1,num2,num3;
00866   REAL val1,val2,val3;
00867   
00868   t=aim->a;
00869   deref_ptr(t);
00870   get_two_args(t->attr_list,&arg1,&arg2);
00871   arg3=aim->b;
00872   
00873   if(arg1) {
00874     deref(arg1);
00875     success=get_real_value(arg1,&val1,&num1);
00876     if(success && arg2) {
00877       deref(arg2);
00878       deref_args(t,set_1_2);
00879       success=get_real_value(arg2,&val2,&num2);
00880     }
00881   }
00882   
00883   if(success)
00884     if(arg1 && arg2) {
00885       deref(arg3);
00886       success=get_bool_value(arg3,&val3,&num3);
00887       if(success)
00888         switch(num1+num2*2+num3*4) {
00889         case 0:
00890           residuate2(arg1,arg2);
00891           break;
00892         case 1:
00893           residuate(arg2);
00894           break;
00895         case 2:
00896           residuate(arg1);
00897           break;
00898         case 3:
00899           unify_bool_result(arg3,(val1<=val2));
00900           break;
00901         case 4:
00902           residuate2(arg1,arg2);
00903           break;
00904         case 5:
00905           residuate(arg2);
00906           break;
00907         case 6:
00908           residuate(arg1);
00909           break;
00910         case 7:
00911           success=(val3==(REAL)(val1<=val2));
00912           break;
00913         }
00914     }
00915     else
00916       curry();
00917   
00918   nonnum_warning(t,arg1,arg2);
00919   return success;
00920 }
00921 
00922 
00923 
00924 
00925 /******** C_BOOLPRED
00926   Internal built-in predicate that handles functions in predicate positions.
00927   This predicate should never be called directly by the user.
00928 */
00929 
00930 static long c_boolpred()
00931 {
00932   long success=TRUE,succ,lesseq;
00933   ptr_psi_term t,arg1;
00934 
00935   t=aim->a;
00936   deref_ptr(t);
00937   get_one_arg(t->attr_list,&arg1);
00938   if (arg1) {
00939     deref(arg1);
00940     deref_args(t,set_1);
00941     if (sub_type(boolean,arg1->type)) {
00942       residuate(arg1);
00943     }
00944     else {
00945       succ=matches(arg1->type,true,&lesseq);
00946       if (succ) {
00947         if (lesseq) {
00948           /* Function returns true: success. */
00949         }
00950         else
00951           residuate(arg1);
00952       }
00953       else {
00954         succ=matches(arg1->type,false,&lesseq);
00955         if (succ) {
00956           if (lesseq) {
00957             /* Function returns false: failure. */
00958             success=FALSE;
00959           }
00960           else
00961             residuate(arg1);
00962         }
00963         else {
00964           /* Both true and false are disentailed. */
00965           if (arg1->type->type==predicate) {
00966             push_goal(prove,arg1,DEFRULES,NULL);
00967           }
00968           else {
00969             Errorline("function result '%P' should be a boolean or a predicate.\n",
00970                       arg1);
00971             return (c_abort());
00972           }
00973         }
00974       }
00975     }
00976   }
00977   else {
00978     Errorline("missing argument to '*boolpred*'.\n");
00979     return (c_abort());
00980   }
00981 
00982   return success;
00983 }
00984 
00985 static long get_bool(typ)
00986 ptr_definition typ;
00987 {
00988   if (sub_type(typ,true)) return TRUE;
00989   else if (sub_type(typ,false)) return FALSE;
00990   else return UNDEF;
00991 }
00992 
00993 static long unify_bool(arg)
00994 ptr_psi_term arg;
00995 {
00996   ptr_psi_term tmp;
00997 
00998   tmp=stack_psi_term(4);
00999   tmp->type=boolean;
01000   push_goal(unify,tmp,arg,NULL);
01001 }
01002 
01003 /* Main routine to handle the and & or functions. */
01004 /* sel = TRUE (for and) or FALSE (for or) */
01005 static long c_logical_main(sel)
01006 long sel;
01007 {
01008   long success=TRUE;
01009   ptr_psi_term funct,arg1,arg2,arg3;
01010   long sm1, sm2, sm3;
01011   long a1comp, a2comp, a3comp;
01012   long a1, a2, a3;
01013 
01014   funct=aim->a;
01015   deref_ptr(funct);
01016   get_two_args(funct->attr_list,&arg1,&arg2);
01017   if (arg1 && arg2) {
01018     deref(arg1);
01019     deref(arg2);
01020     deref_args(funct,set_1_2);
01021     arg3=aim->b;
01022     deref(arg3);
01023 
01024     a1comp = matches(arg1->type,boolean,&sm1);
01025     a2comp = matches(arg2->type,boolean,&sm2);
01026     a3comp = matches(arg3->type,boolean,&sm3);
01027     if (a1comp && a2comp && a3comp) {
01028       a1 = get_bool(arg1->type);
01029       a2 = get_bool(arg2->type);
01030       a3 = get_bool(arg3->type);
01031       if (a1== !sel || a2== !sel) {
01032         unify_bool_result(arg3,!sel);
01033       } else if (a1==sel) {
01034         /* tmp=stack_psi_term(4); */
01035         /* tmp->type=boolean; */
01036         /* push_goal(unify,tmp,arg3,NULL); */
01037         push_goal(unify,arg2,arg3,NULL);
01038       } else if (a2==sel) {
01039         /* tmp=stack_psi_term(4); */
01040         /* tmp->type=boolean; */
01041         /* push_goal(unify,tmp,arg3,NULL); */
01042         push_goal(unify,arg1,arg3,NULL);
01043       } else if (a3==sel) {
01044         unify_bool_result(arg1,sel);
01045         unify_bool_result(arg2,sel);
01046       } else if (arg1==arg2) {
01047         /* tmp=stack_psi_term(4); */
01048         /* tmp->type=boolean; */
01049         /* push_goal(unify,tmp,arg3,NULL); */
01050         push_goal(unify,arg1,arg3,NULL);
01051       } else {
01052         if (a1==UNDEF) residuate(arg1);
01053         if (a2==UNDEF) residuate(arg2);
01054         if (a3==UNDEF) residuate(arg3);
01055       }
01056       if (!sm1) unify_bool(arg1);
01057       if (!sm2) unify_bool(arg2);
01058       if (!sm3) unify_bool(arg3);
01059     }
01060     else {
01061       success=FALSE;
01062       Errorline("Non-boolean argument or result in '%P'.\n",funct);
01063     }
01064   }
01065   else
01066     curry();
01067 
01068   return success;
01069 }
01070 
01071 
01072 
01073 
01074 /******** C_AND, C_OR
01075   Logical and & or.
01076   These functions do all possible local propagations.
01077 */
01078 static long c_and()
01079 {
01080   return c_logical_main(TRUE);
01081 }
01082 
01083 static long c_or()
01084 {
01085   return c_logical_main(FALSE);
01086 }
01087 
01088 
01089 
01090 
01091 /******** C_NOT
01092   Logical not.
01093   This function does all possible local propagations.
01094 */
01095 static long c_not()
01096 {
01097   long success=TRUE;
01098   ptr_psi_term funct,arg1,arg2;
01099   long sm1, sm2;
01100   long a1comp, a2comp;
01101   long a1, a2;
01102 
01103   funct=aim->a;
01104   deref_ptr(funct);
01105   get_one_arg(funct->attr_list,&arg1);
01106   if (arg1) {
01107     deref(arg1);
01108     deref_args(funct,set_1);
01109     arg2=aim->b;
01110     deref(arg2);
01111  
01112     a1comp = matches(arg1->type,boolean,&sm1);
01113     a2comp = matches(arg2->type,boolean,&sm2);
01114     if (a1comp && a2comp) {
01115       a1 = get_bool(arg1->type);
01116       a2 = get_bool(arg2->type);
01117       if (a1==TRUE || a1==FALSE) {
01118         unify_bool_result(arg2,!a1);
01119       } else if (a2==TRUE || a2==FALSE) {
01120         unify_bool_result(arg1,!a2);
01121       } else if (arg1==arg2) {
01122         success=FALSE;
01123       } else {
01124         if (a1==UNDEF) residuate(arg1);
01125         if (a2==UNDEF) residuate(arg2);
01126       }
01127       if (!sm1) unify_bool(arg1);
01128       if (!sm2) unify_bool(arg2);
01129     }
01130     else {
01131       success=FALSE;
01132       Errorline("Non-boolean argument or result in '%P'.\n",funct);
01133     }
01134   }
01135   else
01136     curry();
01137 
01138   return success;
01139 }
01140 
01141 
01142 
01143 
01144 /******** C_XOR
01145   Logical exclusive or.
01146   This function does all possible local propagations.
01147 */
01148 static long c_xor()
01149 {
01150   long success=TRUE;
01151   ptr_psi_term funct,arg1,arg2,arg3;
01152   long sm1, sm2, sm3;
01153   long a1comp, a2comp, a3comp;
01154   long a1, a2, a3;
01155 
01156   funct=aim->a;
01157   deref_ptr(funct);
01158   get_two_args(funct->attr_list,&arg1,&arg2);
01159   if (arg1 && arg2) {
01160     deref(arg1);
01161     deref(arg2);
01162     deref_args(funct,set_1_2);
01163     arg3=aim->b;
01164     deref(arg3);
01165 
01166     a1comp = matches(arg1->type,boolean,&sm1);
01167     a2comp = matches(arg2->type,boolean,&sm2);
01168     a3comp = matches(arg3->type,boolean,&sm3);
01169     if (a1comp && a2comp && a3comp) {
01170       a1 = get_bool(arg1->type);
01171       a2 = get_bool(arg2->type);
01172       a3 = get_bool(arg3->type);
01173       if ((a1==TRUE || a1==FALSE) && (a2==TRUE || a2==FALSE)) {
01174         unify_bool_result(arg3, a1^a2);
01175       } else if ((a1==TRUE || a1==FALSE) && (a3==TRUE || a3==FALSE)) {
01176         unify_bool_result(arg2, a1^a3);
01177       } else if ((a3==TRUE || a3==FALSE) && (a2==TRUE || a2==FALSE)) {
01178         unify_bool_result(arg1, a3^a2);
01179 
01180       } else if (a1==TRUE && arg3==arg2) {
01181         success=FALSE;
01182       } else if (a2==TRUE && arg3==arg2) {
01183         success=FALSE;
01184       } else if (a3==TRUE && arg1==arg2) {
01185         success=FALSE;
01186 
01187       } else if (a1==FALSE) {
01188         push_goal(unify,arg2,arg3,NULL);
01189       } else if (a2==FALSE) {
01190         push_goal(unify,arg1,arg3,NULL);
01191       } else if (a3==FALSE) {
01192         push_goal(unify,arg1,arg2,NULL);
01193 
01194       } else if (arg1==arg2) {
01195         unify_bool_result(arg3,FALSE);
01196       } else if (arg1==arg3) {
01197         unify_bool_result(arg2,FALSE);
01198       } else if (arg3==arg2) {
01199         unify_bool_result(arg1,FALSE);
01200       } else {
01201         if (a1==UNDEF) residuate(arg1);
01202         if (a2==UNDEF) residuate(arg2);
01203         if (a3==UNDEF) residuate(arg3);
01204       }
01205       if (!sm1) unify_bool(arg1);
01206       if (!sm2) unify_bool(arg2);
01207       if (!sm3) unify_bool(arg3);
01208     }
01209     else {
01210       success=FALSE;
01211       Errorline("Non-boolean argument or result in '%P'.\n",funct);
01212     }
01213   }
01214   else
01215     curry();
01216 
01217   return success;
01218 }
01219 
01220 
01221 
01222 
01223 /******** C_APPLY
01224   This evaluates "apply(functor => F,Args)".  If F is
01225   a known function, then it builds the psi-term F(Args), and evaluates it.
01226 */
01227 static long c_apply()
01228 {
01229   long success=TRUE;
01230   ptr_psi_term funct,other;
01231   ptr_node n,fattr;
01232   
01233   funct=aim->a;
01234   deref_ptr(funct);
01235   n=find(featcmp,functor->keyword->symbol,funct->attr_list);
01236   if (n) {
01237     other=(ptr_psi_term )n->data;
01238     deref(other);
01239     if (other->type==top)
01240       residuate(other);
01241     else
01242       if(other->type && other->type->type!=function) {
01243         success=FALSE;
01244         Errorline("argument is not a function in %P.\n",funct);
01245       }
01246       else {
01247         /* What we really want here is to merge all attributes in       */
01248         /* funct->attr_list, except '*functor*', into other->attr_list. */
01249         clear_copy();
01250         other=distinct_copy(other);
01251         fattr=distinct_tree(funct->attr_list); /* Make distinct copy: PVR */
01252         push_goal(eval,other,aim->b,other->type->rule);
01253         merge_unify(&(other->attr_list),fattr);
01254         /* We don't want to remove anything from funct->attr_list here. */
01255         delete_attr(functor->keyword->symbol,&(other->attr_list));
01256       }
01257   }
01258   else
01259     curry();
01260   
01261   return success;
01262 }
01263 
01264 
01265 
01266 /******** C_PROJECT   /*  RM: Jan  7 1993 
01267   Here we evaluate "project(Psi-term,Label)". This
01268   returns the psi-term associated to label Label in Psi-term.
01269   It is identical to C_PROJECT except that the order of the arguments is
01270   inversed.
01271 */
01272 static long c_project()
01273 
01274 {
01275   long success=TRUE;
01276   ptr_psi_term arg1,arg2,funct,result;
01277   ptr_node n;
01278   char *label;
01279   double v;
01280  
01281   /* char *thebuffer="integer"; 18.5 */
01282   char thebuffer[20]; /* Maximum number of digits in an integer */
01283   
01284   funct=aim->a;
01285   deref_ptr(funct);
01286   result=aim->b;
01287   get_two_args(funct->attr_list,&arg1,&arg2);
01288   if (arg2 && arg1) {
01289     deref(arg1);
01290     deref(arg2);
01291     deref_args(funct,set_1_2);
01292     
01293     label=NULL;
01294 
01295     /*  RM: Jul 20 1993: Don't residuate on 'string' etc...  */
01296     if(arg2->type!=top) {
01297       if(arg2->value && sub_type(arg2->type,quoted_string)) /* 10.8 */
01298         label=(char *)arg2->value;
01299       else
01300         if(arg2->value && sub_type(arg2->type,integer)) { /* 10.8 */
01301           v= *(REAL *)arg2->value;
01302           if(v==floor(v)) {
01303             sprintf(thebuffer,"%ld",(long)v);
01304             label=heap_copy_string(thebuffer); /* A little voracious */
01305           }
01306           else { /*  RM: Jul 28 1993  */
01307             Errorline("non-integer numeric feature in %P\n",funct);
01308             return FALSE;
01309           }
01310         }
01311         else {
01312           if(arg2->type->keyword->private_feature) /*  RM: Mar 12 1993  */
01313             label=arg2->type->keyword->combined_name;
01314           else
01315             label=arg2->type->keyword->symbol; 
01316         }
01317     }
01318     
01319     if (label) {
01320       n=find(featcmp,label,arg1->attr_list);
01321       
01322       if (n)
01323         push_goal(unify,result,n->data,NULL);
01324       else if (arg1->type->type==function && !(arg1->flags&QUOTED_TRUE)) {
01325         Errorline("attempt to add a feature to curried function %P\n",
01326                   arg1);
01327         return FALSE;
01328       }
01329       else {
01330         deref_ptr(result);
01331         if((GENERIC)arg1>=heap_pointer) { /*  RM: Feb  9 1993  */
01332           if((GENERIC)result<heap_pointer)
01333             push_psi_ptr_value(result,&(result->coref));
01334           clear_copy();
01335           result->coref=inc_heap_copy(result);
01336           heap_insert(featcmp,label,&(arg1->attr_list),result->coref);
01337         }
01338         else {
01339     
01340 #ifdef ARITY  /*  RM: Mar 29 1993  */
01341           arity_add(arg1,label);
01342 #endif
01343           
01344           /*  RM: Mar 25 1993  */
01345           if(arg1->type->always_check || arg1->attr_list)
01346             bk_stack_insert(featcmp,label,&(arg1->attr_list),result);
01347           else {
01348             bk_stack_insert(featcmp,label,&(arg1->attr_list),result);
01349             fetch_def_lazy(arg1, arg1->type,arg1->type,NULL,NULL);
01350           }
01351           
01352           if (arg1->resid)
01353             release_resid(arg1);
01354         }
01355       } 
01356     }
01357     else
01358       residuate(arg2);
01359   }
01360   else
01361     curry();
01362   
01363   return success;
01364 }
01365 
01366 
01367 
01368 
01369 /******** C_DIFF
01370   Arithmetic not-equal.
01371 */
01372 static long c_diff()
01373 {
01374   long success=TRUE;
01375   ptr_psi_term arg1,arg2,arg3,t;
01376   long num1,num2,num3;
01377   REAL val1,val2,val3;
01378   
01379   t=aim->a;
01380   deref_ptr(t);
01381   get_two_args(t->attr_list,&arg1,&arg2);
01382   arg3=aim->b;
01383   
01384   if(arg1) {
01385     deref(arg1);
01386     success=get_real_value(arg1,&val1,&num1);
01387     if(success && arg2) {
01388       deref(arg2);
01389       deref_args(t,set_1_2);
01390       success=get_real_value(arg2,&val2,&num2);
01391     }
01392   }
01393   
01394   if(success)
01395     if(arg1 && arg2) {
01396       deref(arg3);
01397       success=get_bool_value(arg3,&val3,&num3);
01398       if(success)
01399         switch(num1+2*num2+4*num3) {
01400         case 0:
01401           if(arg1==arg2)
01402             unify_bool_result(arg3,FALSE);
01403           else
01404             residuate2(arg1,arg2);
01405           break;
01406         case 1:
01407           residuate2(arg2,arg3);
01408           break;
01409         case 2:
01410           residuate2(arg1,arg3);
01411           break;
01412         case 3:
01413           unify_bool_result(arg3,(val1!=val2));
01414           break;
01415         case 4:
01416           if(arg1==arg2 && val3)
01417             success=FALSE;
01418           else
01419             residuate2(arg1,arg2);
01420           break;
01421         case 5:
01422           if(val3)
01423             residuate(arg2);
01424           else
01425             success=unify_real_result(arg2,val1);
01426           break;
01427         case 6:
01428           if(val3)
01429             residuate(arg1);
01430           else
01431             success=unify_real_result(arg1,val2);
01432           break;
01433         case 7:
01434           success=(val3==(REAL)(val1!=val2));
01435           break;
01436         }
01437     }
01438     else
01439       curry();
01440   
01441   nonnum_warning(t,arg1,arg2);
01442   return success;
01443 }
01444 
01445 
01446 
01447 
01448 /******** C_FAIL
01449   Always fail.
01450 */
01451 static long c_fail()
01452 {
01453   return FALSE;
01454 }
01455 
01456 
01457 
01458 /******** C_SUCCEED
01459   Always succeed.
01460 */
01461 static long c_succeed()
01462 {
01463   ptr_psi_term t;
01464 
01465   t=aim->a;
01466   deref_args(t,set_empty);
01467   return TRUE;
01468 }
01469 
01470 
01471 
01472 /******** C_REPEAT
01473   Succeed indefinitely on backtracking.
01474 */
01475 static long c_repeat()
01476 {
01477   ptr_psi_term t;
01478 
01479   t=aim->a;
01480   deref_args(t,set_empty);
01481   push_choice_point(prove,t,DEFRULES,NULL);
01482   return TRUE;
01483 }
01484 
01485 
01486 /******** C_VAR
01487   Return true/false iff argument is/is not '@' (top with no attributes).
01488 */
01489 static long c_var()
01490 {
01491   long success=TRUE;
01492   ptr_psi_term arg1,result,g,other;
01493   
01494   g=aim->a;
01495   deref_ptr(g);
01496   result=aim->b;
01497   deref(result);
01498   get_one_arg(g->attr_list,&arg1);
01499   if (arg1) {
01500     deref(arg1);
01501     deref_args(g,set_1);
01502     other=stack_psi_term(4); /* 19.11 */
01503     other->type=((arg1->type==top)&&(arg1->attr_list==NULL))?true:false;
01504     resid_aim=NULL;
01505     push_goal(unify,result,other,NULL);
01506   }
01507   else {
01508     curry();
01509     /* Errorline("argument missing in %P.\n",t); */
01510     /* return c_abort(); */
01511   }
01512   
01513   return success;
01514 }
01515 
01516 
01517 /******** C_NONVAR
01518   Return true/false iff argument is not/is '@' (top with no attributes).
01519 */
01520 static long c_nonvar()
01521 {
01522   long success=TRUE;
01523   ptr_psi_term arg1,result,g,other;
01524   
01525   g=aim->a;
01526   deref_ptr(g);
01527   result=aim->b;
01528   deref(result);
01529   get_one_arg(g->attr_list,&arg1);
01530   if (arg1) {
01531     deref(arg1);
01532     deref_args(g,set_1);
01533     other=stack_psi_term(4); /* 19.11 */
01534     other->type=((arg1->type==top)&&(arg1->attr_list==NULL))?false:true;
01535     resid_aim=NULL;
01536     push_goal(unify,result,other,NULL);
01537   }
01538   else {
01539     curry();
01540     /* Errorline("argument missing in %P.\n",t); */
01541     /* return c_abort(); */
01542   }
01543   
01544   return success;
01545 }
01546 
01547 
01548 /******** C_IS_FUNCTION
01549   Succeed iff argument is a function (built-in or user-defined).
01550 */
01551 static long c_is_function()
01552 {
01553   long success=TRUE;
01554   ptr_psi_term arg1,result,g,other;
01555   
01556   g=aim->a;
01557   deref_ptr(g);
01558   result=aim->b;
01559   deref(result);
01560   get_one_arg(g->attr_list,&arg1);
01561   if (arg1) {
01562     deref(arg1);
01563     deref_args(g,set_1);
01564     other=stack_psi_term(4); /* 19.11 */
01565     other->type=(arg1->type->type==function)?true:false;
01566     resid_aim=NULL;
01567     push_goal(unify,result,other,NULL);
01568   }
01569   else {
01570     curry();
01571     /* Errorline("argument missing in %P.\n",t); */
01572     /* return c_abort(); */
01573   }
01574   
01575   return success;
01576 }
01577 
01578 
01579 /******** C_IS_PREDICATE
01580   Succeed iff argument is a predicate (built-in or user-defined).
01581 */
01582 static long c_is_predicate()
01583 {
01584   long success=TRUE;
01585   ptr_psi_term arg1,result,g,other;
01586   
01587   g=aim->a;
01588   deref_ptr(g);
01589   result=aim->b;
01590   deref(result);
01591   get_one_arg(g->attr_list,&arg1);
01592   if (arg1) {
01593     deref(arg1);
01594     deref_args(g,set_1);
01595     other=stack_psi_term(4); /* 19.11 */
01596     other->type=(arg1->type->type==predicate)?true:false;
01597     resid_aim=NULL;
01598     push_goal(unify,result,other,NULL);
01599   }
01600   else {
01601     curry();
01602     /* Errorline("argument missing in %P.\n",t); */
01603     /* return c_abort(); */
01604   }
01605   
01606   return success;
01607 }
01608 
01609 
01610 /******** C_IS_SORT
01611   Succeed iff argument is a sort (built-in or user-defined).
01612 */
01613 static long c_is_sort()
01614 {
01615   long success=TRUE;
01616   ptr_psi_term arg1,result,g,other;
01617   
01618   g=aim->a;
01619   deref_ptr(g);
01620   result=aim->b;
01621   deref(result);
01622   get_one_arg(g->attr_list,&arg1);
01623   if (arg1) {
01624     deref(arg1);
01625     deref_args(g,set_1);
01626     other=stack_psi_term(4); /* 19.11 */
01627     other->type=(arg1->type->type==type)?true:false;
01628     resid_aim=NULL;
01629     push_goal(unify,result,other,NULL);
01630   }
01631   else {
01632     curry();
01633     /* Errorline("argument missing in %P.\n",t); */
01634     /* return c_abort(); */
01635   }
01636   
01637   return success;
01638 }
01639 
01640 
01641 
01642 /* Return TRUE iff t has only argument "1", and return the argument. */
01643 long only_arg1(t, arg1)
01644 ptr_psi_term t;
01645 ptr_psi_term *arg1;
01646 {
01647   ptr_node n=t->attr_list;
01648 
01649   if (n && n->left==NULL && n->right==NULL && !featcmp(n->key,one)) {
01650     *arg1=(ptr_psi_term)n->data;
01651     return TRUE;
01652   }
01653   else
01654     return FALSE;
01655 }
01656 
01657 
01658 
01659 /******** C_DYNAMIC()
01660   Mark all the arguments as 'unprotected', i.e. they may be changed
01661   by assert/retract/redefinition.
01662 */
01663 static long c_dynamic()
01664 {
01665   ptr_psi_term t=aim->a;
01666   deref_ptr(t);
01667   /* mark_quote(t); 14.9 */
01668   assert_protected(t->attr_list,FALSE);
01669   return TRUE;
01670 }
01671 
01672 
01673 
01674 /******** C_STATIC()
01675   Mark all the arguments as 'protected', i.e. they may not be changed
01676   by assert/retract/redefinition.
01677 */
01678 static long c_static()
01679 {
01680   ptr_psi_term t=aim->a;
01681   deref_ptr(t);
01682   /* mark_quote(t); 14.9 */
01683   assert_protected(t->attr_list,TRUE);
01684   return TRUE;
01685 }
01686 
01687 
01688 
01689 /******** C_DELAY_CHECK()
01690   Mark that the properties of the types in the arguments are delay checked
01691   during unification (i.e. they are only checked when the psi-term is
01692   given attributes, and they are not checked as long as the psi-term has
01693   no attributes.)
01694 */
01695 static long c_delay_check()
01696 {
01697   ptr_psi_term t=aim->a;
01698 
01699   deref_ptr(t);
01700   /* mark_quote(t); 14.9 */
01701   assert_delay_check(t->attr_list);
01702   inherit_always_check();
01703   return TRUE;
01704 }
01705 
01706 
01707 
01708 /******** C_NON_STRICT()
01709   Mark that the function or predicate's arguments are not evaluated when
01710   the function or predicate is called.
01711 */
01712 static long c_non_strict()
01713 {
01714   ptr_psi_term t=aim->a;
01715 
01716   deref_ptr(t);
01717   /* mark_quote(t); 14.9 */
01718   assert_args_not_eval(t->attr_list);
01719   return TRUE;
01720 }
01721 
01722 
01723 
01724 /******** C_OP()
01725   Declare an operator.
01726 */
01727 static long c_op()
01728 {
01729   long declare_operator();
01730   ptr_psi_term t=aim->a;
01731 
01732   return declare_operator(t);
01733 }
01734 
01735 
01736 
01737 long file_exists(s)
01738 char *s;
01739 {
01740   FILE *f;
01741   char *e;
01742   long success=FALSE;
01743   
01744   e=expand_file_name(s);
01745   if (f=fopen(e,"r")) {
01746     fclose(f);
01747     success=TRUE;
01748   }
01749   return success;
01750 }
01751 
01752 
01753 
01754 /******** C_EXISTS
01755   Succeed iff a file can be read in (i.e. if it exists).
01756 */
01757 static long c_exists()
01758 {
01759   ptr_psi_term g;
01760   ptr_node n;
01761   long success=TRUE;
01762   ptr_psi_term arg1; 
01763   char *c_arg1; 
01764 
01765   g=aim->a;
01766   deref_ptr(g);
01767 
01768   if (success) {
01769     n=find(featcmp,one,g->attr_list);
01770     if (n) {
01771       arg1= (ptr_psi_term )n->data;
01772       deref(arg1);
01773       deref_args(g,set_1);
01774       if (!psi_to_string(arg1,&c_arg1)) {
01775         success=FALSE;
01776         Errorline("bad argument in %P.\n",g);
01777       }
01778     }
01779     else {
01780       success=FALSE;
01781       Errorline("bad argument in %P.\n",g);
01782     }
01783   }
01784 
01785   if (success)
01786     success=file_exists(c_arg1);
01787 
01788   return success;
01789 }
01790 
01791 
01792 
01793 /******** C_LOAD
01794   Load a file.  This load accepts and executes any queries in the loaded
01795   file, including calls to user-defined predicates and other load predicates.
01796 */
01797 static long c_load()
01798 {
01799   long success=FALSE;
01800   ptr_psi_term arg1,arg2,t;
01801   char *fn;
01802 
01803   t=aim->a;
01804   deref_ptr(t);
01805   get_two_args(t->attr_list,&arg1,&arg2);
01806   if(arg1) {
01807     deref(arg1);
01808     deref_args(t,set_1);
01809     if (psi_to_string(arg1,&fn)) {
01810       success=open_input_file(fn);
01811       if (success) {
01812         file_date+=2;
01813         push_goal(load,input_state,file_date,fn);
01814         file_date+=2;
01815       }
01816     }
01817     else {
01818       Errorline("bad file name in %P.\n",t);
01819       success=FALSE;
01820     }
01821   }
01822   else {
01823     Errorline("no file name in %P.\n",t);
01824     success=FALSE;
01825   }
01826 
01827   return success;
01828 }
01829 
01830 
01831 
01832 /******** C_GET_CHOICE()
01833   Return the current state of the choice point stack (i.e., the time stamp
01834   of the current choice point).
01835 */
01836 static long c_get_choice()
01837 {
01838   long gts,success=TRUE;
01839   ptr_psi_term funct,result;
01840 
01841   funct=aim->a;
01842   deref_ptr(funct);
01843   result=aim->b;
01844   deref_args(funct,set_empty);
01845   if (choice_stack)
01846     gts=choice_stack->time_stamp;
01847   else
01848     gts=global_time_stamp-1;
01849     /* gts=INIT_TIME_STAMP; PVR 11.2.94 */
01850   push_goal(unify,result,real_stack_psi_term(4,(REAL)gts),NULL);
01851 
01852   return success;
01853 }
01854 
01855 
01856 
01857 /******** C_SET_CHOICE()
01858   Set the choice point stack to a state no later than (i.e. the same or earlier
01859   than) the state of the first argument (i.e., remove all choice points up to
01860   the first one whose time stamp is =< the first argument).  This predicate
01861   will remove zero or more choice points, never add them.  The first argument
01862   must come from a past call to get_choice.
01863   Together, get_choice and set_choice allow one to implement an "ancestor cut"
01864   that removes all choice points created between the current execution point
01865   and an execution point arbitarily remote in the past.
01866   The built-ins get_choice, set_choice, and exists_choice are implemented
01867   using the timestamping mechanism in the interpreter.  The two
01868   relevant properties of the timestamping mechanism are that each choice
01869   point is identified by an integer and that the integers are in increasing
01870   order (but not necessarily consecutive) from the bottom to the top of the
01871   choice point stack.
01872 */
01873 static long c_set_choice()
01874 {
01875   REAL gts_r;
01876   long gts;
01877   long num,success=TRUE;
01878   ptr_psi_term t,arg1;
01879   ptr_choice_point cutpt;
01880 
01881   t=aim->a;
01882   deref_ptr(t);
01883   get_one_arg(t->attr_list,&arg1);
01884   if (arg1) {
01885     deref(arg1);
01886     deref_args(t,set_1);
01887     success = get_real_value(arg1,&gts_r,&num);
01888     if (success) {
01889       if (num) {
01890         gts=(unsigned long)gts_r;
01891         if (choice_stack) {
01892           cutpt=choice_stack;
01893           while (cutpt && cutpt->time_stamp>gts) cutpt=cutpt->next;
01894           if (choice_stack!=cutpt) {
01895             choice_stack=cutpt;
01896 #ifdef CLEAN_TRAIL
01897             clean_trail(choice_stack);
01898 #endif
01899           }
01900         }
01901       }
01902       else {
01903         Errorline("bad argument to %P.\n",t);
01904         success=FALSE;
01905       }
01906     }
01907     else {
01908       Errorline("bad argument %P.\n",t);
01909       success=FALSE;
01910     }
01911   }
01912   else
01913     curry();
01914 
01915   return success;
01916 }
01917 
01918 
01919 
01920 /******** C_EXISTS_CHOICE()
01921   Return true iff there exists a choice point A such that arg1 < A <= arg2,
01922   i.e. A is more recent than the choice point marked by arg1 and no more
01923   recent than the choice point marked by arg2.  The two arguments to
01924   exists_choice must come from past calls to get_choice.
01925   This function allows one to check whether a choice point exists between
01926   any two arbitrary execution points of the program.
01927 */
01928 static long c_exists_choice()
01929 {
01930   REAL gts_r;
01931   long ans,gts1,gts2,num,success=TRUE;
01932   ptr_psi_term funct,result,arg1,arg2,ans_term;
01933   ptr_choice_point cp;
01934 
01935   funct=aim->a;
01936   deref_ptr(funct);
01937   result=aim->b;
01938   deref_args(funct,set_empty);
01939   get_two_args(funct->attr_list,&arg1,&arg2);
01940   if (arg1 && arg2) {
01941     deref(arg1);
01942     deref(arg2);
01943     deref_args(funct,set_1_2);
01944     success = get_real_value(arg1,&gts_r,&num);
01945     if (success && num) {
01946       gts1 = (unsigned long) gts_r;
01947       success = get_real_value(arg2,&gts_r,&num);
01948       if (success && num) {
01949         gts2 = (unsigned long) gts_r;
01950         cp = choice_stack;
01951         if (cp) {
01952           while (cp && cp->time_stamp>gts2) cp=cp->next;
01953           ans=(cp && cp->time_stamp>gts1);
01954         }
01955         else
01956           ans=FALSE;
01957         ans_term=stack_psi_term(4);
01958         ans_term->type=ans?true:false;
01959         push_goal(unify,result,ans_term,NULL);
01960       }
01961       else {
01962         Errorline("bad second argument to %P.\n",funct);
01963         success=FALSE;
01964       }
01965     }
01966     else {
01967       Errorline("bad first argument %P.\n",funct);
01968       success=FALSE;
01969     }
01970   }
01971   else
01972     curry();
01973 
01974   return success;
01975 }
01976 
01977 
01978 
01979 /******** C_PRINT_VARIABLES
01980   Print the global variables and their values,
01981   in the same way as is done in the user interface.
01982 */
01983 static long c_print_variables()
01984 {
01985   long success=TRUE;
01986 
01987   print_variables(TRUE); /* 21.1 */
01988 
01989   return success;
01990 }
01991 
01992 
01993 
01994 static void set_parse_queryflag(thelist, sort)
01995 ptr_node thelist;
01996 long sort;
01997 {
01998   ptr_node n;             /* node pointing to argument 2  */
01999   ptr_psi_term arg;       /* argumenrt 2 psi-term */
02000   ptr_psi_term queryflag; /* query term created by this function */
02001 
02002   n=find(featcmp,two,thelist);
02003   if (n) {
02004     /* there was a second argument */
02005     arg=(ptr_psi_term)n->data;
02006     queryflag=stack_psi_term(4);
02007     queryflag->type =
02008     update_symbol(bi_module,
02009                   ((sort==QUERY)?"query":
02010                   ((sort==FACT)?"declaration":"error")));
02011     push_goal(unify,queryflag,arg,NULL);
02012   }
02013 }
02014 
02015 
02016 /******** C_PARSE
02017   Parse a string and return a quoted psi-term.
02018   The global variable names are recognized (see the built-in
02019   print_variables).  All variables in the parsed string
02020   are added to the set of global variables.
02021 */
02022 static long c_parse()
02023 {
02024   long success=TRUE;
02025   ptr_psi_term arg1,arg2,arg3,funct,result;
02026   long smaller,sort,old_var_occurred;
02027   ptr_node n;
02028   parse_block pb;
02029 
02030   funct=aim->a;
02031   deref_ptr(funct);
02032   result=aim->b;
02033   get_one_arg(funct->attr_list,&arg1);
02034   if (arg1) {
02035     deref(arg1);
02036     deref_args(funct,set_1);
02037     success=matches(arg1->type,quoted_string,&smaller);
02038     if (success) {
02039       if (arg1->value) {
02040         ptr_psi_term t;
02041 
02042         /* Parse the string in its own state */
02043         save_parse_state(&pb);
02044         init_parse_state();
02045         stringparse=TRUE;
02046         stringinput=(char*)arg1->value;
02047 
02048         old_var_occurred=var_occurred;
02049         var_occurred=FALSE;
02050         t=stack_copy_psi_term(parse(&sort));
02051         
02052           /* Optional second argument returns 'query', 'declaration', or
02053           /* 'error'. */
02054           n=find(featcmp,two,funct->attr_list);
02055           if (n) {
02056             ptr_psi_term queryflag;
02057             arg2=(ptr_psi_term)n->data;
02058             queryflag=stack_psi_term(4);
02059             queryflag->type=
02060               update_symbol(bi_module,
02061                 ((sort==QUERY)?"query":((sort==FACT)?"declaration":"error"))
02062               );
02063             push_goal(unify,queryflag,arg2,NULL);
02064           }
02065   
02066           /* Optional third argument returns true or false if the psi-term
02067           /* contains a variable or not. */
02068           n=find(featcmp,three,funct->attr_list);
02069           if (n) {
02070             ptr_psi_term varflag;
02071             arg3=(ptr_psi_term)n->data;
02072             varflag=stack_psi_term(4);
02073             varflag->type=var_occurred?true:false;
02074             push_goal(unify,varflag,arg3,NULL);
02075           }
02076 
02077         var_occurred = var_occurred || old_var_occurred;
02078         stringparse=FALSE;
02079         restore_parse_state(&pb);
02080 
02081         /* parse_ok flag says whether there was a syntax error. */
02082         if (TRUE /*parse_ok*/) {
02083           mark_quote(t);
02084           push_goal(unify,t,result,NULL);
02085         }
02086         else
02087           success=FALSE;
02088       }
02089       else
02090         residuate(arg1);
02091     }
02092     else
02093       success=FALSE;
02094   }
02095   else
02096    curry();
02097 
02098   return success;
02099 }
02100 
02101 
02102 
02103 
02104 
02105 /******** C_READ
02106   Read a psi_term or a token from the current input stream.
02107   The variables in the object read are not added to the set
02108   of global variables.
02109 */
02110 
02111 static long c_read();
02112      
02113 static long c_read_psi() { return (c_read(TRUE)); }
02114 
02115 static long c_read_token() { return (c_read(FALSE)); }
02116 
02117 static long c_read(psi_flag)     
02118 long psi_flag;
02119 {
02120   long success=TRUE;
02121   long sort;
02122   ptr_psi_term arg1,arg2,arg3,g,t;
02123   ptr_node old_var_tree;
02124   ptr_node n;
02125   int line=line_count+1;
02126   
02127   g=aim->a;
02128   deref_ptr(g);
02129   get_one_arg(g->attr_list,&arg1);
02130   if (arg1) {
02131     deref_args(g,set_1);
02132     if (eof_flag) {
02133       Errorline("attempt to read past end of file (%E).\n");
02134       return (abort_life(TRUE));
02135     }
02136     else {
02137       prompt="";
02138       old_var_tree=var_tree;
02139       var_tree=NULL;
02140       if (psi_flag) {
02141         t=stack_copy_psi_term(parse(&sort));
02142 
02143 
02144         /* Optional second argument returns 'query', 'declaration', or
02145            'error'. */
02146         n=find(featcmp,two,g->attr_list); /*  RM: Jun  8 1993  */
02147         if (n) {
02148           ptr_psi_term queryflag;
02149           arg2=(ptr_psi_term)n->data;
02150           queryflag=stack_psi_term(4);
02151           queryflag->type=
02152             update_symbol(bi_module,
02153                           ((sort==QUERY)?"query":((sort==FACT)?"declaration":"error"))
02154                           );
02155           push_goal(unify,queryflag,arg2,NULL);
02156         }
02157 
02158 
02159         /* Optional third argument returns the starting line number */
02160         /*  RM: Oct 11 1993  */
02161         n=find(featcmp,three,g->attr_list);
02162         if (n) {
02163           arg3=(ptr_psi_term)n->data;
02164           g=stack_psi_term(4);
02165           g->type=integer;
02166           g->value=heap_alloc(sizeof(REAL));
02167           *(REAL *)g->value=line;
02168           push_goal(unify,g,arg3,NULL);
02169         }
02170         
02171       }
02172       else {
02173         t=stack_psi_term(0);
02174         read_token_b(t);
02175         /*  RM: Jan  5 1993  removed spurious argument: &quot (??) */
02176         
02177       }
02178       if (t->type==eof) eof_flag=TRUE;
02179       var_tree=old_var_tree;
02180     }
02181     
02182     if (success) {
02183       mark_quote(t);
02184       push_goal(unify,t,arg1,NULL);
02185       /* i_check_out(t); */
02186     }
02187   }
02188   else {
02189     Errorline("argument missing in %P.\n",g);
02190     success=FALSE;
02191   }
02192   
02193   return success;
02194 }
02195 
02196 
02197 
02198 /******** C_HALT
02199   Exit the Wild_Life interpreter.
02200 */
02201 int c_halt()   /*  RM: Jan  8 1993  Used to be 'void' */
02202 {
02203   exit_life(TRUE);
02204 }
02205 
02206 
02207 void exit_life(nl_flag)
02208 long nl_flag;
02209 {
02210   open_input_file("stdin");
02211   times(&life_end);
02212   if (NOTQUIET) { /* 21.1 */
02213     if (nl_flag) printf("\n");
02214     printf("*** Exiting Wild_Life  ");
02215 #ifndef OS2_PORT
02216     printf("[%1.3fs cpu, %1.3fs gc (%2.1f%%)]\n",
02217            (life_end.tms_utime-life_start.tms_utime)/60.0,
02218            garbage_time,
02219            garbage_time*100 / ((life_end.tms_utime-life_start.tms_utime)/60.0)
02220            );
02221 #else
02222     printf("[%1.3fs cpu, %1.3fs gc (%2.1f%%)]\n",
02223            (life_end-life_start)/60.0,
02224            garbage_time,
02225            garbage_time*100 / ((life_end-life_start)/60.0)
02226            );
02227 #endif
02228   }
02229 
02230 #ifdef ARITY  /*  RM: Mar 29 1993  */
02231   arity_end();
02232 #endif
02233   
02234   exit(1);
02235 }
02236 
02237 
02238 
02239 /******** C_ABORT
02240   Return to the top level of the interpreter.
02241 */
02242 long c_abort()   /*  RM: Feb 15 1993  */
02243 {
02244   return (abort_life(TRUE));
02245 }
02246 
02247 
02248 /* 26.1 */
02249 long abort_life(nlflag) /*  RM: Feb 15 1993  */
02250 int nlflag;
02251 {
02252   if ( aborthooksym->type!=function ||
02253        !aborthooksym->rule->b ||
02254        aborthooksym->rule->b->type==abortsym) {
02255     /* Do a true abort if aborthook is not a function or is equal to 'abort'.*/
02256     main_loop_ok = FALSE;
02257     undo(NULL); /* 8.10 */
02258     if(NOTQUIET) fprintf(stderr,"\n*** Abort"); /*  RM: Feb 17 1993  */
02259     if(NOTQUIET && nlflag) fprintf(stderr,"\n");/*  RM: Feb 17 1993  */
02260   } else {
02261     /* Do a 'user-defined abort': initialize the system, then */
02262     /* prove the user-defined abort routine (which is set by  */
02263     /* means of 'setq(aborthook,user_defined_abort)'.         */
02264     ptr_psi_term aborthook;
02265 
02266     undo(NULL);
02267     init_system();
02268     var_occurred=FALSE;
02269     stdin_cleareof();
02270     if(NOTQUIET) fprintf(stderr,"\n*** Abort"); /*  RM: Feb 17 1993  */
02271     if(NOTQUIET && nlflag) fprintf(stderr,"\n");/*  RM: Feb 17 1993  */
02272     aborthook=stack_psi_term(0);
02273     aborthook->type=aborthooksym;
02274     push_goal(prove,aborthook,DEFRULES,NULL);
02275   }
02276   return TRUE;
02277 }
02278 
02279 
02280 
02281 /******** C_NOT_IMPLEMENTED
02282   This function always fails, it is in fact identical to BOTTOM.
02283 */
02284 static long c_not_implemented()
02285 {
02286   ptr_psi_term t;
02287   
02288   t=aim->a;
02289   deref_ptr(t);
02290   Errorline("built-in %P is not implemented yet.\n",t);
02291   return FALSE;
02292 }
02293 
02294 
02295 
02296 /******** C_DECLARATION
02297   This function always fails, it is in fact identical to BOTTOM.
02298 */
02299 static long c_declaration()
02300 {
02301   ptr_psi_term t;
02302   
02303   t=aim->a;
02304   deref_ptr(t);
02305   Errorline("%P is a declaration, not a query.\n",t);
02306   return FALSE;
02307 }
02308 
02309 
02310 
02311 /******** C_SETQ
02312 
02313   Create a function with one rule F -> X, where F and X are the
02314   arguments of setq.  Setq evaluates its first argument and quotes the first.
02315   away any previous definition of F.  F must be undefined or a function, there
02316   is an error if F is a sort or a predicate.  This gives an error for a static
02317   function, but none for an undefined (i.e. uninterpreted) psi-term, which is
02318   made dynamic.  */
02319 
02320 
02321 static long c_setq()
02322 {
02323   long success=FALSE;
02324   ptr_psi_term arg1,arg2,g;
02325   ptr_pair_list p;
02326   ptr_definition d;
02327 
02328   g=aim->a;
02329   get_two_args(g->attr_list,&arg1,&arg2);
02330   if (arg1 && arg2) {
02331     deref_rec(arg2); /*  RM: Jan  6 1993  */
02332     deref_ptr(arg1);
02333     d=arg1->type;
02334     if (d->type==function || d->type==undef) {
02335       if (d->type==undef || !d->protected) {
02336         if (!arg1->attr_list) {
02337           d->type=function;
02338           d->protected=FALSE;
02339           p=HEAP_ALLOC(pair_list);
02340           p->a=heap_psi_term(4);
02341           p->a->type=d;
02342           clear_copy();
02343           p->b=quote_copy(arg2,HEAP);
02344           p->next=NULL;
02345           d->rule=p;
02346           success=TRUE;
02347         }
02348         else
02349          Errorline("%P may not have arguments in %P.\n",arg1,g);
02350       }
02351       else
02352         Errorline("%P should be dynamic in %P.\n",arg1,g);
02353     }
02354     else
02355       Errorline("%P should be a function or uninterpreted in %P.\n",arg1,g);
02356   }
02357   else
02358     Errorline("%P is missing one or both arguments.\n",g);
02359 
02360   return success;
02361 }
02362 
02363 
02364 
02365 /******** C_ASSERT_FIRST
02366   Assert a fact, inserting it as the first clause
02367   for that predicate or function.
02368 */
02369 static long c_assert_first()
02370 {
02371   long success=FALSE;
02372   ptr_psi_term arg1,g;
02373   
02374   g=aim->a;
02375   bk_mark_quote(g); /*  RM: Apr  7 1993  */
02376   get_one_arg(g->attr_list,&arg1);
02377   assert_first=TRUE;
02378   if (arg1) {
02379     deref_ptr(arg1);
02380     assert_clause(arg1);
02381     encode_types();
02382     success=assert_ok;
02383   }
02384   else {
02385     success=FALSE;
02386     Errorline("bad clause in %P.\n",g);
02387   }
02388   
02389   return success;
02390 }
02391 
02392 
02393 
02394 /******** C_ASSERT_LAST
02395   Assert a fact, inserting as the last clause for that predicate or function.
02396 */
02397 static long c_assert_last()
02398 {
02399   long success=FALSE;
02400   ptr_psi_term arg1,g;
02401   
02402   g=aim->a;
02403   bk_mark_quote(g); /*  RM: Apr  7 1993  */
02404   get_one_arg(g->attr_list,&arg1);
02405   assert_first=FALSE;
02406   if (arg1) {
02407     deref_ptr(arg1);
02408     assert_clause(arg1);
02409     encode_types();
02410     success=assert_ok;
02411   }
02412   else {
02413     success=FALSE;
02414     Errorline("bad clause in %P.\n",g);
02415   }
02416   
02417   return success;
02418 }
02419 
02420 
02421 
02422 /******** PRED_CLAUSE(t,r,g)
02423   Set about finding a clause that unifies with psi_term T.
02424   This routine is used both for CLAUSE and RETRACT.
02425   If R==TRUE then delete the first clause which unifies with T.
02426 */
02427 long pred_clause(t,r,g)
02428 ptr_psi_term t, g;
02429 long r;
02430 {
02431   long success=FALSE;
02432   ptr_psi_term head,body;
02433   
02434   bk_mark_quote(g); /*  RM: Apr  7 1993  */
02435   if (t) {
02436     deref_ptr(t);
02437     
02438     if (!strcmp(t->type->keyword->symbol,"->")) {
02439       get_two_args(t->attr_list,&head,&body);
02440       if (head) {
02441         deref_ptr(head);
02442         if (head && body &&
02443             (head->type->type==function || head->type->type==undef))
02444           success=TRUE;
02445       }
02446     }
02447     else if (!strcmp(t->type->keyword->symbol,":-")) {
02448       get_two_args(t->attr_list,&head,&body);
02449       if (head) {
02450         deref_ptr(head);
02451         if (head &&
02452             (head->type->type==predicate || head->type->type==undef)) {
02453           success=TRUE;
02454           if (!body) {
02455             body=stack_psi_term(4);
02456             body->type=succeed;
02457           }
02458         }
02459       }
02460     }
02461     /* There is no body, so t is a fact */
02462     else if (t->type->type==predicate || t->type->type==undef) {
02463       head=t;
02464       body=stack_psi_term(4);
02465       body->type=succeed;
02466       success=TRUE;
02467     }
02468   }
02469   
02470   if (success) {
02471     if (r) {
02472       if (redefine(head))
02473         push_goal(del_clause,head,body,&(head->type->rule));
02474       else
02475         success=FALSE;
02476     }
02477     else
02478       push_goal(clause,head,body,&(head->type->rule));
02479   }
02480   else
02481     Errorline("bad argument in %s.\n", (r?"retract":"clause"));
02482   
02483   return success;
02484 }
02485 
02486 
02487 
02488 /******** C_CLAUSE
02489   Find the clauses that unify with the argument in the rules.
02490   The argument must be a predicate or a function.
02491   Use PRED_CLAUSE to perform the search.
02492 */
02493 static long c_clause()
02494 {
02495   long success=FALSE;
02496   ptr_psi_term arg1,arg2,g;
02497   
02498   g=aim->a;
02499   get_two_args(g->attr_list,&arg1,&arg2);
02500   success=pred_clause(arg1,0,g);
02501   return success;
02502 }
02503 
02504 
02505 
02506 /******** C_RETRACT
02507   Retract the first clause that unifies with the argument.
02508   Use PRED_CLAUSE to perform the search.
02509 */
02510 static long c_retract()
02511 {
02512   long success=FALSE;
02513   ptr_psi_term arg1,arg2,g;
02514   
02515   g=aim->a;
02516   get_two_args(g->attr_list,&arg1,&arg2);
02517   success=pred_clause(arg1,1,g);
02518   
02519   return success;
02520 }
02521 
02522 
02523 void global_error_check();
02524 void global_tree();
02525 void global_one();
02526 
02527 /******** C_GLOBAL
02528   Declare that a symbol is a global variable.
02529   Handle multiple arguments and initialization
02530   (the initialization term is evaluated).
02531   If there is an error anywhere in the declaration,
02532   then evaluate and declare nothing.
02533 */
02534 static long c_global()    /*  RM: Feb 10 1993  */
02535 {
02536   long error=FALSE, eval=FALSE;
02537   ptr_psi_term g;
02538   
02539   g=aim->a;
02540   deref_ptr(g);
02541   if (g->attr_list) {
02542     /* Do error check of all arguments first: */
02543     global_error_check(g->attr_list, &error, &eval);
02544     if (eval) return !error;
02545     /* If no errors, then make the arguments global: */
02546     if (!error)
02547       global_tree(g->attr_list);
02548   } else {
02549     Errorline("argument(s) missing in %P\n",g);
02550   }
02551   
02552   return !error;
02553 }
02554 
02555 
02556 
02557 void global_error_check(n, error, eval)
02558 ptr_node n;
02559 int *error, *eval;
02560 {
02561   if (n) {
02562     ptr_psi_term t,a1,a2;
02563     int bad_init=FALSE;
02564     global_error_check(n->left, error, eval);
02565 
02566     t=(ptr_psi_term)n->data;
02567     deref_ptr(t);
02568     if (t->type==leftarrowsym) {
02569       get_two_args(t->attr_list,&a1,&a2);
02570       if (a1==NULL || a2==NULL) {
02571         Errorline("%P is an incorrect global variable declaration (%E).\n",t);
02572         *error=TRUE;
02573         bad_init=TRUE;
02574       } else {
02575         deref_ptr(a1);
02576         deref_ptr(a2);
02577         t=a1;
02578         if (deref_eval(a2)) *eval=TRUE;
02579       }
02580     }
02581     if (!bad_init && t->type->type!=undef && t->type->type!=global) {
02582       Errorline("%T %P cannot be redeclared as a global variable (%E).\n",
02583                 t->type->type,
02584                 t);
02585       t->type=error_psi_term->type;
02586       t->value=NULL; /*  RM: Mar 23 1993  */
02587       *error=TRUE;
02588     }
02589 
02590     global_error_check(n->right, error, eval);
02591   }
02592 }
02593 
02594 
02595 void global_tree(n)
02596 ptr_node n;
02597 {
02598   if (n) {
02599     ptr_psi_term t;
02600     global_tree(n->left);
02601 
02602     t=(ptr_psi_term)n->data;
02603     deref_ptr(t);
02604     global_one(t);
02605 
02606     global_tree(n->right);
02607   }
02608 }
02609 
02610 
02611 void global_one(t)
02612 ptr_psi_term t;
02613 {
02614   ptr_psi_term u,val;
02615 
02616   if (t->type==leftarrowsym) {
02617     get_two_args(t->attr_list,&t,&u);
02618     deref_ptr(t);
02619     deref_ptr(u);
02620   }
02621   else
02622     u=stack_psi_term(4);
02623   
02624   clear_copy();
02625   t->type->type=global;
02626   t->type->init_value=quote_copy(u,HEAP); /*  RM: Mar 23 1993  */
02627 
02628   /* eval_global_var(t);   RM: Feb  4 1994  */
02629   
02630   /*  RM: Nov 10 1993 
02631       val=t->type->global_value;
02632       if (val && (GENERIC)val<heap_pointer) {
02633       deref_ptr(val);
02634       push_psi_ptr_value(val,&(val->coref));
02635       val->coref=u;
02636       } else
02637       t->type->global_value=u;
02638   */
02639 }
02640 
02641 
02642 
02643 /******** C_PERSISTENT
02644   Declare that a symbol is a persistent variable.
02645 */
02646 static long c_persistent()     /*  RM: Feb 10 1993  */
02647 {
02648   long error=FALSE;
02649   ptr_psi_term g;
02650 
02651   g=aim->a;
02652   deref_ptr(g);
02653   if (g->attr_list) {
02654     /* Do error check of all arguments first: */
02655     persistent_error_check(g->attr_list, &error);
02656     /* If no errors, then make the arguments persistent: */
02657     if (!error)
02658       persistent_tree(g->attr_list);
02659   } else {
02660     Errorline("argument(s) missing in %P\n",g);
02661   }
02662 
02663   return !error;
02664 }
02665 
02666 
02667 persistent_error_check(n, error)
02668 ptr_node n;
02669 int *error;
02670 {
02671   if (n) {
02672     ptr_psi_term t;
02673     persistent_error_check(n->left, error);
02674 
02675     t=(ptr_psi_term)n->data;
02676     deref_ptr(t);
02677     if (t->type->type!=undef && t->type->type!=global) {
02678       Errorline("%T %P cannot be redeclared persistent (%E).\n",
02679                  t->type->type,
02680                  t);
02681       t->type=error_psi_term->type;
02682       *error=TRUE;
02683     }
02684 
02685     persistent_error_check(n->right, error);
02686   }
02687 }
02688 
02689 
02690 persistent_tree(n)
02691 ptr_node n;
02692 {
02693   if (n) {
02694     ptr_psi_term t;
02695     persistent_tree(n->left);
02696 
02697     t=(ptr_psi_term)n->data;
02698     deref_ptr(t);
02699     persistent_one(t);
02700 
02701     persistent_tree(n->right);
02702   }
02703 }
02704 
02705 
02706 persistent_one(t)
02707 ptr_psi_term t;
02708 {
02709   t->type->type=global;
02710   if ((GENERIC)t->type->global_value<(GENERIC)heap_pointer)
02711     t->type->global_value=heap_psi_term(4);
02712 }
02713 
02714 
02715 
02716 /******** C_OPEN_IN
02717   Create a stream for input from the specified file.
02718 */
02719 static long c_open_in()
02720 {
02721   long success=FALSE;
02722   ptr_psi_term arg1,arg2,g;
02723   char *fn;
02724   
02725   g=aim->a;
02726   deref_ptr(g);
02727   get_two_args(g->attr_list,&arg1,&arg2);
02728   if(arg1) {
02729     deref(arg1);
02730     if (psi_to_string(arg1,&fn))
02731       if (arg2) {
02732         deref(arg2);
02733         deref_args(g,set_1_2);
02734         if (is_top(arg2)) {
02735           if (open_input_file(fn)) {
02736             /* push_ptr_value(psi_term_ptr,&(arg2->coref)); 9.6 */
02737             push_psi_ptr_value(arg2,&(arg2->coref));
02738             arg2->coref=input_state;
02739             success=TRUE;
02740           }
02741           else
02742             success=FALSE;
02743         }
02744         else
02745           Errorline("bad input stream in %P.\n",g);
02746       }
02747       else
02748         Errorline("no stream in %P.\n",g);
02749     else
02750       Errorline("bad file name in %P.\n",g);
02751   }
02752   else
02753     Errorline("no file name in %P.\n",g);
02754 
02755   return success;
02756 }
02757 
02758 
02759 
02760 /******** C_OPEN_OUT
02761   Create a stream for output from the specified file.
02762 */
02763 static long c_open_out()
02764 {
02765   long success=FALSE;
02766   ptr_psi_term arg1,arg2,arg3,g;
02767   char *fn;
02768   
02769   g=aim->a;
02770   deref_ptr(g);
02771   get_two_args(g->attr_list,&arg1,&arg2);
02772   if(arg1) {
02773     deref(arg1);
02774     if (psi_to_string(arg1,&fn))
02775       if (arg2) {
02776         deref(arg2);
02777         deref(g);
02778         if (overlap_type(arg2->type,stream)) /* 10.8 */
02779           if (open_output_file(fn)) {
02780             arg3=stack_psi_term(4);
02781             arg3->type=stream;
02782             arg3->value=(GENERIC)output_stream;
02783             /* push_ptr_value(psi_term_ptr,&(arg2->coref)); 9.6 */
02784             push_psi_ptr_value(arg2,&(arg2->coref));
02785             arg2->coref=arg3;
02786             success=TRUE;
02787           }
02788           else
02789             success=FALSE;
02790         else
02791           Errorline("bad stream in %P.\n",g);
02792       }
02793       else
02794         Errorline("no stream in %P.\n",g);
02795     else
02796       Errorline("bad file name in %P.\n",g);
02797   }
02798   else
02799     Errorline("no file name in %P.\n",g);
02800   
02801   return success;
02802 }
02803 
02804 
02805 
02806 /******** C_SET_INPUT
02807   Set the current input stream to a given stream.
02808   If the given stream is closed, then do nothing.
02809 */
02810 static long c_set_input()
02811 {
02812   long success=FALSE;
02813   ptr_psi_term arg1,arg2,g;
02814   FILE *thestream;
02815   
02816   g=aim->a;
02817   deref_ptr(g);
02818   get_two_args(g->attr_list,&arg1,&arg2);
02819   if (arg1) {
02820     deref(arg1);
02821     deref_args(g,set_1);
02822     if (equal_types(arg1->type,inputfilesym)) {
02823       success=TRUE;
02824       save_state(input_state);
02825       thestream=get_stream(arg1);
02826       if (thestream!=NULL) {
02827         input_state=arg1;
02828         restore_state(input_state);
02829       }
02830     }
02831     else
02832       Errorline("bad stream in %P.\n",g);
02833   }
02834   else
02835     Errorline("no stream in %P.\n",g);
02836   
02837   return success;
02838 }
02839 
02840 
02841 
02842 /******** C_SET_OUTPUT
02843   Set the current output stream.
02844 */
02845 static long c_set_output()
02846 {
02847   long success=FALSE;
02848   ptr_psi_term arg1,arg2,g;
02849   
02850   g=aim->a;
02851   deref_ptr(g);
02852   get_two_args(g->attr_list,&arg1,&arg2);
02853   if(arg1) {
02854     deref(arg1);
02855     deref_args(g,set_1);
02856     if(equal_types(arg1->type,stream) && arg1->value) {
02857       success=TRUE;
02858       output_stream=(FILE *)arg1->value;
02859     }
02860     else
02861       Errorline("bad stream in %P.\n",g);
02862   }
02863   else
02864     Errorline("no stream in %P.\n",g);
02865   
02866   return success;
02867 }
02868 
02869 /******** C_CLOSE
02870   Close a stream.
02871 */
02872 static long c_close()
02873 {
02874   long success=FALSE;
02875   long inclose,outclose;
02876   ptr_psi_term arg1,arg2,g,s;
02877   
02878   g=aim->a;
02879   deref_ptr(g);
02880   get_two_args(g->attr_list,&arg1,&arg2);
02881   if (arg1) {
02882     deref(arg1);
02883     deref_args(g,set_1);
02884 /*
02885     if (sub_type(arg1->type,sys_stream))
02886       return sys_close(arg1);
02887 */
02888     outclose=equal_types(arg1->type,stream) && arg1->value;
02889     inclose=FALSE;
02890     if (equal_types(arg1->type,inputfilesym)) {
02891       ptr_node n=find(featcmp,STREAM,arg1->attr_list);
02892       if (n) {
02893         arg1=(ptr_psi_term)n->data;
02894         inclose=(arg1->value!=NULL);
02895       }
02896     }
02897 
02898     if (inclose || outclose) {
02899       success=TRUE;
02900       fclose((FILE *)arg1->value);
02901       
02902       if (inclose && arg1->value==(GENERIC)input_stream)
02903         open_input_file("stdin");
02904       else if (outclose && arg1->value==(GENERIC)output_stream)
02905         open_output_file("stdout");
02906       
02907       arg1->value=NULL;
02908     }
02909     else
02910       Errorline("bad stream in %P.\n",g);
02911   }
02912   else
02913     Errorline("no stream in %P.\n",g);
02914   
02915   return success;
02916 }
02917 
02918 
02919  
02920 
02921 /******** C_GET
02922   Read the next character from the current input stream and return
02923   its Ascii code.  This includes blank characters, so this predicate
02924   differs slightly from Edinburgh Prolog's get(X).
02925   At end of file, return the psi-term 'end_of_file'.
02926 */
02927 static long c_get()
02928 {
02929   long success=TRUE;
02930   ptr_psi_term arg1,arg2,g,t;
02931   long c;
02932   
02933   g=aim->a;
02934   deref_ptr(g);
02935   get_two_args(g->attr_list,&arg1,&arg2);
02936   if (arg1) {
02937     deref(arg1);
02938     deref_args(g,set_1);
02939 
02940     if (eof_flag) {
02941       success=FALSE;
02942     }
02943     else {
02944       prompt="";
02945       c=read_char();
02946       t=stack_psi_term(0);
02947       if (c==EOF) {
02948         t->type=eof;
02949         eof_flag=TRUE;
02950       }
02951       else {
02952         t->type=integer;
02953         t->value=heap_alloc(sizeof(REAL)); /* 12.5 */
02954         * (REAL *)t->value = (REAL) c;
02955       }
02956     }
02957     
02958     if (success) {
02959       push_goal(unify,t,arg1,NULL);
02960       i_check_out(t);
02961     }
02962   }
02963   else {
02964     Errorline("argument missing in %P.\n",g);
02965     success=FALSE;
02966   }
02967  
02968   return success;
02969 }
02970 
02971 
02972 
02973 /******** C_PUT, C_PUT_ERR
02974   Write the root of a psi-term to the current output stream or to stderr.
02975   This routine accepts the string type (which is written without quotes),
02976   a number type (whose integer part is considered an Ascii code if it is
02977   in the range 0..255), and any other psi-term (in which case its name is
02978   written).
02979 */
02980 static long c_put_main(); /* Forward declaration */
02981 
02982 static long c_put()
02983 {
02984   return c_put_main(FALSE);
02985 }
02986 
02987 static long c_put_err()
02988 {
02989   return c_put_main(TRUE);
02990 }
02991 
02992 static long c_put_main(to_stderr)
02993 long to_stderr;
02994 {
02995   long i,success=FALSE;
02996   ptr_psi_term arg1,arg2,g;
02997   char tstr[2], *str=tstr;
02998   
02999   g=aim->a;
03000   deref_ptr(g);
03001   get_two_args(g->attr_list,&arg1,&arg2);
03002   if (arg1) {
03003     deref(arg1);
03004     deref_args(g,set_1);
03005     if ((equal_types(arg1->type,integer) || equal_types(arg1->type,real))
03006         && arg1->value) {
03007       i = (unsigned long) floor(*(REAL *) arg1->value);
03008       if (i==(unsigned long)(unsigned char)i) {
03009         str[0] = i; str[1] = 0;
03010         success=TRUE;
03011       }
03012       else {
03013         Errorline("out-of-range character value in %P.\n",g);
03014       }
03015     }
03016     else if (psi_to_string(arg1,&str)) {
03017       success=TRUE;
03018     }
03019     if (success)
03020       fprintf((to_stderr?stderr:output_stream),"%s",str);
03021   }
03022   else
03023     Errorline("argument missing in %P.\n",g);
03024   
03025   return success;
03026 }
03027 
03028 
03029 
03030 /******** GENERIC_WRITE
03031   Implements write, writeq, pretty_write, pretty_writeq.
03032 */
03033 static long generic_write()
03034 {
03035   ptr_psi_term g;
03036 
03037   g=aim->a;
03038   /* deref_rec(g); */
03039   deref_args(g,set_empty);
03040   pred_write(g->attr_list);
03041   /* fflush(output_stream); */
03042   return TRUE;
03043 }
03044 
03045 /******** C_WRITE_ERR
03046   Write a list of arguments to stderr.  Print cyclical terms
03047   correctly, but don't use the pretty printer indentation.
03048 */
03049 static long c_write_err()
03050 {
03051   indent=FALSE;
03052   const_quote=FALSE;
03053   write_stderr=TRUE;
03054   write_corefs=FALSE;
03055   write_resids=FALSE;
03056   write_canon=FALSE;
03057   return generic_write();
03058 }
03059 
03060 /******** C_WRITEQ_ERR
03061   Write a list of arguments to stderr in a form that allows them to be
03062   read in again.  Print cyclical terms correctly, but don't use the pretty
03063   printer indentation.
03064 */
03065 static long c_writeq_err()
03066 {
03067   indent=FALSE;
03068   const_quote=TRUE;
03069   write_stderr=TRUE;
03070   write_corefs=FALSE;
03071   write_resids=FALSE;
03072   write_canon=FALSE;
03073   return generic_write();
03074 }
03075 
03076 /******** C_WRITE
03077   Write a list of arguments. Print cyclical terms
03078   correctly, but don't use the pretty printer indentation.
03079 */
03080 static long c_write()
03081 {
03082   indent=FALSE;
03083   const_quote=FALSE;
03084   write_stderr=FALSE;
03085   write_corefs=FALSE;
03086   write_resids=FALSE;
03087   write_canon=FALSE;
03088   return generic_write();
03089 }
03090 
03091 /******** C_WRITEQ
03092   Write a list of arguments in a form that allows them to be read in
03093   again.  Print cyclical terms correctly, but don't use the pretty
03094   printer indentation.
03095 */
03096 static long c_writeq()
03097 {
03098   indent=FALSE;
03099   const_quote=TRUE;
03100   write_stderr=FALSE;
03101   write_corefs=FALSE;
03102   write_resids=FALSE;
03103   write_canon=FALSE;
03104   return generic_write();
03105 }
03106 
03107 /******** C_WRITE_CANONICAL
03108   Write a list of arguments in a form that allows them to be read in
03109   again.  Print cyclical terms correctly, but don't use the pretty
03110   printer indentation.
03111 */
03112 static long c_write_canonical()
03113 {
03114   indent=FALSE;
03115   const_quote=TRUE;
03116   write_stderr=FALSE;
03117   write_corefs=FALSE;
03118   write_resids=FALSE;
03119   write_canon=TRUE;
03120   return generic_write();
03121 }
03122 
03123 /******** C_PRETTY_WRITE
03124   The same as write, only indenting if output is wider than PAGEWIDTH.
03125 */
03126 static long c_pwrite()
03127 {
03128   indent=TRUE;
03129   const_quote=FALSE;
03130   write_stderr=FALSE;
03131   write_corefs=FALSE;
03132   write_resids=FALSE;
03133   write_canon=FALSE;
03134   return generic_write();
03135 }
03136 
03137 
03138 /******** C_PRETTY_WRITEQ
03139   The same as writeq, only indenting if output is wider than PAGEWIDTH.
03140 */
03141 static long c_pwriteq()
03142 {
03143   indent=TRUE;
03144   const_quote=TRUE;
03145   write_stderr=FALSE;
03146   write_corefs=FALSE;
03147   write_resids=FALSE;
03148   write_canon=FALSE;
03149   return generic_write();
03150 }
03151 
03152 
03153 
03154 /******** C_PAGE_WIDTH
03155   Set the page width.
03156 */
03157 static long c_page_width()
03158 {
03159   long success=FALSE;
03160   ptr_psi_term arg1,arg2,g;
03161   long pw;
03162   
03163   g=aim->a;
03164   deref_ptr(g);
03165   get_two_args(g->attr_list,&arg1,&arg2);
03166   if(arg1) {
03167     deref(arg1);
03168     deref_args(g,set_1);
03169     if (equal_types(arg1->type,integer) && arg1->value) {
03170       pw = *(REAL *)arg1->value;
03171       if (pw>0)
03172         page_width=pw;
03173       else
03174         Errorline("argument in %P must be positive.\n",g);
03175       success=TRUE;
03176     }
03177     else if (sub_type(integer,arg1->type)) {
03178       push_goal(unify,arg1,real_stack_psi_term(4,(REAL)page_width),NULL);
03179       success=TRUE;
03180     }
03181     else
03182       Errorline("bad argument in %P.\n",g);
03183   }
03184   else
03185     Errorline("argument missing in %P.\n",g);
03186   
03187   return success;
03188 }
03189 
03190 
03191 
03192 /******** C_PRINT_DEPTH
03193   Set the depth limit of printing.
03194 */
03195 static long c_print_depth()
03196 {
03197   long success=FALSE;
03198   ptr_psi_term arg1,arg2,g;
03199   long dl;
03200   
03201   g=aim->a;
03202   deref_ptr(g);
03203   get_two_args(g->attr_list,&arg1,&arg2);
03204   if (arg1) {
03205     deref(arg1);
03206     deref_args(g,set_1);
03207     if (equal_types(arg1->type,integer) && arg1->value) {
03208       dl = *(REAL *)arg1->value;
03209       if (dl>=0)
03210         print_depth=dl;
03211       else
03212         Errorline("argument in %P must be positive or zero.\n",g);
03213       success=TRUE;
03214     }
03215     else if (sub_type(integer,arg1->type)) {
03216       push_goal(unify,arg1,real_stack_psi_term(4,(REAL)print_depth),NULL);
03217       success=TRUE;
03218     }
03219     else
03220       Errorline("bad argument in %P.\n",g);
03221   }
03222   else {
03223     /* No arguments: reset print depth to default value */
03224     print_depth=PRINT_DEPTH;
03225     success=TRUE;
03226   }
03227   
03228   return success;
03229 }
03230 
03231 
03232 
03233 /******** C_ROOTSORT
03234   Return the principal sort of the argument == create a copy with the
03235   attributes detached.
03236 */
03237 static long c_rootsort()
03238 {
03239   long success=TRUE;
03240   ptr_psi_term arg1,arg2,arg3,g,other;
03241   
03242   g=aim->a;
03243   deref_ptr(g);
03244   arg3=aim->b;
03245   deref(arg3);
03246   get_two_args(g->attr_list,&arg1,&arg2);
03247   if(arg1) {
03248     deref(arg1);
03249     deref_args(g,set_1);
03250     other=stack_psi_term(4); /* 19.11 */
03251     other->type=arg1->type;    
03252     other->value=arg1->value;
03253     resid_aim=NULL;
03254     push_goal(unify,arg3,other,NULL);
03255   }
03256   else
03257     curry();
03258   
03259   return success;
03260 }
03261 
03262 
03263 
03264 
03265 /******** C_DISJ
03266   This implements disjunctions (A;B).
03267   A nonexistent A or B is taken to mean 'fail'.
03268   Disjunctions should not be implemented in Life, because doing so results in
03269   both A and B being evaluated before the disjunction is.
03270   Disjunctions could be implemented in Life if there were a 'melt' predicate.
03271   */
03272 static long c_disj()
03273 {
03274   long success=TRUE;
03275   ptr_psi_term arg1,arg2,g;
03276 
03277   g=aim->a;
03278   resid_aim=NULL;
03279   deref_ptr(g);
03280   get_two_args(g->attr_list,&arg1,&arg2);
03281   deref_args(g,set_1_2);
03282   Traceline("pushing predicate disjunction choice point for %P\n",g);
03283   if (arg2) push_choice_point(prove,arg2,DEFRULES,NULL);
03284   if (arg1) push_goal(prove,arg1,DEFRULES,NULL);
03285   if (!arg1 && !arg2) {
03286     success=FALSE;
03287     Errorline("neither first nor second arguments exist in %P.\n",g);
03288   }
03289 
03290   return success;
03291 }
03292 
03293 
03294 
03295 /******** C_COND
03296   This implements COND(Condition,Then,Else).
03297   First Condition is evaluated.  If it returns true, return the Then value.
03298   If it returns false, return the Else value.  Either the Then or the Else
03299   values may be omitted, in which case they are considered to be true.
03300 */
03301 static long c_cond()
03302 {
03303   long success=TRUE;
03304   ptr_psi_term arg1,arg2,result,g;
03305   ptr_psi_term *arg1addr;
03306   REAL val1;
03307   long num1;
03308   ptr_node n;
03309   
03310   g=aim->a;
03311   deref_ptr(g);
03312   result=aim->b;
03313   deref(result);
03314   
03315   get_one_arg_addr(g->attr_list,&arg1addr);
03316   if (arg1addr) {
03317     arg1= *arg1addr;
03318     deref_ptr(arg1);
03319     if (arg1->type->type==predicate) {
03320       ptr_psi_term call_once;
03321       ptr_node ca;
03322 
03323       /* Transform cond(pred,...) into cond(call_once(pred),...) */
03324       goal_stack=aim;
03325       call_once=stack_psi_term(0);
03326       call_once->type=calloncesym;
03327       call_once->attr_list=(ca=STACK_ALLOC(node));
03328       ca->key=one;
03329       ca->left=ca->right=NULL;
03330       ca->data=(GENERIC)arg1;
03331       push_ptr_value(psi_term_ptr,arg1addr);
03332       *arg1addr=call_once;
03333       return success;
03334     }
03335     deref(arg1);
03336     deref_args(g,set_1_2_3);
03337     success=get_bool_value(arg1,&val1,&num1);
03338     if (success) {
03339       if (num1) {
03340         resid_aim=NULL;
03341         n=find(featcmp,(val1?two:three),g->attr_list);
03342         if (n) {
03343           arg2=(ptr_psi_term)n->data;
03344           /* mark_eval(arg2); XXX 24.8 */
03345           push_goal(unify,result,arg2,NULL);
03346           i_check_out(arg2);
03347         }
03348         else {
03349           ptr_psi_term trueterm;
03350           trueterm=stack_psi_term(4);
03351           trueterm->type=true;
03352           push_goal(unify,result,trueterm,NULL);
03353         }
03354       }
03355       else
03356         residuate(arg1);
03357     }
03358     else /*  RM: Apr 15 1993  */
03359       Errorline("argument to cond is not boolean in %P\n",g);
03360   }
03361   else
03362     curry();
03363   
03364   return success;
03365 }
03366 
03367 
03368 
03369 /******** C_EXIST_FEATURE
03370   Here we evaluate "has_feature(Label,Psi-term,Value)". This
03371   is a boolean function that returns true iff Psi-term
03372   has the feature Label.
03373 
03374   Added optional 3rd argument which is unified with the feature value if it exists.
03375   */
03376 
03377 static long c_exist_feature()  /*  PVR: Dec 17 1992  */  /* PVR 11.4.94 */
03378 {
03379   long success=TRUE,v;
03380   ptr_psi_term arg1,arg2,arg3,funct,result,ans;
03381   ptr_node n;
03382   char *label;
03383   /* char *thebuffer="integer"; 18.5 */
03384   char thebuffer[20]; /* Maximum number of digits in an integer */
03385 
03386   funct=aim->a;
03387   deref_ptr(funct);
03388   result=aim->b;
03389   get_two_args(funct->attr_list,&arg1,&arg2);
03390 
03391   
03392   n=find(featcmp,three,funct->attr_list,&arg3); /*  RM: Feb 10 1993  */
03393   if(n)
03394     arg3=(ptr_psi_term)n->data;
03395   else
03396     arg3=NULL;
03397   
03398   if (arg1 && arg2) {
03399     deref(arg1);
03400     deref(arg2);
03401     
03402     if(arg3) /*  RM: Feb 10 1993  */
03403       deref(arg3);
03404     
03405     deref_args(funct,set_1_2);
03406     label=NULL;
03407     
03408     if (arg1->value && sub_type(arg1->type,quoted_string))
03409       label=(char *)arg1->value;
03410     else if (arg1->value && sub_type(arg1->type,integer)) {
03411       v= *(REAL *)arg1->value;
03412       sprintf(thebuffer,"%ld",(long)v);
03413       label=heap_copy_string(thebuffer); /* A little voracious */
03414     } else if (arg1->type->keyword->private_feature) {
03415       label=arg1->type->keyword->combined_name;
03416     } else
03417       label=arg1->type->keyword->symbol;
03418 
03419     n=find(featcmp,label,arg2->attr_list);
03420     ans=stack_psi_term(4);
03421     ans->type=(n!=NULL)?true:false;
03422       
03423     if(arg3 && n) /*  RM: Feb 10 1993  */
03424       push_goal(unify,arg3,n->data,NULL);
03425       
03426     push_goal(unify,result,ans,NULL);
03427   }
03428   else
03429     curry();
03430 
03431   return success;
03432 }
03433 
03434 
03435 
03436 
03437 /******** C_FEATURES
03438   Convert the feature names of a psi_term into a list of psi-terms.
03439   This uses the MAKE_FEATURE_LIST routine.
03440 */
03441 static long c_features()
03442 {
03443   long success=TRUE;
03444   ptr_psi_term arg1,arg2,funct,result;
03445   ptr_psi_term the_list; /*  RM: Dec  9 1992
03446                              Modified the routine to use 'cons'
03447                              instead of the old list representation.
03448                              */
03449   /*  RM: Mar 11 1993  Added MODULE argument */
03450   ptr_module module=NULL;
03451   ptr_module save_current;
03452 
03453 
03454 
03455   
03456   funct=aim->a;
03457   deref_ptr(funct);
03458   result=aim->b;
03459   get_two_args(funct->attr_list,&arg1,&arg2);
03460 
03461   
03462   if(arg2) {
03463     deref(arg2);
03464     success=get_module(arg2,&module);
03465   }
03466   else
03467     module=current_module;
03468 
03469   
03470   if(arg1 && success) {
03471     deref(arg1);
03472     deref_args(funct,set_1);
03473     resid_aim=NULL;
03474 
03475     save_current=current_module;
03476     if(module)
03477       current_module=module;
03478     
03479     push_goal(unify,
03480               result,
03481               make_feature_list(arg1->attr_list,stack_nil(),module,0),
03482               NULL);
03483     
03484     current_module=save_current;
03485   }
03486   else
03487     curry();
03488   
03489   return success;
03490 }
03491 
03492 
03493 
03494 /******** C_FEATURES
03495   Return the list of values of the features of a term.
03496   */
03497 static long c_feature_values()
03498 {
03499   long success=TRUE;
03500   ptr_psi_term arg1,arg2,funct,result;
03501   ptr_psi_term the_list; /*  RM: Dec  9 1992
03502                              Modified the routine to use 'cons'
03503                              instead of the old list representation.
03504                              */
03505   /*  RM: Mar 11 1993  Added MODULE argument */
03506   ptr_module module=NULL;
03507   ptr_module save_current;
03508 
03509   
03510   funct=aim->a;
03511   deref_ptr(funct);
03512   result=aim->b;
03513   get_two_args(funct->attr_list,&arg1,&arg2);
03514 
03515   
03516   if(arg2) {
03517     deref(arg2);
03518     success=get_module(arg2,&module);
03519   }
03520   else
03521     module=current_module;
03522 
03523   
03524   if(arg1 && success) {
03525     deref(arg1);
03526     deref_args(funct,set_1);
03527     resid_aim=NULL;
03528 
03529     save_current=current_module;
03530     if(module)
03531       current_module=module;
03532     
03533     push_goal(unify,
03534               result,
03535               make_feature_list(arg1->attr_list,stack_nil(),module,1),
03536               NULL);
03537     
03538     current_module=save_current;
03539   }
03540   else
03541     curry();
03542   
03543   return success;
03544 }
03545 
03546 
03547 
03548 /* Return TRUE iff T is a type that should not show up as part of the
03549    type hierarchy, i.e. it is an internal hidden type. */
03550 long hidden_type(t)
03551 ptr_definition t;
03552 {
03553    return (/* (t==conjunction) || 19.8 */
03554            /* (t==disjunction) || RM: Dec  9 1992 */
03555            (t==constant) || (t==variable) ||
03556            (t==comment) || (t==functor));
03557 }
03558 
03559 
03560 
03561 /* Collect properties of the symbols in the symbol table, and make a
03562    psi-term list of them.
03563    This routine is parameterized (by sel) to collect three properties:
03564    1. All symbols that are types with no parents.
03565    2. All symbols that are of 'undef' type.
03566    3. The operator triples of all operators.
03567 
03568    Note the similarity between this routine and a tree-to-list
03569    routine in Prolog.  The pointer manipulations are simpler in
03570    Prolog, though.
03571 
03572    If the number of symbols is very large, this routine may run out of space
03573    before garbage collection.
03574 */
03575 ptr_psi_term collect_symbols(sel) /*  RM: Feb  3 1993  */
03576      long sel;
03577 
03578 {
03579   ptr_psi_term new;
03580   ptr_definition def;
03581   long botflag;
03582   ptr_psi_term result;
03583 
03584 
03585   result=stack_nil();
03586   
03587   for(def=first_definition;def;def=def->next) {
03588 
03589     if (sel==least_sel || sel==greatest_sel) {
03590       botflag=(sel==least_sel);
03591 
03592       /* Insert the node if it's a good one */
03593       if (((botflag?def->children:def->parents)==NULL &&
03594            def!=top && def!=nothing &&
03595            def->type==type ||
03596            def->type==undef)
03597           && !hidden_type(def)) {
03598         /* Create the node that will be inserted */
03599         new=stack_psi_term(4);
03600         new->type=def;
03601         result=stack_cons(new,result);
03602       }
03603     }
03604     else if (sel==op_sel) {
03605       ptr_operator_data od=def->op_data;
03606 
03607       while (od) {
03608         ptr_psi_term name,type;
03609 
03610         new=stack_psi_term(4);
03611         new->type=opsym;
03612         result=stack_cons(new,result);
03613         
03614         stack_add_int_attr(new,one,od->precedence);
03615 
03616         type=stack_psi_term(4);
03617         switch (od->type) {
03618         case xf:
03619           type->type=xf_sym;
03620           break;
03621         case yf:
03622           type->type=yf_sym;
03623           break;
03624         case fx:
03625           type->type=fx_sym;
03626           break;
03627         case fy:
03628           type->type=fy_sym;
03629           break;
03630         case xfx:
03631           type->type=xfx_sym;
03632           break;
03633         case xfy:
03634           type->type=xfy_sym;
03635           break;
03636         case yfx:
03637           type->type=yfx_sym;
03638           break;
03639         }
03640         stack_add_psi_attr(new,two,type);
03641 
03642         name=stack_psi_term(4);
03643         name->type=def;
03644         stack_add_psi_attr(new,three,name);
03645 
03646         od=od->next;
03647       }
03648     }
03649   }
03650   
03651   return result;
03652 }
03653 
03654 
03655 
03656 /******** C_OPS
03657   Return a list of all operators (represented as 3-tuples op(prec,type,atom)).
03658   This function has no arguments.
03659 */
03660 static long c_ops()
03661 {
03662   long success=TRUE;
03663   ptr_psi_term result, g, t;
03664 
03665   g=aim->a;
03666   deref_args(g,set_empty);
03667   result=aim->b;
03668   t=collect_symbols(op_sel);   /*  RM: Feb  3 1993  */
03669   push_goal(unify,result,t,NULL);
03670 
03671   return success;
03672 }
03673 
03674 
03675 
03676 
03677 /* PVR 23.2.94 -- Added this to fix c_strip and c_copy_pointer */
03678 /* Make a copy of an attr_list structure, keeping the same leaf pointers */
03679 static ptr_node copy_attr_list(n)
03680 ptr_node n;
03681 {
03682   ptr_node m;
03683 
03684   if (n==NULL) return NULL;
03685 
03686   m = STACK_ALLOC(node);
03687   m->key = n->key;
03688   m->data = n->data;
03689   m->left = copy_attr_list(n->left);
03690   m->right = copy_attr_list(n->right);
03691   return m;
03692 }
03693 
03694 
03695 /******** C_STRIP
03696   Return the attributes of a psi-term, that is, a psi-term of type @ but with
03697   all the attributes of the argument.
03698 */
03699 static long c_strip()
03700 {
03701   long success=TRUE;
03702   ptr_psi_term arg1,arg2,funct,result;
03703   
03704   funct=aim->a;
03705   deref_ptr(funct);
03706   result=aim->b;
03707   get_two_args(funct->attr_list,&arg1,&arg2);
03708   if(arg1) {
03709     deref(arg1);
03710     deref_args(funct,set_1);
03711     resid_aim=NULL;
03712     /* PVR 23.2.94 */
03713     merge_unify(&(result->attr_list),copy_attr_list(arg1->attr_list));
03714   }
03715   else
03716     curry();
03717   
03718   return success;
03719 }
03720 
03721 
03722 
03723 
03724 /******** C_SAME_ADDRESS
03725   Return TRUE if two arguments share the same address.
03726 */
03727 static long c_same_address()
03728 {
03729   long success=TRUE;
03730   ptr_psi_term arg1,arg2,funct,result;
03731   REAL val3;
03732   long num3;
03733   
03734   funct=aim->a;
03735   deref_ptr(funct);
03736   result=aim->b;
03737   get_two_args(funct->attr_list,&arg1,&arg2);
03738   
03739   if (arg1 && arg2) {
03740     success=get_bool_value(result,&val3,&num3);
03741     resid_aim=NULL;
03742     deref(arg1);
03743     deref(arg2);
03744     deref_args(funct,set_1_2);
03745     
03746     if (num3) {
03747       if (val3)
03748         push_goal(unify,arg1,arg2,NULL);
03749       else
03750         success=(arg1!=arg2);
03751     }
03752     else
03753       if (arg1==arg2)
03754         unify_bool_result(result,TRUE);
03755       else
03756         unify_bool_result(result,FALSE);
03757   }
03758   else
03759     curry();
03760   
03761   return success;
03762 }
03763 
03764 
03765 
03766 /******** C_DIFF_ADDRESS
03767   Return TRUE if two arguments have different addresses.
03768 */
03769 static long c_diff_address()
03770 {
03771   long success=TRUE;
03772   ptr_psi_term arg1,arg2,funct,result;
03773   REAL val3;
03774   long num3;
03775   
03776   funct=aim->a;
03777   deref_ptr(funct);
03778   result=aim->b;
03779   get_two_args(funct->attr_list,&arg1,&arg2);
03780   
03781   if (arg1 && arg2) {
03782     success=get_bool_value(result,&val3,&num3);
03783     resid_aim=NULL;
03784     deref(arg1);
03785     deref(arg2);
03786     deref_args(funct,set_1_2);
03787     
03788     if (num3) {
03789       if (val3)
03790         push_goal(unify,arg1,arg2,NULL);
03791       else
03792         success=(arg1==arg2);
03793     }
03794     else
03795       if (arg1==arg2)
03796         unify_bool_result(result,FALSE);
03797       else
03798         unify_bool_result(result,TRUE);
03799   }
03800   else
03801     curry();
03802   
03803   return success;
03804 }
03805 
03806 
03807 
03808 
03809 /******** C_EVAL
03810   Evaluate an expression and return its value.
03811 */
03812 static long c_eval()
03813 {
03814   long success=TRUE;
03815   ptr_psi_term arg1, copy_arg1, arg2, funct, result;
03816 
03817   funct = aim->a;
03818   deref_ptr(funct);
03819   result = aim->b;
03820   deref(result);
03821   get_two_args(funct->attr_list, &arg1, &arg2);
03822   if (arg1) {
03823     deref(arg1);
03824     deref_args(funct,set_1);
03825     assert((unsigned long)(arg1->type)!=4);
03826     clear_copy();
03827     copy_arg1 = eval_copy(arg1,STACK);
03828     resid_aim = NULL;
03829     push_goal(unify,copy_arg1,result,NULL);
03830     i_check_out(copy_arg1);
03831   } else
03832     curry();
03833 
03834   return success;
03835 }
03836 
03837 
03838 
03839 
03840 /******** C_EVAL_INPLACE
03841   Evaluate an expression and return its value.
03842 */
03843 static long c_eval_inplace()
03844 {
03845   long success=TRUE;
03846   ptr_psi_term arg1, copy_arg1, arg2, funct, result;
03847 
03848   funct = aim->a;
03849   deref_ptr(funct);
03850   result = aim->b;
03851   deref(result);
03852   get_two_args(funct->attr_list, &arg1, &arg2);
03853   if (arg1) {
03854     deref(arg1);
03855     deref_args(funct,set_1);
03856     resid_aim = NULL;
03857     mark_eval(arg1);
03858     push_goal(unify,arg1,result,NULL);
03859     i_check_out(arg1);
03860   } else
03861     curry();
03862 
03863   return success;
03864 }
03865 
03866 
03867 
03868 
03869 /******** C_QUOTE
03870   Quote an expression, i.e. do not evaluate it but mark it as completely
03871   evaluated.
03872   This works if the function is declared as non_strict.
03873 */
03874 static long c_quote()
03875 {
03876   long success=TRUE;
03877   ptr_psi_term arg1,arg2,funct,result;
03878 
03879   funct = aim->a;
03880   deref_ptr(funct);
03881   result = aim->b;
03882   deref(result);
03883   get_two_args(funct->attr_list, &arg1, &arg2);
03884   if (arg1) {
03885     push_goal(unify,arg1,result,NULL);
03886   } else
03887     curry();
03888 
03889   return success;
03890 }
03891 
03892 
03893 
03894 /******** C_SPLIT_DOUBLE
03895   Split a double into two 32-bit words.
03896   */
03897 
03898 static long c_split_double()
03899 {
03900   long success=FALSE;
03901   ptr_psi_term arg1,arg2,funct,result;
03902   int n;
03903   union {
03904     double d;
03905     struct {
03906       int hi;
03907       int lo;
03908     } w2;
03909   }hack;
03910   double hi,lo;
03911   int n1,n2;
03912   
03913   funct = aim->a;
03914   deref_ptr(funct);
03915   result=aim->b;
03916   
03917   get_two_args(funct->attr_list, &arg1, &arg2);
03918   if(arg1 && arg2) {
03919     deref_ptr(arg1);
03920     deref_ptr(arg2);
03921     deref_ptr(result);
03922     if(get_real_value(result,&(hack.d),&n)  &&
03923        get_real_value(arg1  ,&hi      ,&n1) &&
03924        get_real_value(arg2  ,&lo      ,&n2)) {
03925       
03926       
03927       if(n) {
03928         unify_real_result(arg1,(REAL)hack.w2.hi);
03929         unify_real_result(arg2,(REAL)hack.w2.lo);
03930         success=TRUE;
03931       }
03932       else
03933         if(n1 && n2) {
03934           hack.w2.hi=(int)hi;
03935           hack.w2.lo=(int)lo;
03936           unify_real_result(result,hack.d);
03937           success=TRUE;
03938         }
03939         else {
03940           residuate(result);
03941           residuate2(arg1,arg2);
03942         }
03943     }
03944     else
03945       Errorline("non-numeric arguments in %P\n",funct);
03946   }
03947   else
03948     curry();
03949   
03950   return success;
03951 }
03952 
03953 
03954 
03955 /******** C_STRING_ADDRESS
03956   Return the address of a string.
03957   */
03958 
03959 static long c_string_address()
03960 {
03961   long success=FALSE;
03962   ptr_psi_term arg1,arg2,funct,result,t;
03963   double val;
03964   int num;
03965   int smaller;
03966   
03967   
03968   funct = aim->a;
03969   deref_ptr(funct);
03970   result=aim->b;
03971   
03972   get_two_args(funct->attr_list, &arg1, &arg2);
03973   if(arg1) {
03974     deref_ptr(arg1);
03975     deref_ptr(result);
03976       success=matches(arg1->type,quoted_string,&smaller);
03977       if (success) {
03978         if (arg1->value) {
03979           unify_real_result(result,(REAL)(long)(arg1->value));
03980         }
03981         else {
03982           if(success=get_real_value(result,&val,&num)) {
03983             if(num) {
03984               t=stack_psi_term(4);
03985               t->type=quoted_string;
03986               t->value=(GENERIC)(long)val;
03987               push_goal(unify,t,arg1,NULL);
03988             }
03989             else
03990               residuate2(arg1,result);
03991           
03992           }
03993           else
03994             Errorline("result is not a real in %P\n",funct);
03995         }
03996       }
03997       else
03998         Errorline("argument is not a string in %P\n",funct);
03999   }
04000   else
04001     curry();
04002   
04003   return success;
04004 }
04005 
04006 
04007 
04008 /******** C_CHDIR
04009   Change the current working directory
04010   */
04011 
04012 static long c_chdir()
04013 {
04014   long success=FALSE;
04015   ptr_psi_term arg1,arg2,funct,result,t;
04016   double val;
04017   int num;
04018   int smaller;
04019   
04020   
04021   funct = aim->a;
04022   deref_ptr(funct);
04023   
04024   get_two_args(funct->attr_list, &arg1, &arg2);
04025   if(arg1) {
04026     deref_ptr(arg1);
04027     if(matches(arg1->type,quoted_string,&smaller) && arg1->value)
04028       success=!chdir(expand_file_name((char *)arg1->value));
04029     else
04030       Errorline("bad argument in %P\n",funct);
04031   }
04032   else
04033     Errorline("argument missing in %P\n",funct);
04034   
04035   return success;
04036 }
04037 
04038 
04039 
04040 /******** C_CALL_ONCE
04041   Prove a predicate, return true or false if it succeeds or fails.
04042   An implicit cut is performed: only only solution is given.
04043 */
04044 #if 0   /* DENYS Jan 25 1995 */
04045 static long c_call_once()
04046 {
04047   long success=TRUE;
04048   ptr_psi_term arg1,arg2,funct,result,other;
04049   ptr_choice_point cutpt; 
04050 
04051   funct=aim->a;
04052   deref_ptr(funct);
04053   result=aim->b;
04054   get_two_args(funct->attr_list,&arg1,&arg2);
04055   if (arg1) {
04056     deref_ptr(arg1);
04057     deref_args(funct,set_1);
04058     if(arg1->type==top)
04059       residuate(arg1);
04060     else
04061       if(FALSE /*arg1->type->type!=predicate*/) {
04062         success=FALSE;
04063         Errorline("argument of %P should be a predicate.\n",funct);
04064       }
04065       else {
04066         resid_aim=NULL;
04067         cutpt=choice_stack;
04068 
04069         /* Result is FALSE */
04070         other=stack_psi_term(0);
04071         other->type=false;
04072 
04073         push_choice_point(unify,result,other,NULL);
04074 
04075         /* Result is TRUE */
04076         other=stack_psi_term(0);
04077         other->type=true;
04078 
04079         push_goal(unify,result,other,NULL);
04080         push_goal(eval_cut,other,cutpt,NULL);
04081         push_goal(prove,arg1,DEFRULES,NULL);
04082       }
04083   }
04084   else
04085     curry();
04086 
04087   return success;
04088 }
04089 #endif
04090 
04091 
04092 
04093 /******** C_CALL
04094   Prove a predicate, return true or false if it succeeds or fails.
04095   No implicit cut is performed.
04096 */
04097 static long c_call()
04098 {
04099   long success=TRUE;
04100   ptr_psi_term arg1,arg2,funct,result,other;
04101   ptr_choice_point cutpt; 
04102 
04103   funct=aim->a;
04104   deref_ptr(funct);
04105   result=aim->b;
04106   get_two_args(funct->attr_list,&arg1,&arg2);
04107   if (arg1) {
04108     deref_ptr(arg1);
04109     deref_args(funct,set_1);
04110     if(arg1->type==top)
04111       residuate(arg1);
04112     else
04113       if(FALSE /*arg1->type->type!=predicate*/) {
04114         success=FALSE;
04115         Errorline("argument of %P should be a predicate.\n",funct);
04116       }
04117       else {
04118         resid_aim=NULL;
04119         cutpt=choice_stack;
04120 
04121         /* Result is FALSE */
04122         other=stack_psi_term(0);
04123         other->type=false;
04124 
04125         push_choice_point(unify,result,other,NULL);
04126 
04127         /* Result is TRUE */
04128         other=stack_psi_term(0);
04129         other->type=true;
04130 
04131         push_goal(unify,result,other,NULL);
04132         push_goal(prove,arg1,DEFRULES,NULL);
04133       }
04134   }
04135   else
04136     curry();
04137 
04138   return success;
04139 }
04140 
04141 
04142 
04143 /******** C_BK_ASSIGN()
04144   This implements backtrackable assignment.
04145 */
04146 static long c_bk_assign()
04147 {
04148   long success=FALSE;
04149   ptr_psi_term arg1,arg2,g;
04150   
04151   g=aim->a;
04152   deref_ptr(g);
04153   get_two_args(g->attr_list,&arg1,&arg2);
04154   if (arg1 && arg2) {
04155     success=TRUE;
04156     deref(arg1);
04157     deref_rec(arg2); /* 17.9 */
04158     /* deref(arg2); 17.9 */
04159     deref_args(g,set_1_2);
04160     if (arg1 != arg2) {
04161 
04162       /*  RM: Mar 10 1993  */
04163       if((GENERIC)arg1>=heap_pointer) {
04164         Errorline("cannot use '<-' on persistent value in %P\n",g);
04165         return c_abort();
04166       }
04167 
04168 
04169 #ifdef TS
04170       if (!TRAIL_CONDITION(arg1)) {
04171         /* If no trail, then can safely overwrite the psi-term */
04172         release_resid_notrail(arg1);
04173         *arg1 = *arg2;
04174         push_psi_ptr_value(arg2,&(arg2->coref)); /* 14.12 */
04175         arg2->coref=arg1; /* 14.12 */
04176       }
04177       else {
04178         push_psi_ptr_value(arg1,&(arg1->coref));
04179         arg1->coref=arg2;
04180         release_resid(arg1);
04181       }
04182 #else
04183       push_psi_ptr_value(arg1,&(arg1->coref));
04184       arg1->coref=arg2;
04185       release_resid(arg1);
04186 #endif
04187     }
04188   }
04189   else
04190     Errorline("argument missing in %P.\n",g);
04191   
04192   return success;
04193 }
04194 
04195 
04196 
04197 
04198 /******** C_ASSIGN()
04199   This implements non-backtrackable assignment.
04200   It doesn't work because backtrackable unifications can have been made before
04201   this assignment was reached. It is complicated by the fact that the assigned
04202   term has to be copied into the heap as it becomes a permanent object.
04203 */
04204 static long c_assign()
04205 {
04206   long success=FALSE;
04207   ptr_psi_term arg1,arg2,g,perm,smallest;
04208   
04209   g=aim->a;
04210   deref_ptr(g);
04211   get_two_args(g->attr_list,&arg1,&arg2);
04212   if (arg1 && arg2) {
04213     success=TRUE;
04214     deref_ptr(arg1);
04215     deref_rec(arg2); /* 17.9 */
04216     /* deref(arg2); 17.9 */
04217     deref_args(g,set_1_2);
04218     if ((GENERIC)arg1<heap_pointer || arg1!=arg2) {
04219       clear_copy();
04220       *arg1 = *exact_copy(arg2,HEAP);
04221     }
04222   }
04223   else
04224     Errorline("argument missing in %P.\n",g);
04225   
04226   return success;
04227 }
04228 
04229 
04230 
04231 /******** C_GLOBAL_ASSIGN()
04232   This implements non-backtrackable assignment on global variables.
04233 
04234   Closely modelled on 'c_assign', except that pointers to the heap are not
04235   copied again onto the heap.
04236   */
04237 
04238 static long c_global_assign()
04239 {
04240   long success=FALSE;
04241   ptr_psi_term arg1,arg2,g,perm,smallest;
04242   ptr_psi_term new;
04243   
04244   g=aim->a;
04245   deref_ptr(g);
04246   get_two_args(g->attr_list,&arg1,&arg2);
04247   if (arg1 && arg2) {
04248     success=TRUE;
04249     deref_rec(arg1);
04250     deref_rec(arg2);
04251     deref_args(g,set_1_2);
04252     if (arg1!=arg2) {
04253 
04254       clear_copy();
04255       new=inc_heap_copy(arg2);
04256       
04257       if((GENERIC)arg1<heap_pointer) {
04258         push_psi_ptr_value(arg1,&(arg1->coref));
04259         arg1->coref= new;
04260       }
04261       else {
04262         *arg1= *new; /* Overwrite in-place */
04263         new->coref=arg1;
04264       }
04265     }
04266   }
04267   else
04268     Errorline("argument missing in %P.\n",g);
04269   
04270   return success;
04271 }
04272 
04273 
04274 
04275 /******** C_UNIFY_FUNC
04276   An explicit unify function that curries on its two arguments.
04277 */
04278 static long c_unify_func()
04279 {
04280   long success=TRUE;
04281   ptr_psi_term funct,arg1,arg2,result;
04282 
04283   funct=aim->a;
04284   deref_ptr(funct);
04285   get_two_args(funct->attr_list,&arg1,&arg2);
04286   if (arg1 && arg2) {
04287     deref(arg1);
04288     deref(arg2);
04289     deref_args(funct,set_1_2);
04290     result=aim->b;
04291     push_goal(unify,arg1,result,NULL);
04292     push_goal(unify,arg1,arg2,NULL);
04293   }
04294   else
04295     curry();
04296 
04297   return success;
04298 }
04299 
04300 
04301 
04302 
04303 /******** C_UNIFY_PRED()
04304   This unifies its two arguments (i.e. implements the predicate A=B).
04305 */
04306 static long c_unify_pred()
04307 {
04308   long success=FALSE;
04309   ptr_psi_term arg1,arg2,g;
04310   
04311   g=aim->a;
04312   deref_ptr(g);
04313   get_two_args(g->attr_list,&arg1,&arg2);
04314   if (arg1 && arg2) {
04315     deref_args(g,set_1_2);
04316     success=TRUE;
04317     push_goal(unify,arg1,arg2,NULL);
04318   }
04319   else
04320     Errorline("argument missing in %P.\n",g);
04321   
04322   return success;
04323 }
04324 
04325 
04326 
04327 
04328 /******** C_COPY_POINTER
04329   Make a fresh copy of the input's sort, keeping exactly the same
04330   arguments as before (i.e., copying the sort and feature table but not
04331   the feature values).
04332 */
04333 static long c_copy_pointer()   /*  PVR: Dec 17 1992  */
04334 {
04335   long success=TRUE;
04336   ptr_psi_term funct,arg1,result,other;
04337 
04338   funct=aim->a;
04339   deref_ptr(funct);
04340   get_one_arg(funct->attr_list,&arg1);
04341   if (arg1) {
04342     deref(arg1);
04343     deref_args(funct,set_1);
04344     other=stack_psi_term(4);
04345     other->type=arg1->type;
04346     other->value=arg1->value;
04347     other->attr_list=copy_attr_list(arg1->attr_list); /* PVR 23.2.94 */
04348     result=aim->b;
04349     push_goal(unify,other,result,NULL);
04350   }
04351   else
04352     curry();
04353 
04354   return success;
04355 }
04356 
04357 
04358 
04359 /******** C_COPY_TERM
04360   Make a fresh copy of the input argument, keeping its structure
04361   but with no connections to the input.
04362 */
04363 static long c_copy_term()
04364 {
04365   long success=TRUE;
04366   ptr_psi_term funct,arg1,copy_arg1,result;
04367 
04368   funct=aim->a;
04369   deref_ptr(funct);
04370   get_one_arg(funct->attr_list,&arg1);
04371   if (arg1) {
04372     deref(arg1);
04373     deref_args(funct,set_1);
04374     result=aim->b;
04375     clear_copy();
04376     copy_arg1=exact_copy(arg1,STACK);
04377     push_goal(unify,copy_arg1,result,NULL);
04378   }
04379   else
04380     curry();
04381 
04382   return success;
04383 }
04384 
04385 
04386 
04387 
04388 /******** C_UNDO
04389   This will prove a goal on backtracking.
04390   This is a completely uninteresting implmentation which is equivalent to:
04391 
04392   undo.
04393   undo(G) :- G.
04394 
04395   The problem is that it can be affected by CUT.
04396   A correct implementation would be very simple:
04397   stack the pair (ADDRESS=NULL, VALUE=GOAL) onto the trail and when undoing
04398   push the goal onto the goal-stack.
04399 */
04400 static long c_undo()
04401 {
04402   long success=TRUE;
04403   ptr_psi_term arg1,arg2,g;
04404   
04405   g=aim->a;
04406   deref_ptr(g);
04407   get_two_args(g->attr_list,&arg1,&arg2);
04408   if (arg1) {
04409     deref_args(g,set_1);
04410     push_choice_point(prove,arg1,DEFRULES,NULL);
04411   }
04412   else {
04413     success=FALSE;
04414     Errorline("argument missing in %P.\n",g);
04415   }
04416   
04417   return success;
04418 }
04419 
04420 
04421 
04422 
04423 /******** C_FREEZE_INNER
04424   This implements the freeze and implies predicates.
04425   For example:
04426 
04427     freeze(g)
04428 
04429   The proof will use matching on the heads of g's definition rather than
04430   unification to prove Goal.  An implicit cut is put at the beginning
04431   of each clause body.  Body goals are executed in the same way as
04432   without freeze.  Essentially, the predicate is called as if it were
04433   a function.
04434 
04435     implies(g)
04436 
04437   The proof will use matching as for freeze, but there is no cut at the
04438   beginning of the clause body & no residuation is done (the clause
04439   fails if its head is not implied by the caller).  Essentially, the
04440   predicate is called as before except that matching is used instead
04441   of unification to decide whether to enter a clause.
04442 */
04443 static long c_freeze_inner(freeze_flag)
04444 long freeze_flag;
04445 {
04446   long success=TRUE;
04447   ptr_psi_term arg1,g;
04448   ptr_psi_term head, body;
04449   ptr_pair_list rule;
04450   /* RESID */ ptr_resid_block rb;
04451   ptr_choice_point cutpt;
04452   ptr_psi_term match_date;
04453   
04454   g=aim->a;
04455   deref_ptr(g);
04456   get_one_arg(g->attr_list,&arg1);
04457   
04458   if (arg1) {
04459     deref_ptr(arg1);
04460     /* if (!arg1->type->evaluate_args) mark_quote(arg1); 8.9 */ /* 18.2 PVR */
04461     deref_args(g,set_1);
04462     deref_ptr(arg1);
04463     
04464     if (arg1->type->type!=predicate) {
04465       success=FALSE;
04466       Errorline("the argument %P of freeze must be a predicate.\n",arg1);
04467       /* main_loop_ok=FALSE; 8.9 */
04468       return success;
04469     }
04470     resid_aim=aim;
04471     match_date=(ptr_psi_term)stack_pointer;
04472     cutpt=choice_stack; /* 13.6 */
04473     /* Third argument of freeze's aim is used to keep track of which */
04474     /* clause is being tried in the frozen goal. */
04475     rule=(ptr_pair_list)aim->c; /* 8.9 */ /* Isn't aim->c always NULL? */
04476     resid_vars=NULL;
04477     curried=FALSE;
04478     can_curry=TRUE; /* 8.9 */
04479 
04480     if (!rule) rule=arg1->type->rule; /* 8.9 */
04481     /* if ((unsigned long)rule==DEFRULES) rule=arg1->type->rule; 8.9 */
04482 
04483     if (rule) {
04484       Traceline("evaluate frozen predicate %P\n",g);
04485       /* resid_limit=(ptr_goal )stack_pointer; 12.6 */
04486       
04487       if ((unsigned long)rule<=MAX_BUILT_INS) {
04488         success=FALSE; /* 8.9 */
04489         Errorline("the argument %P of freeze must be user-defined.\n",arg1); /* 8.9 */
04490         return success; /* 8.9 */
04491         /* Removed obsolete stuff here 11.9 */
04492       }
04493       else {
04494         while (rule && (rule->a==NULL || rule->b==NULL)) {
04495           rule=rule->next;
04496           Traceline("alternative clause has been retracted\n");
04497         }
04498         if (rule) {
04499           /* RESID */ rb = STACK_ALLOC(resid_block);
04500           /* RESID */ save_resid(rb,match_date);
04501           /* RESID */ /* resid_aim = NULL; */
04502 
04503           clear_copy();
04504           if (TRUE /*arg1->type->evaluate_args 8.9 */)
04505             head=eval_copy(rule->a,STACK);
04506           else
04507             head=quote_copy(rule->a,STACK);
04508           body=eval_copy(rule->b,STACK);
04509           head->status=4;
04510 
04511           if (rule->next)
04512             /* push_choice_point(prove,g,rule->next,NULL); 8.9 */
04513             push_choice_point(prove,g,DEFRULES,rule->next);
04514         
04515           push_goal(prove,body,DEFRULES,NULL);
04516           if (freeze_flag) /* 12.10 */
04517             push_goal(freeze_cut,body,cutpt,rb); /* 13.6 */
04518           else
04519             push_goal(implies_cut,body,cutpt,rb);
04520           /* RESID */ push_goal(match,arg1,head,rb);
04521           /* eval_args(head->attr_list); */
04522         }
04523         else {
04524           success=FALSE;
04525           /* resid_aim=NULL; */
04526         }
04527       }
04528     }
04529     else {
04530       success=FALSE;
04531       /* resid_aim=NULL; */
04532     }
04533     resid_aim=NULL;
04534     resid_vars=NULL; /* 22.9 */
04535   }
04536   else {
04537     success=FALSE;
04538     Errorline("goal missing in %P.\n",g);
04539   }
04540   
04541   /* match_date=NULL; */ /* 13.6 */
04542   return success;
04543 }
04544 
04545 
04546 /******** C_FREEZE()
04547   See c_freeze_inner.
04548 */
04549 static long c_freeze()
04550 {
04551   return c_freeze_inner(TRUE);
04552 }
04553 
04554 
04555 /******** C_IMPLIES()
04556   See c_freeze_inner.
04557 */
04558 static long c_implies()
04559 {
04560   return c_freeze_inner(FALSE);
04561 }
04562 
04563 
04564 /*  RM: May  6 1993  Changed C_CHAR to return a string */
04565 
04566 /******** C_CHAR
04567   Create a 1 character string from an ASCII code.
04568 */
04569 static long c_char()
04570 
04571 
04572 {
04573   long success=TRUE;
04574   ptr_psi_term arg1,arg2,funct,result;
04575   long smaller;
04576   long num1;
04577   REAL val1;
04578   char *str;
04579   
04580   funct=aim->a;
04581   deref_ptr(funct);
04582   result=aim->b;
04583   deref(result);
04584 
04585   get_two_args(funct->attr_list,&arg1,&arg2);
04586   if (arg1) {
04587     deref(arg1);
04588     deref_args(funct,set_1);
04589     if (overlap_type(arg1->type,integer)) {
04590       if (arg1->value) {
04591         ptr_psi_term t;
04592 
04593         t=stack_psi_term(4);
04594         t->type=quoted_string;
04595         str=(char *)heap_alloc(2);
04596         str[0] = (unsigned char) floor(*(REAL *) arg1->value);
04597         str[1] = 0;
04598         t->value=(GENERIC)str;
04599 
04600         push_goal(unify,t,result,NULL);
04601       }
04602       else
04603         residuate(arg1);
04604     }
04605     else {
04606       Errorline("argument of %P must be an integer.\n",funct);
04607       success=FALSE;
04608     }
04609   }
04610   else
04611     curry();
04612   
04613   return success;
04614 }
04615 
04616 
04617 
04618 
04619 /******** C_ASCII
04620   Return the Ascii code of the first character of a string or of a
04621   psi-term's name.
04622 */
04623 static long c_ascii()
04624 {
04625   long success=TRUE;
04626   ptr_psi_term arg1,arg2,funct,result;
04627   long smaller;
04628   long num1;
04629   REAL val1;
04630   
04631   funct=aim->a;
04632   deref_ptr(funct);
04633   result=aim->b;
04634   deref(result);
04635 
04636   /* success=get_real_value(result,&val1,&num1); */
04637   /* if (success) { */
04638     get_two_args(funct->attr_list,&arg1,&arg2);
04639     if (arg1) {
04640       deref(arg1);
04641       deref_args(funct,set_1);
04642       success=matches(arg1->type,quoted_string,&smaller);
04643       if (success) {
04644         if (arg1->value) {
04645           unify_real_result(result,(REAL)(*((unsigned char *)arg1->value)));
04646         }
04647         else
04648           residuate(arg1);
04649       }
04650       else {/*  RM: Feb 18 1994  */
04651         success=FALSE;
04652         Errorline("String argument expected in '%P'\n",funct);
04653       }
04654       /*
04655       else {
04656         success=TRUE;
04657         unify_real_result(result,(REAL)(*((unsigned char *)arg1->type->keyword->symbol)));
04658         }
04659         */
04660     }
04661     else
04662       curry();
04663   /* } */
04664   
04665   return success;
04666 }
04667 
04668 
04669 
04670 /******** C_STRING2PSI(P)
04671   Convert a string to a psi-term whose name is the string's value.
04672 */
04673 static long c_string2psi()
04674 {
04675   long success=TRUE;
04676   ptr_psi_term arg1,arg2,arg3,funct,result,t;
04677   long smaller;
04678   ptr_module mod=NULL; /*  RM: Mar 11 1993  */
04679   ptr_module save_current; /*  RM: Mar 12 1993  */
04680   
04681   
04682   funct=aim->a;
04683   deref_ptr(funct);
04684   result=aim->b;
04685   deref(result);
04686 
04687   get_two_args(funct->attr_list,&arg1,&arg2);
04688   if(arg1)
04689     deref(arg1);
04690   if(arg2)
04691     deref(arg2);
04692   deref_args(funct,set_1_2);
04693   
04694   if (arg1) {
04695     success=overlap_type(arg1->type,quoted_string);
04696     if(success) {
04697       
04698       /*  RM: Mar 11 1993  */
04699       if(arg2)
04700         success=get_module(arg2,&mod);
04701       
04702       if (success) {
04703         if(!arg1->value)
04704           residuate(arg1);
04705         else {
04706           t=stack_psi_term(4);
04707           save_current=current_module;
04708           if(mod)
04709             current_module=mod;
04710           t->type=update_symbol(mod,(char *)arg1->value);
04711           current_module=save_current;
04712           if(t->type==error_psi_term->type)
04713             success=FALSE;
04714           else
04715             push_goal(unify,t,result,NULL);
04716         }
04717       }
04718     }
04719     else {
04720       success=FALSE;
04721       Warningline("argument of '%P' is not a string.\n",funct);
04722       /* report_warning(funct,"argument is not a string"); 9.9 */
04723     }
04724   }
04725   else
04726     curry();
04727 
04728   if(!success)
04729     Errorline("error occurred in '%P'\n",funct);
04730   
04731   return success;
04732 }
04733 
04734 
04735 
04736 /******** C_PSI2STRING(P)
04737   Convert a psi-term's name into a string with the name as value.
04738 */
04739 static long c_psi2string()
04740 {
04741   long success=TRUE;
04742   ptr_psi_term arg1,arg3,funct,result,t;
04743   char buf[100]; /*  RM: Mar 10 1993  */
04744   
04745   funct=aim->a;
04746   deref_ptr(funct);
04747   result=aim->b;
04748   deref(result);
04749 
04750   get_one_arg(funct->attr_list,&arg1);
04751   if (arg1) {
04752     deref(arg1);
04753     deref_args(funct,set_1);
04754     t=stack_psi_term(0);
04755     t->type=quoted_string;
04756 
04757     /*  RM: Mar 10 1993  */
04758     if(arg1->value && sub_type(arg1->type,real)) {
04759       sprintf(buf,"%g", *((double *)(arg1->value)));
04760       t->value=(GENERIC)heap_copy_string(buf);
04761     }
04762     else
04763       if(arg1->value && sub_type(arg1->type,quoted_string)) {
04764         t->value=(GENERIC)heap_copy_string((char *)arg1->value);
04765       }
04766       else
04767         t->value=(GENERIC)heap_copy_string(arg1->type->keyword->symbol);
04768     
04769     push_goal(unify,t,result,NULL);
04770   }
04771   else
04772     curry();
04773 
04774   return success;
04775 }
04776 
04777 
04778 
04779 /******** C_INT2STRING(P)
04780   Convert an integer psi-term into a string representing its value.
04781 */
04782 static long c_int2string()
04783 {
04784   char val[STRLEN]; /* Big enough for a _long_ number */
04785   long success=TRUE,i;
04786   ptr_psi_term arg1,arg3,funct,result,t;
04787   REAL the_int,next,neg;
04788 
04789   funct=aim->a;
04790   deref_ptr(funct);
04791   result=aim->b;
04792   deref(result);
04793 
04794   get_one_arg(funct->attr_list,&arg1);
04795   if (arg1) {
04796     deref(arg1);
04797     deref_args(funct,set_1);
04798     if (overlap_type(arg1->type,integer)) {
04799       if (arg1->value) {
04800         the_int = *(REAL *)arg1->value;
04801 
04802         if (the_int!=floor(the_int)) return FALSE;
04803 
04804         neg = (the_int<0.0);
04805         if (neg) the_int = -the_int;
04806         i=STRLEN;
04807         i--;
04808         val[i]=0;
04809         do {
04810           i--;
04811           if (i<=0) {
04812             Errorline("internal buffer too small for int2str(%P).\n",arg1);
04813             return FALSE;
04814           }
04815           next = floor(the_int/10);
04816           val[i]= '0' + (unsigned long) (the_int-next*10);
04817           the_int = next;
04818         } while (the_int);
04819 
04820         if (neg) { i--; val[i]='-'; }
04821         t=stack_psi_term(0);
04822         t->type=quoted_string;
04823         t->value=(GENERIC)heap_copy_string(&val[i]);
04824         push_goal(unify,t,result,NULL);
04825       }
04826       else
04827         residuate(arg1);
04828     }
04829     else
04830       success=FALSE;
04831   }
04832   else
04833     curry();
04834 
04835   return success;
04836 }
04837 
04838 
04839 
04840 /******** C_SUCH_THAT
04841   This implements 'Value | Goal'.
04842   First it unifies Value with the result, then it proves Goal.
04843 
04844   This routine is different than the straight-forward implementation in Life
04845   which would have been: "V|G => cond(G,V,{})" because
04846   V is evaluated and unified before G is proved.
04847 */
04848 static long c_such_that()
04849 {
04850   long success=TRUE;
04851   ptr_psi_term arg1,arg2,funct,result;
04852   
04853   funct=aim->a;
04854   deref_ptr(funct);
04855   result=aim->b;
04856   get_two_args(funct->attr_list,&arg1,&arg2);
04857   if (arg1 && arg2) {
04858     deref_ptr(arg1);
04859     deref_ptr(arg2);
04860     deref_args(funct,set_1_2);
04861     resid_aim=NULL;
04862     push_goal(prove,arg2,DEFRULES,NULL);
04863     push_goal(unify,arg1,result,NULL);
04864     i_check_out(arg1);
04865   }
04866   else
04867     curry();
04868   
04869   return success;
04870 }
04871 
04872 
04873 
04874 /* Return an attr_list with one argument */
04875 ptr_node one_attr()
04876 {
04877    ptr_node n;
04878 
04879    n = STACK_ALLOC(node);
04880    n->key = one;
04881    n->data = NULL; /* To be filled in later */
04882    n->left = NULL;
04883    n->right = NULL;
04884 
04885    return n;
04886 }
04887 
04888 
04889 /* Return a psi term with one or two args, and the addresses of the args */
04890 ptr_psi_term new_psi_term(numargs, typ, a1, a2)
04891 long numargs;
04892 ptr_definition typ;
04893 ptr_psi_term **a1, **a2;
04894 {
04895    ptr_psi_term t;
04896    ptr_node n1, n2;
04897 
04898    if (numargs==2) {
04899      n2 = STACK_ALLOC(node);
04900      n2->key = two;
04901      *a2 = (ptr_psi_term *) &(n2->data);
04902      n2->left = NULL;
04903      n2->right = NULL;
04904    }
04905    else
04906      n2=NULL;
04907 
04908    n1 = STACK_ALLOC(node);
04909    n1->key = one;
04910    *a1 = (ptr_psi_term *) &(n1->data);
04911    n1->left = NULL;
04912    n1->right = n2;
04913 
04914    t=stack_psi_term(4);
04915    t->type = typ;
04916    t->attr_list = n1;
04917 
04918    return t;
04919 }
04920 
04921 
04922 /* Return TRUE iff there are some rules r */
04923 /* This is true for a user-defined function or predicate with a definition, */
04924 /* and for a type with constraints. */
04925 long has_rules(r)
04926 ptr_pair_list r;
04927 {
04928   if (r==NULL) return FALSE;
04929   while (r) {
04930     if (r->a!=NULL) return TRUE;
04931     r=r->next;
04932   }
04933   return FALSE;
04934 }
04935 
04936 /* Return TRUE if rules r are for a built-in */
04937 long is_built_in(r)
04938 ptr_pair_list r;
04939 {
04940   return ((unsigned long)r>0 && (unsigned long)r<MAX_BUILT_INS);
04941 }
04942 
04943 
04944 /* List the characteristics (delay_check, dynamic/static, non_strict) */
04945 /* in such a way that they can be immediately read in. */
04946 list_special(t)
04947 ptr_psi_term t;
04948 {
04949   ptr_definition d = t->type;
04950   ptr_pair_list r = t->type->rule;
04951   long prflag=FALSE;
04952 
04953   if (t->type->type==type) {
04954     if (!d->always_check) {
04955       if (is_built_in(r)) fprintf(output_stream,"%% ");
04956       fprintf(output_stream,"delay_check(");
04957       display_psi_stream(t);
04958       fprintf(output_stream,")?\n");
04959       prflag=TRUE;
04960     }
04961   } else {
04962     if (!d->protected) {
04963       if (is_built_in(r)) fprintf(output_stream,"%% ");
04964       fprintf(output_stream,"%s(",(d->protected?"static":"dynamic"));
04965       display_psi_stream(t);
04966       fprintf(output_stream,")?\n");
04967       prflag=TRUE;
04968     } 
04969   }
04970   if (!d->evaluate_args) {
04971     if (is_built_in(r)) fprintf(output_stream,"%% ");
04972     fprintf(output_stream,"non_strict(");
04973     display_psi_stream(t);
04974     fprintf(output_stream,")?\n");
04975     prflag=TRUE;
04976   }
04977   /* if (prflag) fprintf(output_stream,"\n"); */
04978 }
04979 
04980 
04981 /******** C_LISTING
04982   List the definition of a predicate or a function, and the own constraints
04983   of a type (i.e. the non-inherited constraints).
04984 */
04985 static long c_listing()
04986 {
04987   long success=TRUE;
04988   ptr_psi_term arg1,arg2,g;
04989   def_type fp;
04990   ptr_pair_list r;
04991   ptr_node n;
04992   ptr_psi_term t, t2, *a1, *a2, *a3;
04993   char *s1,*s2;
04994   
04995   g=aim->a;
04996   deref_ptr(g);
04997   get_two_args(g->attr_list,&arg1,&arg2);
04998   if (arg1) {
04999     deref_ptr(arg1);
05000     list_special(arg1);
05001     fp=arg1->type->type;
05002     r=arg1->type->rule;
05003     if (is_built_in(r) || !has_rules(r)) {
05004 
05005       if (is_built_in(r)) {
05006         s1="built-in ";
05007         s2="";
05008       }
05009       else {
05010         s1="user-defined ";
05011         s2=" with an empty definition";
05012       }
05013       switch (fp) {
05014       case function:
05015         fprintf(output_stream,"%% '%s' is a %sfunction%s.\n",
05016                 arg1->type->keyword->symbol,s1,s2);
05017         break;
05018       case predicate:
05019         fprintf(output_stream,"%% '%s' is a %spredicate%s.\n",
05020                 arg1->type->keyword->symbol,s1,s2);
05021         break;
05022       case type:
05023         if (arg1->value) {
05024           fprintf(output_stream,"%% ");
05025           if (arg1->type!=quoted_string) fprintf(output_stream,"'");
05026           display_psi_stream(arg1);
05027           if (arg1->type!=quoted_string) fprintf(output_stream,"'");
05028           fprintf(output_stream," is a value of sort '%s'.\n",
05029                   arg1->type->keyword->symbol);
05030         }
05031         break;
05032 
05033       case global: /*  RM: Feb  9 1993  */
05034         fprintf(output_stream,"%% ");
05035         outputline("'%s' is a %sglobal variable worth %P.\n",
05036                    arg1->type->keyword->symbol,
05037                    s1,
05038                    arg1->type->global_value);
05039         break;
05040 
05041 #ifdef CLIFE
05042       case block: /* AA: Mar 10 1993 */
05043         fprintf(output_stream,"%% '%s' is a %block.\n",
05044                 arg1->type->keyword->symbol,"","");     
05045 #endif
05046         
05047       default:
05048         fprintf(output_stream,"%% '%s' is undefined.\n", arg1->type->keyword->symbol);
05049       }
05050     }
05051     else {
05052       if (fp==type || fp==function || fp==predicate) {
05053         n = one_attr();
05054         if (fp==function)
05055           t = new_psi_term(2, funcsym, &a1, &a2);
05056         else if (fp==predicate)
05057           t = new_psi_term(2, predsym, &a1, &a2);
05058         else { /* fp==type */
05059           t = new_psi_term(1, typesym, &a3, &a2); /* a2 is a dummy */
05060           t2 = new_psi_term(2, such_that, &a1, &a2);
05061         }
05062         n->data = (GENERIC) t;
05063         while (r) {
05064           *a1 = r->a; /* Func, pred, or type */
05065           *a2 = r->b;
05066           if (r->a) {
05067             /* Handle an attribute constraint with no predicate: */
05068             if (fp==type) { if (r->b==NULL) *a3 = r->a; else *a3 = t2; }
05069             listing_pred_write(n, (fp==function)||(fp==type));
05070             fprintf(output_stream,".\n");
05071           }
05072           r = r->next;
05073         }
05074         /* fprintf(output_stream,"\n"); */
05075         /* fflush(output_stream); */
05076       }
05077       else {
05078         success=FALSE;
05079         Errorline("argument of %P must be a predicate, function, or sort.\n",g);
05080       }
05081     }
05082   }
05083   else {
05084     success=FALSE;
05085     Errorline("argument missing in %P.\n",g);
05086   }
05087   
05088   return success;
05089 }
05090 
05091 
05092 
05093 /******** C_print_codes
05094   Print the codes of all the sorts.
05095 */
05096 static long c_print_codes()
05097 {
05098   ptr_psi_term t;
05099 
05100   t=aim->a;
05101   deref_args(t,set_empty);
05102   outputline("There are %d sorts.\n",type_count);
05103   print_codes();
05104   return TRUE;
05105 }
05106 
05107 
05108 
05109 /*********************** TEMPLATES FOR NEW PREDICATES AND FUNCTIONS  *******/
05110 
05111 
05112 
05113 /******** C_PRED
05114   Template for C built-in predicates.
05115 */
05116 static long c_pred()
05117 {
05118   long success=TRUE;
05119   ptr_psi_term arg1,arg2,g;
05120   
05121   g=aim->a;
05122   deref_ptr(g);
05123   get_two_args(g->attr_list,&arg1,&arg2);
05124   if (arg1 && arg2) {
05125     deref_args(g,set_1_2);
05126   }
05127   else {
05128     success=FALSE;
05129     Errorline("argument(s) missing in %P.\n",g);
05130   }
05131   
05132   return success;
05133 }
05134 
05135 
05136 
05137 /******** C_FUNCT
05138   Template for C built-in functions.
05139 */
05140 static long c_funct()
05141 {
05142   long success=TRUE;
05143   ptr_psi_term arg1,arg2,funct;
05144 
05145   
05146   funct=aim->a;
05147   deref_ptr(funct);
05148 
05149   get_two_args(funct->attr_list,&arg1,&arg2);
05150 
05151   if (arg1 && arg2) {
05152     deref_args(funct,set_1_2);
05153   }
05154   else
05155     curry();
05156   
05157   return success;
05158 }
05159 
05160 
05161 
05162 /******************************************************************************
05163   
05164   Here are the routines which allow a new built_in type, predicate or function
05165   to be declared.
05166   
05167   ****************************************************************************/
05168 
05169 
05170 
05171 /******** NEW_BUILT_IN(m,s,t,r)
05172   Add a new built-in predicate or function.
05173   Used also in x_pred.c
05174 
05175   M=module.
05176   S=string.
05177   T=type (function or predicate).
05178   R=address of C routine to call.
05179 */
05180 void new_built_in(m,s,t,r)
05181      ptr_module m;
05182      char *s;
05183      def_type t;
05184      long (*r)();
05185 {
05186   ptr_definition d;
05187 
05188   if (built_in_index >= MAX_BUILT_INS) {
05189     fprintf(stderr,"Too many primitives, increase MAX_BUILT_INS in extern.h\n");
05190     exit(-1);
05191   }
05192 
05193   if(m!=current_module)  /*  RM: Jan 13 1993  */
05194     set_current_module(m);
05195   
05196   d=update_symbol(m,s); /* RM: Jan  8 1993 */
05197   d->type=t;
05198   built_in_index++;
05199   d->rule=(ptr_pair_list )built_in_index;
05200   c_rule[built_in_index]=r;
05201 }
05202 
05203 
05204 
05205 /******** OP_DECLARE(p,t,s)
05206   Declare that string S is an operator of precedence P and of type T where
05207   T=xf, fx, yf, fy, xfx etc...
05208 */
05209 static void op_declare(p,t,s)
05210 long p;
05211 operator t;
05212 char *s;
05213 {
05214   ptr_definition d;
05215   ptr_operator_data od;
05216   
05217   if (p>MAX_PRECEDENCE || p<0) {
05218     Errorline("operator precedence must be in the range 0..%d.\n",
05219               MAX_PRECEDENCE);
05220     return;
05221   }
05222   d=update_symbol(NULL,s);
05223 
05224   od= (ptr_operator_data) heap_alloc (sizeof(operator_data));
05225   /* od= (ptr_operator_data) malloc (sizeof(operator_data)); 12.6 */
05226     
05227   od->precedence=p;
05228   od->type=t;
05229   od->next=d->op_data;
05230   d->op_data=od;
05231 }
05232 
05233 
05234 
05235 /******** DECLARE_OPERATOR(t)
05236   Declare a new operator or change a pre-existing one.
05237 
05238   For example: '*op*'(3,xfx,+)?
05239   T is the OP declaration.
05240 */
05241 long declare_operator(t)
05242 ptr_psi_term t;
05243 {
05244   ptr_psi_term prec,type,atom;
05245   ptr_node n;
05246   char *s;
05247   long p;
05248   operator kind=nop;
05249   long success=FALSE;
05250 
05251   deref_ptr(t);
05252   n=t->attr_list;
05253   get_two_args(n,&prec,&type);
05254   n=find(featcmp,three,n);
05255   if (n && prec && type) {
05256     atom=(ptr_psi_term )n->data;
05257     deref_ptr(prec);
05258     deref_ptr(type);
05259     deref_ptr(atom);
05260     if (!atom->value) {
05261       s=atom->type->keyword->symbol;
05262       if (sub_type(prec->type,integer) && prec->value) { /* 10.8 */
05263         p = * (REAL *)prec->value;
05264         if (p>0 && p<=MAX_PRECEDENCE) {
05265           
05266           if (type->type == xf_sym) kind=xf;
05267           else if (type->type == yf_sym) kind=yf;
05268           else if (type->type == fx_sym) kind=fx;
05269           else if (type->type == fy_sym) kind=fy;
05270           else if (type->type == xfx_sym) kind=xfx;
05271           else if (type->type == xfy_sym) kind=xfy;
05272           else if (type->type == yfx_sym) kind=yfx;
05273           else
05274             Errorline("bad operator kind '%s'.\n",type->type->keyword->symbol);
05275     
05276           if (kind!=nop) {
05277             op_declare(p,kind,s);
05278             success=TRUE;
05279           }
05280         }
05281         else
05282           Errorline("precedence must range from 1 to 1200 in %P.\n",t);
05283       }
05284       else
05285         Errorline("precedence must be a positive integer in %P.\n",t);
05286     }
05287     else
05288       Errorline("numbers or strings may not be operators in %P.\n",t);
05289   }
05290   else
05291     Errorline("argument missing in %P.\n",t);
05292 
05293   return success;
05294 }
05295 
05296 
05297 
05298 char *str_conc(s1,s2)
05299 char *s1, *s2;
05300 {
05301   char *result;
05302 
05303   result=(char *)heap_alloc(strlen(s1)+strlen(s2)+1);
05304   sprintf(result,"%s%s",s1,s2);
05305 
05306   return result;
05307 }
05308 
05309 
05310 
05311 char *sub_str(s,p,n)
05312 char *s;
05313 long p;
05314 long n;
05315 {
05316   char *result;
05317   long i;
05318   long l;
05319 
05320   l=strlen(s);
05321   if(p>l || p<0 || n<0)
05322     n=0;
05323   else
05324     if(p+n-1>l)
05325       n=l-p+1;
05326 
05327   result=(char *)heap_alloc(n+1);
05328   for(i=0;i<n;i++)
05329     *(result+i)= *(s+p+i-1);
05330 
05331   *(result+n)=0;
05332   
05333   return result;
05334 }
05335 
05336 
05337 
05338 long append_files(s1,s2)
05339 char *s1, *s2;
05340 {
05341   FILE *f1;
05342   FILE *f2;
05343   long result=FALSE;
05344   
05345   f1=fopen(s1,"a");
05346   if(f1) {
05347     f2=fopen(s2,"r");
05348     if(f2) {
05349       while(!feof(f2))
05350         fputc(fgetc(f2),f1);
05351       fclose(f2);
05352       fclose(f1);
05353       result=TRUE;
05354     }
05355     else
05356       Errorline("couldn't open \"%s\"\n",f2);
05357       /* printf("*** Error: couldn't open \"%s\"\n",f2); PVR 14.9.93 */
05358    }
05359   else
05360     Errorline("couldn't open \"%s\"\n",f1);
05361     /* printf("*** Error: couldn't open \"%s\"\n",f1); PVR 14.9.93 */
05362 
05363   return result;
05364 }
05365 
05366 
05367 
05368 
05369 /******** C_CONCATENATE
05370   Concatenate the strings in arguments 1 and 2.
05371 */
05372 long c_concatenate()
05373 {
05374   ptr_psi_term result,funct,temp_result;
05375   ptr_node n1, n2;
05376   long success=TRUE;
05377   long all_args=TRUE;
05378   char * c_result;
05379   ptr_psi_term arg1; 
05380   char * c_arg1; 
05381   ptr_psi_term arg2; 
05382   char * c_arg2; 
05383 
05384   funct=aim->a;
05385   deref_ptr(funct);
05386   result=aim->b;
05387 
05388   /* Evaluate all arguments first: */
05389   n1=find(featcmp,one,funct->attr_list);
05390   if (n1) {
05391     arg1= (ptr_psi_term )n1->data;
05392     deref(arg1);
05393   }
05394   n2=find(featcmp,two,funct->attr_list);
05395   if (n2) {
05396     arg2= (ptr_psi_term )n2->data;
05397     deref(arg2);
05398   }
05399   deref_args(funct,set_1_2);
05400 
05401   if (success) {
05402     if (n1) {
05403        if (overlap_type(arg1->type,quoted_string)) /* 10.8 */
05404           if (arg1->value)
05405               c_arg1= (char *)arg1->value;
05406           else {
05407             residuate(arg1);
05408             all_args=FALSE;
05409           }
05410        else
05411          success=FALSE;
05412     }
05413     else {
05414       all_args=FALSE;
05415       curry();
05416     };
05417   };
05418 
05419   if (success) {
05420     if (n2) {
05421        if (overlap_type(arg2->type,quoted_string)) /* 10.8 */
05422           if (arg2->value)
05423               c_arg2= (char *)arg2->value;
05424           else {
05425             residuate(arg2);
05426             all_args=FALSE;
05427           }
05428        else
05429          success=FALSE;
05430     }
05431     else {
05432       all_args=FALSE;
05433       curry();
05434     }
05435   }
05436 
05437   if(success && all_args) {
05438       c_result=str_conc( c_arg1, c_arg2 );
05439       temp_result=stack_psi_term(0);
05440       temp_result->type=quoted_string;
05441       temp_result->value=(GENERIC) c_result;
05442       push_goal(unify,temp_result,result,NULL);
05443   }
05444 
05445   return success;
05446 }
05447 
05448 
05449 
05450 /******** C_MODULE_NAME
05451   Return the module in which a term resides.
05452   */
05453 static long c_module_name()
05454 {
05455   long success=TRUE;
05456   ptr_psi_term arg1,arg2,funct,result;
05457   
05458   
05459   funct=aim->a;
05460   result=aim->b;
05461   deref_ptr(funct);
05462   deref_ptr(result);
05463   
05464   get_two_args(funct->attr_list,&arg1,&arg2);
05465   
05466   if (arg1) {
05467     deref_ptr(arg1);
05468     arg2=stack_psi_term(0);
05469     arg2->type=quoted_string;
05470     arg2->value=(GENERIC)heap_copy_string(arg1->type->keyword->module->module_name);
05471     push_goal(unify,arg2,result,NULL);
05472   }
05473   else
05474     curry();
05475   
05476   return success;
05477 }
05478 
05479 
05480 
05481 /******** C_COMBINED_NAME
05482   Return the string module#name for a term.
05483   */
05484 static long c_combined_name()
05485 {
05486   long success=TRUE;
05487   ptr_psi_term arg1,arg2,funct,result;
05488   
05489   
05490   funct=aim->a;
05491   result=aim->b;
05492   deref_ptr(funct);
05493   deref_ptr(result);
05494   
05495   get_two_args(funct->attr_list,&arg1,&arg2);
05496   
05497   if (arg1) {
05498     deref_ptr(arg1);
05499     arg2=stack_psi_term(0);
05500     arg2->type=quoted_string;
05501     arg2->value=(GENERIC)heap_copy_string(arg1->type->keyword->combined_name);
05502     push_goal(unify,arg2,result,NULL);
05503   }
05504   else
05505     curry();
05506   
05507   return success;
05508 }
05509 
05510 
05511 
05512 
05513 /******** C_STRING_LENGTH
05514   Return the length of the string in argument 1.
05515   */
05516 long c_string_length()
05517 {
05518   ptr_psi_term result,funct;
05519   ptr_node n1;
05520   long success=TRUE;
05521   long all_args=TRUE;
05522   long c_result;
05523   ptr_psi_term arg1; 
05524   char * c_arg1; 
05525 
05526   funct=aim->a;
05527   deref_ptr(funct);
05528   result=aim->b;
05529 
05530   /* Evaluate all arguments first: */
05531   n1=find(featcmp,one,funct->attr_list);
05532   if (n1) {
05533     arg1= (ptr_psi_term )n1->data;
05534     deref(arg1);
05535   }
05536   deref_args(funct,set_1);
05537 
05538   if (success) {
05539     if (n1) {
05540        if (overlap_type(arg1->type,quoted_string)) /* 10.8 */
05541           if (arg1->value)
05542               c_arg1= (char *)arg1->value;
05543           else {
05544             residuate(arg1);
05545             all_args=FALSE;
05546           }
05547        else
05548          success=FALSE;
05549     }
05550     else {
05551       all_args=FALSE;
05552       curry();
05553     };
05554   };
05555 
05556   if (success && all_args) {
05557       c_result=strlen(c_arg1);
05558       push_goal(unify,real_stack_psi_term(0,(REAL)c_result),result,NULL);
05559   };
05560 
05561 return success;
05562 }
05563 
05564 
05565 
05566 
05567 /******** C_SUB_STRING
05568   Return the substring of argument 1 from position argument 2 for a
05569   length of argument 3 characters.
05570 */
05571 long c_sub_string()
05572 {
05573   ptr_psi_term result,funct,temp_result;
05574   ptr_node n1,n2,n3;
05575   long success=TRUE;
05576   long all_args=TRUE;
05577   char * c_result;
05578   ptr_psi_term arg1; 
05579   char * c_arg1; 
05580   ptr_psi_term arg2; 
05581   long c_arg2; 
05582   ptr_psi_term arg3; 
05583   long c_arg3; 
05584 
05585   funct=aim->a;
05586   deref_ptr(funct);
05587   result=aim->b;
05588 
05589   /* Evaluate all arguments first: */
05590   n1=find(featcmp,one,funct->attr_list);
05591   if (n1) {
05592     arg1= (ptr_psi_term )n1->data;
05593     deref(arg1);
05594   }
05595   n2=find(featcmp,two,funct->attr_list);
05596   if (n2) {
05597     arg2= (ptr_psi_term )n2->data;
05598     deref(arg2);
05599   }
05600   n3=find(featcmp,three,funct->attr_list);
05601   if (n3) {
05602     arg3= (ptr_psi_term )n3->data;
05603     deref(arg3);
05604   }
05605   deref_args(funct,set_1_2_3);
05606 
05607   if (success) {
05608     if (n1) {
05609        if (overlap_type(arg1->type,quoted_string)) /* 10.8 */
05610           if (arg1->value)
05611               c_arg1= (char *)arg1->value;
05612           else {
05613             residuate(arg1);
05614             all_args=FALSE;
05615           }
05616        else
05617          success=FALSE;
05618     }
05619     else {
05620       all_args=FALSE;
05621       curry();
05622     };
05623   };
05624 
05625   if (success) {
05626     if (n2) {
05627        if (overlap_type(arg2->type,integer)) /* 10.8 */
05628           if (arg2->value)
05629               c_arg2= (long)(* (double *)(arg2->value));
05630           else {
05631             residuate(arg2);
05632             all_args=FALSE;
05633           }
05634        else
05635          success=FALSE;
05636     }
05637     else {
05638       all_args=FALSE;
05639       curry();
05640     };
05641   };
05642 
05643   if (success) {
05644     if (n3) {
05645        if (overlap_type(arg3->type,integer)) /* 10.8 */
05646           if (arg3->value)
05647               c_arg3= (long)(* (double *)(arg3->value));
05648           else {
05649             residuate(arg3);
05650             all_args=FALSE;
05651           }
05652        else
05653          success=FALSE;
05654     }
05655     else {
05656       all_args=FALSE;
05657       curry();
05658     };
05659   };
05660 
05661   if (success && all_args) {
05662       c_result=sub_str(c_arg1,c_arg2,c_arg3);
05663       temp_result=stack_psi_term(0);
05664       temp_result->type=quoted_string;
05665       temp_result->value=(GENERIC) c_result;
05666       push_goal(unify,temp_result,result,NULL);
05667   };
05668 
05669 return success;
05670 }
05671 
05672 
05673 
05674 
05675 /******** C_APPEND_FILE
05676   Append the file named by argument 2 to the file named by argument 1.
05677   This predicate will not residuate; it requires string arguments.
05678 */
05679 long c_append_file()
05680 {
05681   ptr_psi_term g;
05682   ptr_node n1,n2;
05683   long success=TRUE;
05684   ptr_psi_term arg1; 
05685   char * c_arg1; 
05686   ptr_psi_term arg2; 
05687   char * c_arg2; 
05688 
05689   g=aim->a;
05690   deref_ptr(g);
05691 
05692   /* Evaluate all arguments first: */
05693   n1=find(featcmp,one,g->attr_list);
05694   if (n1) {
05695     arg1= (ptr_psi_term )n1->data;
05696     deref(arg1);
05697   }
05698   n2=find(featcmp,two,g->attr_list);
05699   if (n2) {
05700     arg2= (ptr_psi_term )n2->data;
05701     deref(arg2);
05702   }
05703   deref_args(g,set_1_2);
05704 
05705   if (success) {
05706     if (n1) {
05707        if (overlap_type(arg1->type,quoted_string))
05708           if (arg1->value)
05709               c_arg1= (char *)arg1->value;
05710           else {
05711             success=FALSE;
05712             Errorline("bad argument in %P.\n",g);
05713           }
05714        else
05715          success=FALSE;
05716     }
05717     else {
05718       success=FALSE;
05719       Errorline("bad argument in %P.\n",g);
05720     };
05721   };
05722 
05723   if (success) {
05724     if (n2) {
05725        if (overlap_type(arg2->type,quoted_string))
05726           if (arg2->value)
05727               c_arg2= (char *)arg2->value;
05728           else {
05729             success=FALSE;
05730             Errorline("bad argument in %P.\n",g);
05731           }
05732        else
05733          success=FALSE;
05734     }
05735     else {
05736       success=FALSE;
05737       Errorline("bad argument in %P.\n",g);
05738     };
05739   };
05740 
05741   if (success)
05742     success=append_files(c_arg1,c_arg2);
05743 
05744 return success;
05745 }
05746 
05747 
05748 
05749 /******** C_RANDOM
05750   Return an integer random number between 0 and abs(argument1).
05751   Uses the Unix random() function (rand_r(&seed) for Solaris).
05752 */
05753 long c_random()
05754 {
05755   ptr_psi_term result,funct;
05756   ptr_node n1;
05757   long success=TRUE;
05758   long all_args=TRUE;
05759   long c_result;
05760   ptr_psi_term arg1; 
05761   long c_arg1; 
05762 
05763   funct=aim->a;
05764   deref_ptr(funct);
05765   result=aim->b;
05766 
05767   /* Evaluate all arguments first: */
05768   n1=find(featcmp,one,funct->attr_list);
05769   if (n1) {
05770     arg1= (ptr_psi_term )n1->data;
05771     deref(arg1);
05772   }
05773   deref_args(funct,set_1);
05774 
05775   if (success) {
05776     if (n1) {
05777        if (overlap_type(arg1->type,integer))
05778           if (arg1->value)
05779               c_arg1= (long)(* (double *)(arg1->value));
05780           else {
05781             residuate(arg1);
05782             all_args=FALSE;
05783           }
05784        else
05785          success=FALSE;
05786     }
05787     else {
05788       all_args=FALSE;
05789       curry();
05790     }
05791   }
05792 
05793   if (success && all_args) {
05794       if (c_arg1) {
05795 #ifdef SOLARIS
05796         c_result=(rand_r(&randomseed)<<15) + rand_r(&randomseed);
05797 #else
05798         c_result=random();
05799 #endif
05800         c_result=c_result-(c_result/c_arg1)*c_arg1;
05801       }
05802       else
05803         c_result=0;
05804 
05805       push_goal(unify,real_stack_psi_term(0,(REAL)c_result),result,NULL);
05806   }
05807 
05808   return success;
05809 }
05810 
05811 
05812 
05813 /******** C_INITRANDOM
05814   Uses its integer argument to initialize
05815   the random number generator, which is the Unix random() function.
05816 */
05817 long c_initrandom()
05818 {
05819   ptr_psi_term t;
05820   ptr_node n1;
05821   long success=TRUE;
05822   long all_args=TRUE;
05823   long c_result;
05824   ptr_psi_term arg1; 
05825   long c_arg1; 
05826 
05827   t=aim->a;
05828   deref_ptr(t);
05829 
05830   /* Evaluate all arguments first: */
05831   n1=find(featcmp,one,t->attr_list);
05832   if (n1) {
05833     arg1= (ptr_psi_term )n1->data;
05834     deref(arg1);
05835   }
05836   deref_args(t,set_1);
05837 
05838   if (success) {
05839     if (n1) {
05840        if (overlap_type(arg1->type,integer))
05841           if (arg1->value)
05842               c_arg1= (long)(* (double *)(arg1->value));
05843           else {
05844             residuate(arg1);
05845             all_args=FALSE;
05846           }
05847        else
05848          success=FALSE;
05849     }
05850     else {
05851       all_args=FALSE;
05852     }
05853   }
05854 
05855 #ifdef SOLARIS
05856   if (success && all_args) randomseed=c_arg1;
05857 #else
05858   if (success && all_args) srandom(c_arg1);
05859 #endif
05860 
05861   return success;
05862 }
05863 
05864 
05865 
05866 /******** C_DEREF_LENGTH
05867   Return the length of the dereference chain for argument 1.
05868   */
05869 /*  RM: Jul 15 1993  */
05870 long c_deref_length()
05871 {
05872   ptr_psi_term result,funct;
05873   long success=TRUE;
05874   int count;
05875   ptr_psi_term arg1,arg2;
05876   ptr_node n1;
05877   
05878   funct=aim->a;
05879   deref_ptr(funct);
05880   result=aim->b;
05881 
05882   n1=find(featcmp,one,funct->attr_list);
05883   if (n1) {
05884     count=0;
05885     arg1= (ptr_psi_term )n1->data;
05886     while(arg1->coref) {
05887       count++;
05888       arg1=arg1->coref;
05889     }
05890     success=unify_real_result(result,(REAL)count);
05891   }
05892   else
05893     curry();
05894   
05895   return success;
05896 }
05897 
05898 
05899 
05900 /******** C_ARGS
05901   Return the Unix "ARGV" array as a list of strings.
05902   */
05903 /*  RM: Sep 20 1993  */
05904 long c_args()
05905 {
05906   ptr_psi_term result,list,str;
05907   long success=TRUE;
05908   int i;
05909 
05910   result=aim->b;
05911   
05912   list=stack_nil();
05913   for(i=arg_c-1;i>=0;i--) {
05914     str=stack_psi_term(0);
05915     str->type=quoted_string;
05916     str->value=(GENERIC)heap_copy_string(arg_v[i]);
05917     list=stack_cons(str,list);
05918   }
05919   push_goal(unify,result,list,NULL);
05920   
05921   return success;
05922 }
05923 
05924 /******** INIT_BUILT_IN_TYPES
05925   Initialise the symbol tree with the built-in types.
05926   Declare all built-in predicates and functions.
05927   Initialise system type variables.
05928   Declare all standard operators.
05929 
05930   Called by life.c
05931 */
05932 void init_built_in_types()
05933 {
05934   ptr_definition t;
05935   
05936   /* symbol_table=NULL;   RM: Feb  3 1993  */
05937 
05938   
05939   
05940   /*  RM: Jan 13 1993  */
05941   /* Initialize the minimum syntactic symbols */
05942   set_current_module(syntax_module); /*  RM: Feb  3 1993  */
05943   and=update_symbol(syntax_module,",");  
05944   update_symbol(syntax_module,"[");
05945   update_symbol(syntax_module,"]");
05946   update_symbol(syntax_module,"(");
05947   update_symbol(syntax_module,")");
05948   update_symbol(syntax_module,"{");
05949   update_symbol(syntax_module,"}");
05950   update_symbol(syntax_module,".");
05951   update_symbol(syntax_module,"?");
05952 
05953   
05954   cut                   =update_symbol(syntax_module,"!");
05955   colonsym              =update_symbol(syntax_module,":");
05956   commasym              =update_symbol(syntax_module,",");
05957   disj_nil              =update_symbol(syntax_module,"{}");
05958   eof                   =update_symbol(syntax_module,"end_of_file");
05959   eqsym                 =update_symbol(syntax_module,"=");
05960   leftarrowsym          =update_symbol(syntax_module,"<-");
05961   funcsym               =update_symbol(syntax_module,"->");
05962   life_or               =update_symbol(syntax_module,";");/* RM: Apr 6 1993  */
05963   minus_symbol          =update_symbol(syntax_module,"-");/* RM: Jun 21 1993 */
05964   predsym               =update_symbol(syntax_module,":-");
05965   quote                 =update_symbol(syntax_module,"`");
05966   such_that             =update_symbol(syntax_module,"|");
05967   top                   =update_symbol(syntax_module,"@");
05968   typesym               =update_symbol(syntax_module,"::");
05969 
05970   /*  RM: Jul  7 1993  */
05971   final_dot             =update_symbol(syntax_module,"< . >");
05972   final_question        =update_symbol(syntax_module,"< ? >");
05973 
05974   
05975   
05976   /*  RM: Feb  3 1993  */
05977   set_current_module(bi_module);
05978   error_psi_term=heap_psi_term(4); /* 8.10 */
05979   error_psi_term->type=update_symbol(bi_module,"*** ERROR ***");
05980   error_psi_term->type->code=NOT_CODED;
05981 
05982   apply                 =update_symbol(bi_module,"apply");
05983   boolean               =update_symbol(bi_module,"bool");
05984   boolpredsym           =update_symbol(bi_module,"bool_pred");
05985   built_in              =update_symbol(bi_module,"built_in");
05986   calloncesym           =update_symbol(bi_module,"call_once");
05987   /* colon sym */
05988   /* comma sym */
05989   comment               =update_symbol(bi_module,"comment");
05990 
05991   
05992   /*  RM: Dec 11 1992  conjunctions have been totally scrapped it seems */
05993   /* conjunction=update_symbol("*conjunction*"); 19.8 */
05994 
05995   constant              =update_symbol(bi_module,"*constant*");
05996   disjunction           =update_symbol(bi_module,"disj");/*RM:9 Dec 92*/
05997   false                 =update_symbol(bi_module,"false");
05998   functor               =update_symbol(bi_module,"functor");
05999   iff                   =update_symbol(bi_module,"cond");
06000   integer               =update_symbol(bi_module,"int");
06001   alist                 =update_symbol(bi_module,"cons");/*RM:9 Dec 92*/
06002   nothing               =update_symbol(bi_module,"bottom");
06003   nil                   =update_symbol(bi_module,"nil");/*RM:9 Dec 92*/
06004   quoted_string         =update_symbol(bi_module,"string");
06005   real                  =update_symbol(bi_module,"real");
06006   stream                =update_symbol(bi_module,"stream");
06007   succeed               =update_symbol(bi_module,"succeed");
06008   true                  =update_symbol(bi_module,"true");
06009   timesym               =update_symbol(bi_module,"time");
06010   variable              =update_symbol(bi_module,"*variable*");
06011   opsym                 =update_symbol(bi_module,"op");
06012   loadsym               =update_symbol(bi_module,"load");
06013   dynamicsym            =update_symbol(bi_module,"dynamic");
06014   staticsym             =update_symbol(bi_module,"static");
06015   encodesym             =update_symbol(bi_module,"encode");
06016   listingsym            =update_symbol(bi_module,"c_listing");
06017   /* provesym           =update_symbol(bi_module,"prove"); */
06018   delay_checksym        =update_symbol(bi_module,"delay_check");
06019   eval_argsym           =update_symbol(bi_module,"non_strict");
06020   inputfilesym          =update_symbol(bi_module,"input_file");
06021   call_handlersym       =update_symbol(bi_module,"call_handler");
06022   xf_sym                =update_symbol(bi_module,"xf");
06023   yf_sym                =update_symbol(bi_module,"yf");
06024   fx_sym                =update_symbol(bi_module,"fx");
06025   fy_sym                =update_symbol(bi_module,"fy");
06026   xfx_sym               =update_symbol(bi_module,"xfx");
06027   xfy_sym               =update_symbol(bi_module,"xfy");
06028   yfx_sym               =update_symbol(bi_module,"yfx");
06029   nullsym               =update_symbol(bi_module,"<NULL PSI TERM>");
06030   null_psi_term         =heap_psi_term(4);
06031   null_psi_term->type   =nullsym;
06032 
06033 
06034   set_current_module(no_module); /*  RM: Feb  3 1993  */
06035   t=update_symbol(no_module,"1");
06036   one=t->keyword->symbol;
06037   t=update_symbol(no_module,"2");
06038   two=t->keyword->symbol;
06039   t=update_symbol(no_module,"3");
06040   three=t->keyword->symbol;
06041   set_current_module(bi_module); /*  RM: Feb  3 1993  */
06042   t=update_symbol(bi_module,"year");
06043   year_attr=t->keyword->symbol;
06044   t=update_symbol(bi_module,"month");
06045   month_attr=t->keyword->symbol;
06046   t=update_symbol(bi_module,"day");
06047   day_attr=t->keyword->symbol;
06048   t=update_symbol(bi_module,"hour");
06049   hour_attr=t->keyword->symbol;
06050   t=update_symbol(bi_module,"minute");
06051   minute_attr=t->keyword->symbol;
06052   t=update_symbol(bi_module,"second");
06053   second_attr=t->keyword->symbol;
06054   t=update_symbol(bi_module,"weekday");
06055   weekday_attr=t->keyword->symbol;
06056   
06057   nothing->type=type;
06058   top->type=type;
06059 
06060   /* Built-in routines */
06061 
06062   /* Program database */
06063   new_built_in(bi_module,"dynamic",predicate,c_dynamic);
06064   new_built_in(bi_module,"static",predicate,c_static);
06065   new_built_in(bi_module,"assert",predicate,c_assert_last);
06066   new_built_in(bi_module,"asserta",predicate,c_assert_first);
06067   new_built_in(bi_module,"clause",predicate,c_clause);
06068   new_built_in(bi_module,"retract",predicate,c_retract);
06069   new_built_in(bi_module,"setq",predicate,c_setq);
06070   new_built_in(bi_module,"c_listing",predicate,c_listing);
06071   new_built_in(bi_module,"print_codes",predicate,c_print_codes);
06072 
06073   /* File I/O */
06074   new_built_in(bi_module,"get",predicate,c_get);
06075   new_built_in(bi_module,"put",predicate,c_put);
06076   new_built_in(bi_module,"open_in",predicate,c_open_in);
06077   new_built_in(bi_module,"open_out",predicate,c_open_out);
06078   new_built_in(bi_module,"set_input",predicate,c_set_input);
06079   new_built_in(bi_module,"set_output",predicate,c_set_output);
06080   new_built_in(bi_module,"exists_file",predicate,c_exists);
06081   new_built_in(bi_module,"close",predicate,c_close);
06082   new_built_in(bi_module,"simple_load",predicate,c_load);
06083   new_built_in(bi_module,"put_err",predicate,c_put_err);
06084   new_built_in(bi_module,"chdir",predicate,c_chdir);
06085 
06086   /* Term I/O */
06087   new_built_in(bi_module,"write",predicate,c_write);
06088   new_built_in(bi_module,"writeq",predicate,c_writeq);
06089   new_built_in(bi_module,"pretty_write",predicate,c_pwrite);
06090   new_built_in(bi_module,"pretty_writeq",predicate,c_pwriteq);
06091   new_built_in(bi_module,"write_canonical",predicate,c_write_canonical);
06092   new_built_in(bi_module,"page_width",predicate,c_page_width);
06093   new_built_in(bi_module,"print_depth",predicate,c_print_depth);
06094   new_built_in(bi_module,"put_err",predicate,c_put_err);
06095   new_built_in(bi_module,"parse",function,c_parse);
06096   new_built_in(bi_module,"read",predicate,c_read_psi);
06097   new_built_in(bi_module,"read_token",predicate,c_read_token);
06098   new_built_in(bi_module,"c_op",predicate,c_op); /*  RM: Jan 13 1993  */
06099   new_built_in(bi_module,"ops",function,c_ops);
06100   new_built_in(bi_module,"write_err",predicate,c_write_err);
06101   new_built_in(bi_module,"writeq_err",predicate,c_writeq_err);
06102 
06103   /* Type checks */
06104   new_built_in(bi_module,"nonvar",function,c_nonvar);
06105   new_built_in(bi_module,"var",function,c_var);
06106   new_built_in(bi_module,"is_function",function,c_is_function);
06107   new_built_in(bi_module,"is_predicate",function,c_is_predicate);
06108   new_built_in(bi_module,"is_sort",function,c_is_sort);
06109   
06110   new_built_in(bi_module,
06111                disjunction->keyword->symbol,
06112                function,
06113                c_eval_disjunction);
06114   
06115   /*  RM: Dec 16 1992  So the symbol can be changed easily */
06116 
06117   
06118   /* Arithmetic */
06119   insert_math_builtins();
06120 
06121   /* Comparison */
06122   new_built_in(syntax_module,"<",function,c_lt);  
06123   new_built_in(syntax_module,"=<",function,c_ltoe);  
06124   new_built_in(syntax_module,">",function,c_gt);  
06125   new_built_in(syntax_module,">=",function,c_gtoe);  
06126   new_built_in(syntax_module,"=\\=",function,c_diff);
06127   new_built_in(syntax_module,"=:=",function,c_equal);
06128   new_built_in(syntax_module,"and",function,c_and);
06129   new_built_in(syntax_module,"or",function,c_or);
06130   new_built_in(syntax_module,"not",function,c_not);
06131   new_built_in(syntax_module,"xor",function,c_xor);
06132   new_built_in(syntax_module,"===",function,c_same_address);
06133   
06134   /* RM: Nov 22 1993  */
06135   new_built_in(syntax_module,"\\===",function,c_diff_address); 
06136 
06137   /* Psi-term navigation */
06138   new_built_in(bi_module,"features",function,c_features);
06139   new_built_in(bi_module,"feature_values",function,c_feature_values); /* RM: Mar  3 1994  */
06140 
06141   /*  RM: Jul 20 1993  */
06142   
06143   new_built_in(syntax_module,".",function,c_project);/*  RM: Jul  7 1993  */
06144   new_built_in(bi_module,"root_sort",function,c_rootsort);
06145   new_built_in(bi_module,"strip",function,c_strip);
06146   new_built_in(bi_module,"copy_pointer",function,c_copy_pointer); /* PVR: Dec 17 1992 */
06147   new_built_in(bi_module,"has_feature",function,c_exist_feature); /* PVR: Dec 17 1992 */
06148 
06149   /* Unification and assignment */
06150   new_built_in(syntax_module,"<-",predicate,c_bk_assign);
06151   /* new_built_in(syntax_module,"<<-",predicate,c_assign);  RM: Feb 24 1993  */
06152   
06153   /*  RM: Feb 24 1993  */
06154   new_built_in(syntax_module,"<<-",predicate,c_global_assign);
06155   /* new_built_in(syntax_module,"<<<-",predicate,c_global_assign); */
06156   
06157   /*  RM: Feb  8 1993  */
06158   new_built_in(syntax_module,"{}",function,c_fail); /*  RM: Feb 16 1993  */
06159   new_built_in(syntax_module,"=",predicate,c_unify_pred);
06160   new_built_in(syntax_module,"&",function,c_unify_func);
06161   new_built_in(bi_module,"copy_term",function,c_copy_term);
06162   /* UNI new_built_in(syntax_module,":",function,c_unify_func); */
06163 
06164   /* Type hierarchy navigation */
06165   insert_type_builtins();
06166 
06167   /* String and character utilities */
06168   new_built_in(bi_module,"str2psi",function,c_string2psi);
06169   new_built_in(bi_module,"psi2str",function,c_psi2string);
06170   new_built_in(bi_module,"int2str",function,c_int2string);
06171   new_built_in(bi_module,"asc",function,c_ascii);
06172   new_built_in(bi_module,"chr",function,c_char);
06173 
06174   /* Control */
06175   new_built_in(syntax_module,"|",function,c_such_that);
06176   new_built_in(bi_module,"cond",function,c_cond);
06177   new_built_in(bi_module,"if",function,c_cond);
06178   new_built_in(bi_module,"eval",function,c_eval);
06179   new_built_in(bi_module,"evalin",function,c_eval_inplace);
06180   /* new_built_in(bi_module,"quote",function,c_quote); */
06181   /*new_built_in(bi_module,"call_once",function,c_call_once);*/ /* DENYS: Jan 25 1995 */
06182   /* new_built_in(bi_module,"call",function,c_call); */
06183   /* new_built_in(bi_module,"undefined",function,c_fail); */ /* RM: Jan 13 1993 */
06184   new_built_in(bi_module,"print_variables",predicate,c_print_variables);
06185   new_built_in(bi_module,"get_choice",function,c_get_choice);
06186   new_built_in(bi_module,"set_choice",predicate,c_set_choice);
06187   new_built_in(bi_module,"exists_choice",function,c_exists_choice);
06188   new_built_in(bi_module,"apply",function,c_apply);
06189   new_built_in(bi_module,"bool_pred",predicate,c_boolpred);
06190 
06191   new_built_in(syntax_module,":-",predicate,c_declaration);
06192   new_built_in(syntax_module,"->",predicate,c_declaration);
06193   /* new_built_in(syntax_module,"::",predicate,c_declaration); */
06194   new_built_in(syntax_module,"<|",predicate,c_declaration);
06195   new_built_in(syntax_module,":=",predicate,c_declaration);
06196   new_built_in(syntax_module,";",predicate,c_disj);
06197   new_built_in(syntax_module,"!",predicate,c_not_implemented);
06198   new_built_in(syntax_module,",",predicate,c_succeed);
06199   new_built_in(bi_module,"abort",predicate,c_abort);
06200   new_built_in(bi_module,"halt",predicate,c_halt);
06201   new_built_in(bi_module,"succeed",predicate,c_succeed);
06202   new_built_in(bi_module,"repeat",predicate,c_repeat);
06203   new_built_in(bi_module,"fail",predicate,c_fail);
06204   /* new_built_in(bi_module,"freeze",predicate,c_freeze); PVR 16.9.93 */
06205   new_built_in(bi_module,"implies",predicate,c_implies);
06206   new_built_in(bi_module,"undo",predicate,c_undo);
06207   new_built_in(bi_module,"delay_check",predicate,c_delay_check);
06208   new_built_in(bi_module,"non_strict",predicate,c_non_strict);
06209   
06210   /* System */
06211   insert_system_builtins();
06212 
06213   new_built_in(bi_module,"strcon",function,c_concatenate);
06214   new_built_in(bi_module,"strlen",function,c_string_length);
06215   new_built_in(bi_module,"substr",function,c_sub_string);
06216   new_built_in(bi_module,"append_file",predicate,c_append_file);
06217   new_built_in(bi_module,"random",function,c_random);
06218   new_built_in(bi_module,"initrandom",predicate,c_initrandom);
06219 
06220   /*  RM: Jan  8 1993  */
06221   new_built_in(bi_module,"set_module",predicate,c_set_module);
06222   new_built_in(bi_module,"open_module",predicate,c_open_module);
06223   new_built_in(bi_module,"public",predicate,c_public);
06224   new_built_in(bi_module,"private",predicate,c_private);
06225   new_built_in(bi_module,"display_modules",predicate,c_display_modules);
06226   new_built_in(bi_module,"trace_input",predicate,c_trace_input);
06227   new_built_in(bi_module,"substitute",predicate,c_replace);
06228   new_built_in(bi_module,"current_module",function,c_current_module);
06229   new_built_in(bi_module,"module_name",function,c_module_name);
06230   new_built_in(bi_module,"combined_name",function,c_combined_name);
06231   /* new_built_in(bi_module,"#",function,c_module_access); */
06232   
06233   /* Hack so '.set_up' doesn't issue a Warning message */
06234   /*  RM: Feb  3 1993  */
06235   hash_lookup(bi_module->symbol_table,"set_module")->public=TRUE;
06236   hash_lookup(bi_module->symbol_table,"built_in")->public=TRUE;
06237 
06238   /*  RM: Jan 29 1993  */
06239   abortsym=update_symbol(bi_module,"abort"); /* 26.1 */
06240   aborthooksym=update_symbol(bi_module,"aborthook"); /* 26.1 */
06241   tracesym=update_symbol(bi_module,"trace"); /* 26.1 */
06242 
06243   
06244   /*  RM: Feb  9 1993  */
06245   new_built_in(bi_module,"global",predicate,c_global);
06246   new_built_in(bi_module,"persistent",predicate,c_persistent);
06247   new_built_in(bi_module,"display_persistent",predicate,c_display_persistent);
06248   new_built_in(bi_module,"alias",predicate,c_alias);
06249 
06250   /*  RM: Mar 11 1993  */
06251   new_built_in(bi_module,"private_feature",predicate,c_private_feature);
06252   add_module1=update_symbol(bi_module,"features");
06253   add_module2=update_symbol(bi_module,"str2psi");
06254   add_module3=update_symbol(bi_module,"feature_values"); /* RM: Mar  3 1994  */
06255 
06256   /*  RM: Jun 29 1993  */
06257   new_built_in(bi_module,"split_double",function,c_split_double);
06258   new_built_in(bi_module,"string_address",function,c_string_address);
06259 
06260   /*  RM: Jul 15 1993  */
06261   new_built_in(bi_module,"deref_length",function,c_deref_length);
06262 
06263 
06264   /*  RM: Sep 20 1993  */
06265   new_built_in(bi_module,"argv",function,c_args);
06266 
06267   /* RM: Jan 28 1994  */
06268   new_built_in(bi_module,"public_symbols",function,all_public_symbols);
06269                
06270 #ifdef CLIFE
06271   life_reals();
06272 #endif /* CLIFE */
06273 
06274   insert_sys_builtins();
06275 }

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