C:/Users/Dennis/src/lang/russell.orig/src/pass4/findsig.c

Go to the documentation of this file.
00001 # define TRACE
00002 # undef TRACE
00003 # define DEBUG
00004 
00005 # define TRACE2
00006 # undef TRACE2
00007 
00008 # ifdef DEBUG
00009 #   define IFDEBUG(x) x
00010 # else
00011 #   define IFDEBUG(x)
00012 # endif
00013 
00014 # include <stdio.h>
00015 # include "parm.h"
00016 # include "arith.h"
00017 
00018 # include "stree/ststructs.mh"
00019 # ifdef DEBUG
00020 #   include "stree/is_ptr.h"
00021 # endif
00022 
00023 # include "sigs.h"
00024 
00025 # include "stree/Array.h"
00026 
00027 /* Needed to construct type signatures for constructions */
00028 # include "pass1/stt/sttdefs.h"
00029 
00030 extern FILE * unparse_file;
00031 
00032 extern boolean Gflag;
00033 
00034 extern boolean Nflag;  /* No Call/cc calls */
00035 
00036 # define UNDEFNAME ((sttrelptr) 0)   /* the name of an anonymous identifier */
00037 
00038 extern sttrelptr indx_New,
00039                  indx_ValueOf,
00040                  indx_assign,
00041                  indx_equals,
00042                  indx_ne,
00043                  indx_Mk,
00044                  indx_First,
00045                  indx_Last,
00046                  indx_Pred,
00047                  indx_Succ,
00048                  indx_Ord,
00049                  indx_OrdInv,
00050                  indx_Card,
00051                  indx_In,
00052                  indx_Out;
00053 
00054 extern NODE * sig_New,
00055             * sig_ValueOf,
00056             * sig_assign,
00057             * sig_equals,
00058             * sig_const,
00059             * val_Boolean,
00060             * val_Integer,
00061             * val_Void,
00062             * sig_Signature;
00063 
00064 /* Given a type sig comp corr to a function, set the inline code to match */
00065 /* the special field                                                      */
00066 # define init_inline(r) \
00067         (r) -> tsc_signature -> fsig_inline_code = \
00068         (*spcl_to_inline)((r) -> tsc_signature -> fsig_special);
00069 
00070 extern int yynerrs;
00071 
00072 extern int next_pre; /* needed so that comparison for declarations will */
00073                      /* continue to work.                               */
00074 
00075 # define ERR_NODE_DEFINED
00076 extern NODE * err_node;        /* node to be used for error message in lieu */
00077                                /* of current node.  Used by errmsg macros   */
00078 extern char * err_msg;         /* message to be used in lieu of usual one   */
00079 
00080 extern NODE * curr_tsig; 
00081            /* type signature corresponding to local type identifier */
00082 
00083 NODE * declerr;     /* declsig failure indication */
00084 
00085 NODE * substerr;    /* subst error indication                       */
00086                     /* Set to something other than SUCCESS if       */
00087                     /* subst is asked to substitute an incompletely */
00088                     /* expanded expression, as indicated by         */
00089                     /* dontsubst                                    */
00090 
00091 extern int match_len;      /* length of argument type.  Set by amatch. */
00092 extern unsigned * match_delv;  /* bitvector indicating necessary deletions */
00093                                /* set by amatch.                           */
00094 
00095 extern NODE * failed_asig;  /* Set by amatch to indicate last failure */
00096 extern NODE * failed_psig;  /* Used as a hint in error message        */
00097 extern NODE * failed_comp;
00098 
00099 struct cn * dontsubst = NIL; /* list of incompletely expanded nodes  */
00100                               /* which should not be substituted into */
00101                               /* signatures.                          */
00102 
00103 extern int comp_index;
00104 
00105 # ifdef VAX
00106     int nargs();
00107 # endif
00108 
00109 void find_inline();
00110 
00111 void Gfind_inline();
00112 
00113 boolean may_fail = FALSE; /* current signature deduction may fail */
00114                           /* without dire consequences.           */
00115 
00116 /*
00117  *    findsig(p,dont_coerce) finds the signature corresponding to the expression
00118  * tree rooted at p and of all its subexpressions.
00119  *    If the sig_done field of p is already SIG_IN_PROGRESS it fails by 
00120  * returning the pointer p.
00121  *    If it is SIG_DONE findsig immediately returns SUCCESS. 
00122  *    If sig_done is originally NIL it is set to SIG_IN_PROGRESS
00123  * and begins the (usually recursive) signature computation.
00124  * If any of the subsidiary computations fail by running into a computation
00125  * which is already IN_PROGRESS the offending
00126  * node pointer is returned.
00127  *    If findsig succeeds in determining the signature it stores it in the
00128  * signature field and returns SUCCESS.
00129  *    IN_PROGRESS is thus used to detect and abort non-terminating
00130  * signature calculations.
00131  *    The special value ERR_SIG is used to avoid avalanche errors.  It is
00132  * treated as an acceptable signature in all contexts.
00133  *    Note that it is not acceptable to immediately set signatures
00134  * to ERR_SIG once a cycle is encountered.  It is quite possible
00135  * that the cycle is encountered as a result of using one particular
00136  * branch of a conditional to evaluate its signature, and that
00137  * backtracking and using another branch will still result in success.
00138  *    Dont_coerce indicates that the expression is used in a context
00139  * in which the result signature doesnt matter.  Thus no attempt
00140  * need be made to coerce the branches of a conditional to match.
00141  * Note that the value of this argument only matters the first time
00142  * findsig is called on a given node.
00143  *    The sig_done field is set to SIG_DONE whenever signature computation
00144  * for that node is completed.  The one exception are anonymous local
00145  * type identifiers.  In their case the signature must be recomputed
00146  * each time the node is encountered.
00147  */
00148 
00149                     /* Finish up after recognizing a separately reported */
00150                     /* error.                                            */
00151 # define err_return \
00152     p -> signature = ERR_SIG; \
00153     p -> sig_done = SIG_DONE; \
00154     return(SUCCESS);            /* dealt with it here */
00155 
00156 # ifdef DEBUG
00157     NODE * return_val;
00158 #   define return(p) { return_val = p; goto findsig_out; }
00159 # endif
00160 
00161 NODE * findsig(p, dont_coerce)
00162 register NODE * p;
00163 boolean dont_coerce;
00164 {
00165     register int knd;
00166     register int status = p -> sig_done;
00167     NODE * q, * r;
00168     boolean all_ok;     /* signature evaluation for all subexpressions  */
00169                         /* was successful.                              */
00170 
00171 #   ifdef DEBUG
00172 #     ifdef VAX
00173         if(nargs() != 2) {
00174             dbgmsg("findsig: wrong number of args\n");
00175             abort();
00176         }
00177 #    endif
00178 #   endif
00179 #   ifdef DEBUG
00180         if (p == (NODE *)0x40404040) abort();
00181                 /* use for "conditional breakpoint" */
00182 #   endif
00183     if (status == SIG_DONE)
00184         return(SUCCESS);
00185     if (status == SIG_IN_PROGRESS /* infinite signature computation */) {
00186         return(p);
00187     }
00188     knd = p -> kind;
00189 #   ifdef DEBUG
00190         if ( p -> signature != NIL
00191             && knd != OPRID && knd != LETTERID && knd != FUNCCONSTR ) {
00192             dbgmsg("findsig: bad sig_done value, knd = %s, sig:\n",
00193                     kindname(knd));
00194             prtree(p);
00195             prtree(p -> signature);
00196             abort();
00197         }
00198 #   endif
00199     /* compute new signature */
00200         p -> sig_done = SIG_IN_PROGRESS;
00201         switch(knd) {
00202             case OPRID:
00203             case LETTERID:
00204                 return(findidsig(p));
00205 
00206             case VALSIGNATURE:
00207             case VARSIGNATURE:
00208             case FUNCSIGNATURE:
00209             case TYPESIGNATURE:
00210             case SIGNATURESIG:
00211                 initsig(p, sig_Signature);
00212                 p -> sig_done = SIG_DONE;
00213                 return(SUCCESS);
00214 
00215             case FUNCCONSTR:
00216 #               ifdef DEBUG
00217                   if(p -> signature == NIL) {
00218                     /* not possible: function signatures must be at least */
00219                     /* partially specified.                               */
00220                     dbgmsg("NIL FUNCCONSTR signature\n");
00221                     abort();
00222                   }
00223 #               endif
00224                 q = p -> signature -> fsig_result_sig;
00225                 if (q == NIL /* need to fill in result signature */) {
00226                     if ((r = findsig(p -> fc_body,FALSE)) != SUCCESS) {
00227                         p -> sig_done = SIG_UNKNOWN;
00228                         return(r);
00229                     }
00230                     if(p -> fc_body -> signature != ERR_SIG) {
00231                         initfld(&(p -> signature -> fsig_result_sig),
00232                                 p -> fc_body -> signature);
00233                         if (Gflag) {
00234                           Gfind_inline(p);
00235                         } else {
00236                           find_inline(p);
00237                         }
00238                     } else {
00239                         p -> signature -> fsig_result_sig = ERR_SIG;
00240                     }
00241                     p -> sig_done = SIG_DONE;
00242                     return(SUCCESS);
00243                 } else {
00244                     /* find signature of body if possible */
00245                         boolean old_may_fail = may_fail;
00246                         boolean is_void = comp_st(val_Void, q, NIL, NIL) == 0;
00247 
00248                         if (p -> fc_body -> kind == EXTERNDEF) {
00249                             p -> sig_done = SIG_DONE;
00250                             if (Gflag) {
00251                               Gfind_inline(p);
00252                             } else {
00253                               find_inline(p);
00254                             }
00255                             return(SUCCESS);
00256                         }
00257                         may_fail = TRUE;    /* This has low priority */
00258                         r = findsig(p -> fc_body, is_void);
00259                         may_fail = old_may_fail;
00260                         if (r != SUCCESS) {
00261                             dontsubst = cn_cons(p, dontsubst);
00262                             p -> sig_done = SIG_DONE;
00263                             return(SUCCESS);
00264                         }
00265                     /* q is still the result signature */
00266                     if (q == ERR_SIG
00267                         || p -> fc_body -> signature == ERR_SIG) {
00268                         p -> sig_done = SIG_DONE;
00269                         return(SUCCESS);
00270                     }
00271                     if (q -> kind == VALSIGNATURE && !is_void
00272                            && p -> fc_body -> signature -> kind
00273                               != VALSIGNATURE) {
00274                         /* attempt coercion */
00275                             NODE * nresult;
00276 
00277                             nresult = coerce(p -> fc_body);
00278                             if ((r = findsig(nresult,FALSE)) != SUCCESS) {
00279                                 p -> sig_done = SIG_UNKNOWN;
00280                                 vfree(nresult);
00281                                 return(r);
00282                             }
00283                             chgfld(&(p -> fc_body), nresult);
00284                     }
00285                     if (q -> kind == TYPESIGNATURE
00286                         && amatch(p -> fc_body -> signature,q)
00287                         && match_delv != NIL) {  /* forget components */
00288                         NODE * nresult = mknode(MODPRIMARY,
00289                                                 p -> fc_body,
00290                                                 NIL,
00291                                                 match_delv
00292                                                );
00293 
00294                         nresult -> mp_orig_length = match_len;
00295                         initfld(&(nresult -> signature), q);
00296                         nresult -> sig_done = SIG_DONE;
00297                         chgfld(&(p -> fc_body), nresult);
00298                     }
00299                     /* replace result signature to take advantage of */
00300                     /* optimization information                      */
00301                     if (comp_st(p -> fc_body -> signature,
00302                                 p -> signature -> fsig_result_sig,
00303                                 NIL, NIL) == 0) {
00304                         chgfld(&(p -> signature -> fsig_result_sig),
00305                                p -> fc_body -> signature);
00306                     }
00307                     if (Gflag) {
00308                       Gfind_inline(p);
00309                     } else {
00310                       find_inline(p);
00311                     }
00312                     p -> sig_done = SIG_DONE;
00313                     return(SUCCESS);
00314                 }
00315 
00316             case APPLICATION:
00317                 return(findapplsig(p));
00318 
00319             case GUARDEDLIST:
00320                 {
00321                     NODE * good_element;    /* element which can be used to */
00322                                             /* determine signature          */
00323                     boolean kinds_differ;   /* signatures of guarded        */
00324                                             /* elements have different kind */
00325                                             /* fields                       */
00326                     boolean coerce_guards;  /* Guards need to be coerced    */
00327                     int prev_kind = -1;     /* previous element kind        */
00328                     int curr_kind;
00329                     boolean old_may_fail = may_fail;
00330 
00331                     good_element = NIL;
00332                     all_ok = TRUE;
00333                     kinds_differ = FALSE;
00334                     coerce_guards = FALSE;
00335                     /* find signatures of guarded expressions where possible */
00336                         maplist(q, p -> gl_list, {
00337                             IFDEBUG(
00338                                 if(q -> kind != GUARDEDELEMENT) {
00339                                     dbgmsg("findsig: Bad guarded element\n");
00340                                 }
00341                             )
00342                             if(findsig(q -> ge_element,dont_coerce) == SUCCESS) {
00343                                 good_element = q;
00344                                 if (q -> ge_element -> signature != ERR_SIG) {
00345                                     curr_kind = q -> ge_element -> signature
00346                                                   -> kind;
00347                                     if (prev_kind != -1 
00348                                         && curr_kind != prev_kind) {
00349                                         kinds_differ = TRUE;
00350                                     }
00351                                     prev_kind = curr_kind;
00352                                 }
00353                             } else {
00354                                 all_ok = FALSE;
00355                             }
00356                         });
00357                     may_fail = TRUE;
00358                     /* Now find signatures of guards */
00359                         begin_maplist(s, p -> gl_list) {
00360                             if((q = findsig(s -> ge_guard,FALSE)) != SUCCESS) {
00361 #                               ifdef TRACE
00362                                     printf("Couldn't find guard signature\n");
00363 #                               endif
00364                                 all_ok = FALSE;
00365                             } else if (s -> ge_guard -> signature != ERR_SIG
00366                                        && s -> ge_guard -> signature -> kind
00367                                           != VALSIGNATURE) {
00368 #                               ifdef TRACE
00369                                     printf("Must coerce guards\n");
00370 #                               endif
00371                                 coerce_guards = TRUE;
00372                             }
00373                         } end_maplist;
00374                     may_fail = old_may_fail;
00375                     if (good_element == NIL || (may_fail && !all_ok)) {
00376                         /* cant determine signature of any subexpression */
00377                         /* or its not worth going on partial info        */
00378                         p -> sig_done = SIG_UNKNOWN;
00379 #                       ifdef TRACE
00380                             printf("Giving up\n");
00381 #                       endif
00382                         return(p);
00383                     }
00384                     if ( (kinds_differ || coerce_guards)
00385                          /* && (all_ok || !may_fail) */) {
00386                         /* add omitted V and constant application coercions */
00387                         /* where possible                                   */
00388                             if ((!dont_coerce) && kinds_differ) {
00389                               /* May be impossible to find result sig */
00390                               /* after coercion                       */
00391                                 good_element = NIL;
00392                             }
00393                             begin_maplist(s, p -> gl_list) {
00394                                 if (!dont_coerce && kinds_differ
00395                                     && s -> ge_element -> signature != NIL) {
00396                                     NODE * nelement = coerce(s -> ge_element);
00397                              
00398                                     if (nelement -> sig_done == SIG_UNKNOWN) {
00399                                       if ((q = findsig(nelement, FALSE)) 
00400                                         == SUCCESS) {
00401                                         good_element = s;
00402                                         chgfld(&(s -> ge_element), nelement);
00403                                       } else {
00404                                         all_ok = FALSE;
00405                                         vfree(nelement);
00406                                         if (may_fail) {
00407                                             p -> sig_done = SIG_UNKNOWN;
00408                                             return(s);
00409                                         }
00410                                       }
00411                                     } else {
00412                                       good_element = s;
00413                                     }
00414                                 }
00415                                 if (coerce_guards
00416                                     && s -> ge_guard -> signature != NIL) {
00417                                     NODE * nguard = lock(coerce(s -> ge_guard));
00418 
00419 #                                   ifdef TRACE
00420                                         printf("Coercing guard\n");
00421 #                                   endif
00422                                     if (nguard -> sig_done == SIG_UNKNOWN) {
00423                                       if ((q = findsig(nguard, FALSE)) 
00424                                         == SUCCESS) {
00425 #                                       ifdef TRACE
00426                                             printf("Changed ");
00427                                             unparse_file = stdout;
00428                                             unparse(s -> ge_guard);
00429                                             printf(" to ");
00430                                             unparse(nguard);
00431                                             printf(" with signature ");
00432                                             unparse(nguard -> signature);
00433                                             printf("and refcount %d\n", nguard -> refcount);
00434 #                                       endif
00435                                         chgfld(&(s -> ge_guard), nguard);
00436                                         unlock(nguard);
00437                                       } else {
00438                                         vfree(unlock(nguard));
00439                                         p -> sig_done = SIG_UNKNOWN;
00440                                         return(s);
00441                                       }
00442                                     }
00443                                 }
00444                             }end_maplist;
00445                     }
00446                     /* At least one element had val or func signature */
00447                     /* It must have been possible to determine its    */
00448                     /* signature after coercion. Thus good_element    */
00449                     /* != NIL                                         */
00450 #                   ifdef DEBUG
00451                         if (good_element == NIL) {
00452                             dbgmsg("findsig: bad good_element\n");
00453                         }
00454 #                   endif
00455                     if(!all_ok) {
00456                         /* signature is known, but subexpressions havent  */
00457                         /* been completely expanded.                      */
00458                         dontsubst = cn_cons(p, dontsubst);
00459                     }
00460                     initsig(p, good_element -> ge_element -> signature);
00461                     if (!dont_coerce /* value matters */) 
00462                       /* Fix up code generator information */
00463                         maplist(q, p -> gl_list, {
00464                             r = fixhints(p -> signature,
00465                                          q -> ge_element -> signature);
00466                             if (r != p -> signature) {
00467                                 chgsig(p, r);
00468                             }
00469                         });
00470                     p -> sig_done = SIG_DONE;
00471                     return(SUCCESS);
00472                 }
00473 
00474             case BLOCKDENOTATION:
00475                 {
00476                     NODE * last_den = last(p -> bld_den_seq);
00477                     boolean old_may_fail = may_fail;
00478 
00479                     if((q = findsig(last_den,FALSE)) != SUCCESS) {
00480                         p -> sig_done = SIG_UNKNOWN;
00481                         return(q);
00482                     }
00483                     all_ok = TRUE;
00484                     may_fail = TRUE;
00485                     /* Now find signatures of all subexpressions */
00486                         maplist(s, p -> bld_declaration_list, {
00487                             if((q = findsig(s -> decl_denotation,FALSE)) != SUCCESS) {
00488                                 all_ok = FALSE;
00489                             }
00490                         });
00491                         maplist(s, p -> bld_den_seq, {
00492                             if((q = findsig(s,TRUE)) != SUCCESS) {
00493                                 all_ok = FALSE;
00494                             }
00495                         });
00496                     may_fail = old_may_fail;
00497                     initsig(p, last_den -> signature);
00498                     if (!Nflag || !(p -> bld_flags & NO_SURR_LOOP)) {
00499                         /* May need a.r. for this block */
00500                         clear_slink_known(p -> signature);
00501                     }
00502                     if (!all_ok)
00503                         dontsubst = cn_cons(p, dontsubst);
00504                     p -> sig_done = SIG_DONE;
00505                     return(SUCCESS);
00506                 }
00507 
00508             case USELIST:
00509                 {
00510                     NODE * last_den = last(p -> usl_den_seq);
00511                     boolean old_may_fail = may_fail;
00512 
00513                     /* find signatures of types */
00514                         maplist(s, p -> usl_type_list, {
00515                             if((q = findsig(s,FALSE)) != SUCCESS) {
00516                                 p -> sig_done = SIG_UNKNOWN;
00517                                 return(q);
00518                             } else {
00519                                 if (s -> signature != ERR_SIG
00520                                     && (s -> signature -> kind == LETTERID
00521                                         || s -> signature -> kind == OPRID)) {
00522                                     chgfld(&(s -> signature),
00523                                            sig_structure(s -> signature));
00524                                 }
00525                             }
00526                         });
00527                     if((q = findsig(last_den,FALSE)) != SUCCESS) {
00528                         p -> sig_done = SIG_UNKNOWN;
00529                         return(q);
00530                     }
00531                     /* Now find signatures of all subexpressions */
00532                         may_fail = TRUE;
00533                         all_ok = TRUE;
00534                         maplist(s, p -> usl_den_seq, {
00535                             if((q = findsig(s,TRUE)) != SUCCESS) {
00536                                 all_ok = FALSE;
00537                             }
00538                         });
00539                         may_fail = old_may_fail;
00540                     initsig(p, last_den -> signature);
00541                     if (!all_ok)
00542                         dontsubst = cn_cons(p, dontsubst);
00543                     p -> sig_done = SIG_DONE;
00544                     return(SUCCESS);
00545                 }
00546 
00547             case WORDELSE:
00548                 initfld(&(p -> signature), val_Boolean);
00549                 p -> sig_done = SIG_DONE;
00550                 return(SUCCESS);
00551 
00552             case LOOPDENOTATION:
00553                 {
00554                   /* Find signatures of all subexpressions */
00555                     boolean old_may_fail = may_fail;
00556 
00557                     all_ok = TRUE;
00558                     may_fail = TRUE;
00559                     maplist(s, p -> gl_list, {
00560                         if((q = findsig(s -> ge_guard,FALSE)) != SUCCESS) {
00561                             all_ok = FALSE;
00562                         } else {
00563                           /* coerce if necessary */
00564                             NODE * nguard = coerce(s -> ge_guard);
00565 
00566                             if (nguard -> sig_done == SIG_UNKNOWN) {
00567                               if ((q = findsig(nguard, FALSE)) 
00568                                 == SUCCESS) {
00569                                 chgfld(&(s -> ge_guard), nguard);
00570                               } else {
00571                                 vfree(nguard);
00572                                 p -> sig_done = SIG_UNKNOWN;
00573                                 may_fail = old_may_fail;
00574                                 return(s);
00575                               }
00576                             }
00577                         }
00578                         if((q = findsig(s -> ge_element,TRUE)) != SUCCESS) {
00579                             all_ok = FALSE;
00580                         }
00581                     });
00582                     may_fail = old_may_fail;
00583                   initfld(&(p -> signature), val_Void);
00584                   if (!all_ok)
00585                     dontsubst = cn_cons(p, dontsubst);
00586                   p -> sig_done = SIG_DONE;
00587                   return(SUCCESS);
00588                 }
00589 
00590 #           ifdef DEBUG
00591               case WORDCAND:
00592               case WORDCOR:
00593                 dbgmsg("findsig: cand or cor in syntax tree\n");
00594                 return(SUCCESS);
00595 #           endif
00596             case QSTR:
00597             case UQSTR:
00598                 if ((q = findstdecl(p)) != SUCCESS) {
00599                     p -> sig_done = SIG_UNKNOWN;
00600                     return(q);
00601                 }
00602                 if (p -> sel_type == NIL) {
00603                     switch(p -> kind) {
00604                         case QSTR:  
00605                             errmsg1(p,
00606                                     "No appropriate type for \"%s\"",
00607                                     p -> str_string);
00608                             break;
00609                         case UQSTR:
00610                             errmsg1(p,
00611                                     "No appropriate type for %s",
00612                                     p -> str_string);
00613                             break;
00614                     }
00615                     p -> signature = ERR_SIG;
00616                     p -> sig_done = SIG_DONE;
00617                     return(SUCCESS);
00618                 }
00619                 if ((q = findsig(p -> sel_type, dont_coerce)) != SUCCESS) {
00620                     p -> sig_done = SIG_UNKNOWN;
00621                     return(q);
00622                 }
00623                 {
00624                     NODE * sel_sig = p -> sel_type -> signature;
00625                     NODE * r;
00626                     int maxlen;  /* Maximum length for validity of */
00627                                  /* ts_string_code                 */
00628 
00629                     if (sel_sig == ERR_SIG) {
00630                         p -> signature = ERR_SIG;
00631                         p -> sig_done = SIG_DONE;
00632                         return(SUCCESS);
00633                     }
00634                     if (sel_sig -> ts_string_max == -1) {
00635                         maxlen = MAXSTRLEN;
00636                     } else {
00637                         maxlen = sel_sig -> ts_string_max;
00638                     }
00639                     if (sel_sig -> ts_string_code != NIL
00640                         && sel_sig -> ts_element_code != NIL
00641                         && strlen(p -> str_string) <= maxlen
00642                         && p -> sel_type -> kind == LETTERID
00643                         && p -> sel_type -> sel_type == NIL) {
00644                         if ((r = on_dontsubst(p -> sel_type)) != NIL) {
00645                             p -> sig_done = SIG_UNKNOWN;
00646                             return(r);
00647                         }
00648                         /* Safe to take a shortcut */
00649                         initsig(p, mknode(VALSIGNATURE, p -> sel_type));
00650                         p -> sig_done = SIG_DONE;
00651                         return(SUCCESS);
00652                     }
00653                 }
00654                 if (p -> str_expansion == NIL) {
00655                     initfld(&(p->str_expansion), expand_str(p));
00656                 }
00657                 if ((q = findsig(p -> str_expansion, dont_coerce)) == SUCCESS) {
00658                     initsig(p, p -> str_expansion -> signature);
00659                     p -> sig_done = SIG_DONE;
00660                     return(SUCCESS);
00661                 } else {
00662                     p -> sig_done = SIG_UNKNOWN;
00663                     return(q);
00664                 }
00665 
00666             case MODPRIMARY:
00667                 return(findmpsig(p));
00668 
00669             case PRODCONSTRUCTION:
00670                 {
00671                     NODE * par_list = p -> prod_components;
00672                     NODE * arg_list;  /* fake argument list, used */
00673                                       /* for substitutions        */
00674                     NODE * comp_list = lock(emptylist());
00675                     NODE * local_id = p -> prod_local_type_id == NIL?
00676                                         mknode(LETTERID, UNDEFNAME)
00677                                       : copynode(p -> prod_local_type_id);
00678                     NODE * self = mknode(VALSIGNATURE, local_id);
00679                     boolean simple_type = TRUE;
00680                     int len = length(par_list);
00681                     int i;
00682 
00683                     /* Compute product size */
00684                         if (Gflag) {
00685                             len = 0;
00686                             maplist(s, par_list, {
00687                                 if (!vacuous_arg(s -> par_signature)) {
00688                                     len++;
00689                                 }
00690                             });
00691                         } else {
00692                             len = length(par_list);
00693                         }
00694                     /* Put New, ValueOf and := in component list */
00695                         r = mknode(TSCOMPONENT,
00696                                    mkcompnm(indx_New),
00697                                    copynode(sig_New));
00698                         r -> tsc_signature -> fsig_special = 
00699                             special(PROD_NEW, len);
00700                         init_inline(r);
00701                         addright(comp_list, r);
00702                         r = mknode(TSCOMPONENT,
00703                                    mkcompnm(indx_ValueOf),
00704                                    copynode(sig_ValueOf));
00705                         r -> tsc_signature -> fsig_special = 
00706                             special(PROD_VALUEOF, len);
00707                         init_inline(r);
00708                         addright(comp_list, r);
00709                         r = mknode(TSCOMPONENT,
00710                                    mkcompnm(indx_assign),
00711                                    copynode(sig_assign));
00712                         r -> tsc_signature -> fsig_special = 
00713                             special(PROD_ASSIGN, len);
00714                         init_inline(r);
00715                         addright(comp_list, r);
00716 
00717                     /* add Mk function */
00718                         r = mknode(TSCOMPONENT,
00719                                    mkcompnm(indx_Mk),
00720                                    mknode(FUNCSIGNATURE, NIL,
00721                                           par_list,
00722                                           self
00723                                          )
00724                                   );
00725                         r -> tsc_signature -> fsig_special = 
00726                             special(PROD_MK, len);
00727                         init_inline(r);
00728                         addright(comp_list, r);
00729 
00730                     {/* add projection functions                       */ 
00731                       NODE * par = emptylist(); /* parameter list for */
00732                                                 /* func signature     */
00733                       NODE * arg = emptylist();  /* list containing      */
00734                                                  /* argument in function */
00735                                                  /* applications         */
00736                       NODE * t;
00737 
00738                       /* fix up par and arg */
00739                         addright(par, t = mknode(PARAMETER, NIL, self));
00740                         t -> pre_num = next_pre++;
00741                             /* so copies can be recognized */
00742                         addright(arg, t = mknode(LETTERID, UNDEFNAME));
00743                         t -> id_last_definition = first(par);
00744                         t -> id_def_found = TRUE;
00745 
00746                       /* build arg_list */
00747                         arg_list = lock(emptylist());
00748                         maplist(s, par_list, {
00749                           r = copynode(s -> par_id);
00750                           chgfld(&(r -> sel_type), local_id);
00751                           r -> id_last_definition = NIL;
00752                           r -> id_def_found = TRUE;
00753                           r = mknode(APPLICATION, r, arg);
00754                           addright(arg_list,r);
00755                         });
00756                       i = 0;
00757                       maplist(s, par_list, {
00758                         boolean vac = Gflag && vacuous_arg(s -> par_signature);
00759                                     /* Not represented in product */
00760 
00761                         r = mknode(FUNCSIGNATURE,
00762                                    NIL /* SHOULD BE INLINE CODE */,
00763                                    par,
00764                                    subst(s -> par_signature,
00765                                          par_list,
00766                                          arg_list)
00767                                   );
00768                         if (!vac) { 
00769                             r -> fsig_special = special(PROD_PROJ, i);
00770                         } else {
00771                             r -> fsig_special = special(UNDEF_CONST, 0);
00772                         }
00773                         IFDEBUG(
00774                           if(substerr != NIL) {
00775                             dbgmsg("findsig: unexpected substerr\n");
00776                           }
00777                         )
00778                         if (s -> par_id == NIL) {
00779                             errmsg0(s, "Product component not named");
00780                         }
00781                         r = mknode(TSCOMPONENT, s -> par_id, r);
00782                         init_inline(r);
00783                         addright(comp_list, r);
00784                         if (!vac) {
00785                             i++;
00786                         }
00787                       });
00788                     }
00789                     initsig(p, mknode(TYPESIGNATURE,
00790                                       local_id,
00791                                       comp_list,
00792                                       NIL, NIL, NIL));
00793                     p -> signature -> pre_num = next_pre++;
00794                                 /* so copies can be recognized */
00795                     tsig_order(p -> signature);
00796                     /* Make references to product local type id point to */
00797                     /* signature instead                                 */
00798                       /* Make sure tsubst doesn't get confused */
00799                         local_id -> id_def_found = TRUE;
00800                         local_id -> id_last_definition = p -> signature;
00801                       chgfld(&(p -> signature), tsubst(p -> signature,
00802                                                        p,
00803                                                        local_id,
00804                                                        FALSE));
00805                     /* Fix up local_id */
00806                       local_id -> id_def_found = TRUE;
00807                       local_id -> id_last_definition = p -> signature;
00808                     p -> sig_done = SIG_DONE;
00809                     /* Compute whether resulting type is "simple" */
00810                         maplist(s, par_list, {
00811                           switch(s -> par_signature -> kind) {
00812                             case FUNCSIGNATURE:
00813                             case TYPESIGNATURE:
00814                                 simple_type = FALSE;
00815                                 break;
00816                             case VALSIGNATURE:
00817                                 if(findsig(s -> par_signature
00818                                              -> val_denotation, FALSE)
00819                                           != SUCCESS) {
00820                                     simple_type = FALSE;
00821                                 } else {
00822                                   NODE * den_sig;
00823                                   den_sig = s -> par_signature
00824                                               -> val_denotation
00825                                               -> signature;
00826                                   if (den_sig != ERR_SIG
00827                                       && den_sig -> kind == TYPESIGNATURE) {
00828                                       simple_type = simple_type &&
00829                                                     den_sig -> ts_simple_type;
00830                                   }
00831                                 }
00832                             /* checksigs will complain about VARSIGNATUREs */
00833                           }
00834                         });
00835                     p -> signature -> ts_simple_type = simple_type;
00836                     unlock(comp_list);
00837                     unlock(arg_list);
00838                     vfree(arg_list);
00839                     return(SUCCESS);
00840                 }
00841 
00842             case UNIONCONSTRUCTION:
00843                 {
00844                     NODE * field_list = p -> prod_components;
00845                     NODE * comp_list = lock(emptylist());
00846                     NODE * local_id = p -> prod_local_type_id == NIL?
00847                                         mknode(LETTERID, UNDEFNAME)
00848                                       : copynode(p -> prod_local_type_id);
00849                     NODE * self = mknode(VALSIGNATURE, local_id);
00850                     int len = length(field_list);
00851                     int i;
00852                     boolean simple_type;
00853 
00854                     /* Put New, ValueOf and := in component list */
00855                         r = mknode(TSCOMPONENT,
00856                                    mkcompnm(indx_New),
00857                                    copynode(sig_New));
00858                         r -> tsc_signature -> fsig_special = 
00859                             special(UNION_NEW, len);
00860                         init_inline(r);
00861                         addright(comp_list, r);
00862                         r = mknode(TSCOMPONENT,
00863                                    mkcompnm(indx_ValueOf),
00864                                    copynode(sig_ValueOf));
00865                         r -> tsc_signature -> fsig_special = 
00866                             special(UNION_VALUEOF, len);
00867                         init_inline(r);
00868                         addright(comp_list, r);
00869                         r = mknode(TSCOMPONENT,
00870                                    mkcompnm(indx_assign),
00871                                    copynode(sig_assign));
00872                         r -> tsc_signature -> fsig_special = 
00873                             special(UNION_ASSIGN, len);
00874                         init_inline(r);
00875                         addright(comp_list, r);
00876 
00877                     {/* add projection, injection and inquiry functions */ 
00878                       NODE * par = emptylist(); /* parameter list for */
00879                                                  /* func signature     */
00880                       NODE * t;
00881 
00882                       /* fix up par */
00883                         addright(par, t = mknode(PARAMETER, NIL, self));
00884                         t -> pre_num = next_pre++;
00885 
00886                       i = 0;
00887                       begin_maplist(s, field_list) {
00888                         boolean vac = Gflag && vacuous_arg(s -> par_signature);
00889                                       /* This field is not really represented */
00890 
00891                         IFDEBUG(
00892                             if (s -> kind != PARAMETER) {
00893                                 dbgmsg("findsig: bad union component\n");
00894                             }
00895                         )
00896                         if (s -> par_id -> kind != LETTERID) {
00897                           errmsg1(s, "Bad union field name: %s",
00898                                   getname(s -> par_id -> id_str_table_index));
00899                         }
00900                         /* Projection */
00901                           r = mknode(FUNCSIGNATURE,
00902                                      NIL /* SHOULD BE INLINE CODE */,
00903                                      par,
00904                                      s -> par_signature
00905                                     );
00906                           if (!vac) {
00907                               r -> fsig_special = special(UNION_PROJ, i);
00908                           } else {
00909                               r -> fsig_special = special(UNDEF_CONST, 0);
00910                           }
00911                           r -> fsig_inline_code =
00912                             (*spcl_to_inline)(r -> fsig_special);
00913                           addright(comp_list,
00914                                    mknode(TSCOMPONENT,
00915                                           prefix ("to_", s -> par_id),
00916                                           r)
00917                                   );
00918                         /* Inquiry */
00919                           r = mknode(FUNCSIGNATURE,
00920                                      NIL /* SHOULD BE INLINE CODE */,
00921                                      par,
00922                                      val_Boolean
00923                                     );
00924                           r -> fsig_special = special(UNION_INQ, i);
00925                           r -> fsig_inline_code =
00926                             (*spcl_to_inline)(r -> fsig_special);
00927                           addright(comp_list,
00928                                    mknode(TSCOMPONENT,
00929                                           prefix ("is_", s -> par_id),
00930                                           r)
00931                                   );
00932                         /* Injection */
00933                           r = mknode(FUNCSIGNATURE,
00934                                      NIL,
00935                                      mklist( mknode(PARAMETER,
00936                                                     NIL,
00937                                                     s -> par_signature),
00938                                              -1
00939                                            ),
00940                                      self
00941                                     );
00942                           if (!vac) {
00943                               r -> fsig_special = special(UNION_INJ, i);
00944                           } else {
00945                               r -> fsig_special = special(UNION_INJ0, i);
00946                           }
00947                           r -> fsig_inline_code =
00948                             (*spcl_to_inline)(r -> fsig_special);
00949                           addright(comp_list,
00950                                    mknode(TSCOMPONENT,
00951                                           prefix ("from_", s -> par_id),
00952                                           r)
00953                                   );
00954                         i++;
00955                       } end_maplist;
00956                     }
00957                     initsig(p, mknode(TYPESIGNATURE, NIL,
00958                                       comp_list,
00959                                       NIL, NIL, NIL));
00960                     p -> signature -> pre_num = next_pre++;
00961                                 /* so copies can be recognized */
00962                     tsig_order(p -> signature);
00963                     /* Make references to union local type id point to   */
00964                     /* signature instead                                 */
00965                       /* Make sure tsubst doesn't get confused */
00966                         local_id -> id_def_found = TRUE;
00967                         local_id -> id_last_definition = p -> signature;
00968                       chgfld(&(p -> signature), tsubst(p -> signature,
00969                                                        p,
00970                                                        local_id,
00971                                                        FALSE));
00972                     /* Fix up local_id */
00973                       local_id -> id_last_definition = p -> signature;
00974                     p -> sig_done = SIG_DONE;
00975                     /* Compute whether resulting type is "simple" */
00976                         maplist(s, field_list, {
00977                           switch(s -> par_signature -> kind) {
00978                             case FUNCSIGNATURE:
00979                             case TYPESIGNATURE:
00980                                 simple_type = FALSE;
00981                                 break;
00982                             case VALSIGNATURE:
00983                                 if(findsig(s -> par_signature
00984                                              -> val_denotation, FALSE)
00985                                           != SUCCESS) {
00986                                     simple_type = FALSE;
00987                                 } else {
00988                                   NODE * den_sig;
00989                                   den_sig = s -> par_signature
00990                                               -> val_denotation
00991                                               -> signature;
00992                                   if (den_sig != ERR_SIG
00993                                       && den_sig -> kind == TYPESIGNATURE) {
00994                                       simple_type = simple_type &&
00995                                                     den_sig -> ts_simple_type;
00996                                   }
00997                                 }
00998                             /* checksigs will complain about VARSIGNATUREs */
00999                           }
01000                         });
01001                     p -> signature -> ts_simple_type = simple_type;
01002                     vfree(comp_list);
01003                     return(SUCCESS);
01004                 }
01005 
01006             case ENUMERATION:
01007                 {
01008                     NODE * id_list = p -> enum_id_list;
01009                     NODE * comp_list = lock(emptylist());
01010                     NODE * local_id = mknode(LETTERID, -1);
01011                     NODE * self = mknode(VALSIGNATURE, local_id);
01012                     NODE * self_param = mknode(PARAMETER, NIL, self);
01013                     NODE * self_plist = mklist(self_param, -1);
01014                     NODE * Int_param = mknode(PARAMETER, NIL, val_Integer);
01015                     NODE * Int_plist = mklist(Int_param, -1);
01016                     int len = length(id_list);
01017                     int i;
01018 
01019                     /* Put New, ValueOf and := in component list */
01020                         r = mknode(TSCOMPONENT,
01021                                    mkcompnm(indx_New),
01022                                    copynode(sig_New));
01023                         r -> tsc_signature -> fsig_special = 
01024                             special(ENUM_NEW, len);
01025                         init_inline(r);
01026                         addright(comp_list, r);
01027                         r = mknode(TSCOMPONENT,
01028                                    mkcompnm(indx_ValueOf),
01029                                    copynode(sig_ValueOf));
01030                         r -> tsc_signature -> fsig_special = 
01031                             special(ENUM_VALUEOF, len);
01032                         init_inline(r);
01033                         addright(comp_list, r);
01034                         r = mknode(TSCOMPONENT,
01035                                    mkcompnm(indx_assign),
01036                                    copynode(sig_assign));
01037                         r -> tsc_signature -> fsig_special = 
01038                             special(ENUM_ASSIGN, len);
01039                         init_inline(r);
01040                         addright(comp_list, r);
01041                         r = mknode(TSCOMPONENT,
01042                                    mkcompnm(indx_equals),
01043                                    copynode(sig_equals));
01044                         r -> tsc_signature -> fsig_special = 
01045                             special(ENUM_EQ, len);
01046                         init_inline(r);
01047                         addright(comp_list, r);
01048                         r = mknode(TSCOMPONENT,
01049                                    mkcompnm(indx_ne),
01050                                    copynode(sig_equals));
01051                         r -> tsc_signature -> fsig_special = 
01052                             special(ENUM_NE, len);
01053                         init_inline(r);
01054                         addright(comp_list, r);
01055                         r = mknode(TSCOMPONENT,
01056                                    mkcompnm(indx_First),
01057                                    copynode(sig_const));
01058                         r -> tsc_signature -> fsig_special = 
01059                             special(ENUM_ELEMENT, 0);
01060                         init_inline(r);
01061                         addright(comp_list, r);
01062                         r = mknode(TSCOMPONENT,
01063                                    mkcompnm(indx_Last),
01064                                    copynode(sig_const));
01065                         r -> tsc_signature -> fsig_special = 
01066                             special(ENUM_ELEMENT, len-1);
01067                         init_inline(r);
01068                         addright(comp_list, r);
01069                         r = mknode(TSCOMPONENT,
01070                                    mkcompnm(indx_Pred),
01071                                    mknode(FUNCSIGNATURE,
01072                                           NIL, self_plist, self));
01073                         r -> tsc_signature -> fsig_special = 
01074                             special(ENUM_PRED, len);
01075                         init_inline(r);
01076                         addright(comp_list, r);
01077                         r = mknode(TSCOMPONENT,
01078                                    mkcompnm(indx_Succ),
01079                                    mknode(FUNCSIGNATURE,
01080                                           NIL, self_plist, self));
01081                         r -> tsc_signature -> fsig_special = 
01082                             special(ENUM_SUCC, len);
01083                         init_inline(r);
01084                         addright(comp_list, r);
01085                         r = mknode(TSCOMPONENT,
01086                                    mkcompnm(indx_Ord),
01087                                    mknode(FUNCSIGNATURE,
01088                                           NIL, self_plist, val_Integer));
01089                         r -> tsc_signature -> fsig_special = 
01090                             special(IDENTITY, len);
01091                         init_inline(r);
01092                         addright(comp_list, r);
01093                         r = mknode(TSCOMPONENT,
01094                                    mkcompnm(indx_OrdInv),
01095                                    mknode(FUNCSIGNATURE,
01096                                           NIL, Int_plist, self));
01097                         r -> tsc_signature -> fsig_special = 
01098                             special(IDENTITY, len);
01099                         init_inline(r);
01100                         addright(comp_list, r);
01101                         r = mknode(TSCOMPONENT,
01102                                    mkcompnm(indx_Card),
01103                                    mknode(FUNCSIGNATURE,
01104                                           NIL, emptylist(), val_Integer));
01105                         r -> tsc_signature -> fsig_special = 
01106                             special(ENUM_CARD, len);
01107                         init_inline(r);
01108                         addright(comp_list, r);
01109 
01110                     {/* add constant functions */ 
01111 
01112                       i = 0;
01113                       maplist(s, id_list, {
01114                           IFDEBUG(
01115                             if (s -> kind != LETTERID && s -> kind != OPRID) {
01116                                 dbgmsg("findsig: bad enumeration element\n");
01117                             }
01118                           )
01119                           r = copynode(sig_const);
01120                           r -> fsig_special = special(ENUM_ELEMENT, i);
01121                           r -> fsig_inline_code =
01122                             (*spcl_to_inline)(r -> fsig_special);
01123                           addright(comp_list,
01124                                    mknode(TSCOMPONENT, s, r)
01125                                   );
01126                         i++;
01127                       });
01128                     }
01129                     initsig(p, mknode(TYPESIGNATURE, NIL,
01130                                       comp_list,
01131                                       NIL, NIL, NIL));
01132                     unlock(comp_list);
01133                     p -> signature -> pre_num = next_pre++;
01134                     p -> sig_done = SIG_DONE;
01135                                 /* so copies can be recognized */
01136                     tsig_order(p -> signature);
01137                     p -> signature -> ts_simple_type = TRUE;
01138                     return(SUCCESS);
01139                 }
01140 
01141             case EXTENSION:
01142                 {
01143                     NODE * In_sig;
01144                     NODE * Out_sig;
01145                     NODE * sig; 
01146                     NODE * par_list;
01147                     NODE * orig_sig;
01148                     NODE * new_sig;
01149                     NODE * local_id;
01150                     NODE * id_In, * id_Out;
01151 
01152                     if ((q = findsig(p -> ext_denotation, FALSE)) != SUCCESS) {
01153                         p -> sig_done = SIG_UNKNOWN;
01154                         return(q);
01155                     }
01156                     if (p -> ext_denotation -> signature == ERR_SIG) {
01157                         p -> signature = ERR_SIG;
01158                         p -> sig_done = SIG_DONE;
01159                         return(SUCCESS);
01160                     }
01161                     /* sig := copy of argument signature */
01162                       sig = lock(copynode(p -> ext_denotation -> signature));
01163                       if (sig -> kind != TYPESIGNATURE) {
01164                           errmsg0(p -> ext_denotation,
01165                                   "Extension argument not a type");
01166                           p -> signature = ERR_SIG;
01167                           p -> sig_done = SIG_DONE;
01168                           return(SUCCESS);
01169                       }
01170                       if (sig -> ts_local_type_id != NIL) {
01171                         local_id = lock(copynode(sig -> ts_local_type_id));
01172                       } else {
01173                         local_id = mknode(LETTERID, UNDEFNAME);
01174                       }
01175                       sig -> pre_num = next_pre++;
01176                             /* Make sure we recognize it as different from */
01177                             /* the old one.                                */
01178                       chgfld(&(sig -> ts_clist), copylist(sig -> ts_clist));
01179                       /* Fix up references to local type id of sig */
01180                       {
01181                         NODE * Osig = sig;
01182 
01183                         local_id -> id_last_definition = sig;
01184                         local_id -> id_def_found = TRUE;
01185                         sig = lock(tsubst(sig,
01186                                           p -> ext_denotation -> signature,
01187                                           local_id,
01188                                           TRUE));
01189                         local_id -> id_last_definition = sig;
01190                         vfree(unlock(Osig));
01191                       }
01192                     /* Build id nodes for In and Out */
01193                       id_In = mknode(LETTERID, indx_In);
01194                       id_Out = mknode(LETTERID, indx_Out);
01195                     /* Build signatures of In and Out */
01196                       /* check that it's safe to put arg into signature */
01197                         if (on_dontsubst(p -> ext_denotation) != NIL) {
01198                             p -> sig_done = SIG_UNKNOWN;
01199                             return(on_dontsubst(p -> ext_denotation));
01200                         }
01201                       orig_sig = mknode(VALSIGNATURE, p -> ext_denotation);
01202                       new_sig = mknode(VALSIGNATURE, mknode(LETTERID, -1));
01203                       par_list = mklist(mknode(PARAMETER, NIL, orig_sig), -1);
01204                       In_sig = mknode(FUNCSIGNATURE,
01205                                       NIL,
01206                                       par_list,
01207                                       new_sig);
01208                       par_list = mklist(mknode(PARAMETER, NIL, new_sig), -1);
01209                       Out_sig = mknode(FUNCSIGNATURE,
01210                                        NIL,
01211                                        par_list,
01212                                        orig_sig);
01213                       In_sig -> fsig_special = special(IDENTITY, 0);
01214                       In_sig -> fsig_inline_code =
01215                             (*spcl_to_inline)(In_sig -> fsig_special);
01216                       Out_sig -> fsig_special = special(IDENTITY, 0);
01217                       Out_sig -> fsig_inline_code =
01218                             (*spcl_to_inline)(Out_sig -> fsig_special);
01219                     /* Check that In and Out are not already present */
01220                     /* It's not clear that they can be, but rather   */
01221                     /* than trying to prove that, ...                */
01222                       if (getcomp(sig, id_In, NIL, In_sig, sig, NIL, TRUE)
01223                           != NIL) {
01224                         errmsg0(p, "In occurs in extend argument sig");
01225                       }
01226                       if (getcomp(sig, id_Out, NIL, Out_sig, sig, NIL, TRUE)
01227                           != NIL) {
01228                         errmsg0(p, "Out occurs in extend argument sig");
01229                       }
01230                     /* Add In and Out, initialize indicees */
01231                       inscomp(sig, id_In, In_sig, NIL);
01232                       p -> In_index = comp_index;
01233                       inscomp(sig, id_Out, Out_sig, NIL);
01234                       p -> Out_index = comp_index;
01235                     initsig(p, sig);
01236                     p -> sig_done = SIG_DONE;
01237                     /* No identifier references to sig, thus pre_num is */
01238                     /* irrelevant.  OK to use old optimization info     */
01239                     return(SUCCESS);
01240                 }
01241 
01242             case RECORDCONSTRUCTION:
01243                 {
01244                     NODE * field_list = p -> enum_id_list;
01245                     NODE * comp_list = lock(emptylist());
01246                     NODE * local_id = mknode(LETTERID, -1);
01247                     NODE * self = mknode(VALSIGNATURE, local_id);
01248                     NODE * self_param = mknode(PARAMETER, NIL, self);
01249                     NODE * self_plist = mklist(self_param, -1);
01250                     NODE * Mk_param_list = emptylist();
01251                     NODE * id_New = mkcompnm(indx_New);
01252                     NODE * id_ValueOf = mkcompnm(indx_ValueOf);
01253                     NODE * id_assign = mkcompnm(indx_assign);
01254                     NODE * re_den_sig;
01255                     int len = length(field_list);
01256                     int i;
01257 
01258                     /* Find signatures of type expressions,  make sure */
01259                     /* they can be incorporated into signatures, and   */
01260                     /* that they have the right components             */
01261                       begin_maplist(s, p -> rec_component_list) {
01262                         if ((q = findsig(s -> re_denotation, FALSE))
01263                             != SUCCESS) {
01264                           p -> sig_done = SIG_UNKNOWN;
01265                           return(q);
01266                         }
01267                         re_den_sig = s -> re_denotation -> signature;
01268                         if (re_den_sig == ERR_SIG) {
01269                           err_return;
01270                         }
01271                         if (re_den_sig -> kind != TYPESIGNATURE) {
01272                             errmsg0(s,
01273                               "Non-type expression in record construction");
01274                             err_return;
01275                         }
01276                         if (on_dontsubst(s -> re_denotation) != NIL) {
01277                             p -> sig_done = SIG_UNKNOWN;
01278                             return(on_dontsubst(s -> re_denotation));
01279                         }
01280                         if (getcomp(re_den_sig,
01281                                     id_ValueOf, NIL, sig_ValueOf, re_den_sig,
01282                                     NIL, TRUE) == NIL) {
01283                           errmsg0(s, "No V operation in record component");
01284                         }
01285                         s -> re_ValueOf_index = comp_index;
01286                         if (getcomp(re_den_sig,
01287                                     id_New, NIL, sig_New, re_den_sig,
01288                                     NIL, TRUE) == NIL) {
01289                           errmsg0(s, "No New operation in record component");
01290                         }
01291                         s -> re_New_index = comp_index;
01292                         if (getcomp(re_den_sig,
01293                                     id_assign, NIL, sig_assign, re_den_sig,
01294                                     NIL, TRUE) == NIL) {
01295                           errmsg0(s, "No := operation in record component");
01296                         }
01297                         s -> re_assign_index = comp_index;
01298                       } end_maplist;
01299                     /* Put New, ValueOf and := in component list */
01300                         r = mknode(TSCOMPONENT,
01301                                    id_New,
01302                                    copynode(sig_New));
01303                         r -> tsc_signature -> fsig_special = 
01304                             special(RECORD_NEW, len);
01305                         init_inline(r);
01306                         addright(comp_list, r);
01307                         r = mknode(TSCOMPONENT,
01308                                    id_ValueOf,
01309                                    copynode(sig_ValueOf));
01310                         r -> tsc_signature -> fsig_special = 
01311                             special(RECORD_VALUEOF, len);
01312                         init_inline(r);
01313                         addright(comp_list, r);
01314                         r = mknode(TSCOMPONENT,
01315                                    id_assign,
01316                                    copynode(sig_assign));
01317                         r -> tsc_signature -> fsig_special = 
01318                             special(RECORD_ASSIGN, len);
01319                         init_inline(r);
01320                         addright(comp_list, r);
01321                     /* Put Mk in comp_list */
01322                       maplist(s, p -> rec_component_list, {
01323                         r = mknode(VALSIGNATURE, s -> re_denotation);
01324                         r = mknode(PARAMETER, NIL, r);
01325                         addright(Mk_param_list, r);
01326                       });
01327                       r = mknode(FUNCSIGNATURE, NIL,
01328                                  Mk_param_list, self);
01329                       r -> fsig_special = special(RECORD_MK, len);
01330                       r = mknode(TSCOMPONENT,
01331                                  mkcompnm(indx_Mk),
01332                                  r);
01333                       init_inline(r);
01334                       addright(comp_list, r);
01335                     /* Add fields          */
01336                       i = 0;   /* component number */
01337                       begin_maplist(s, p -> rec_component_list) {
01338                         NODE * vl_field_sig;
01339                         NODE * vr_field_sig;
01340 
01341                         vl_field_sig =
01342                              mknode(FUNCSIGNATURE,
01343                                     NIL,  /* in-line code */
01344                                     self_plist,
01345                                     mknode(VALSIGNATURE,
01346                                            s -> re_denotation)); 
01347                         r = mklist(mknode(PARAMETER,
01348                                           NIL,
01349                                           mknode(VARSIGNATURE,local_id)),
01350                                    -1);
01351                         vr_field_sig =
01352                              mknode(FUNCSIGNATURE,
01353                                     NIL,
01354                                     r,
01355                                     mknode(VARSIGNATURE,
01356                                            s -> re_denotation));
01357                         vl_field_sig -> fsig_special =
01358                             special(RECORD_VAL_FIELD, i);
01359                         vr_field_sig -> fsig_special =
01360                             special(RECORD_VAR_FIELD, i);
01361                         r = mknode(TSCOMPONENT,
01362                                    s -> re_id,
01363                                    vl_field_sig);
01364                         init_inline(r);
01365                         addright(comp_list, r);
01366                         r = mknode(TSCOMPONENT,
01367                                    s -> re_id,
01368                                    vr_field_sig);
01369                         init_inline(r);
01370                         addright(comp_list, r);
01371                         i++;
01372                       } end_maplist;
01373                     initsig(p, mknode(TYPESIGNATURE, NIL,
01374                                       comp_list,
01375                                       NIL, NIL, NIL));
01376                     unlock(comp_list);
01377                     p -> signature -> pre_num = next_pre++;
01378                     p -> sig_done = SIG_DONE;
01379                                 /* so copies can be recognized */
01380                     tsig_order(p -> signature);
01381                     /* fill in ts_simple type */
01382                       p -> signature -> ts_simple_type = TRUE;
01383                       maplist(s, p -> rec_component_list, {
01384                         if (s -> re_denotation -> signature
01385                               -> ts_simple_type == FALSE) {
01386                             p -> signature -> ts_simple_type = FALSE;
01387                         }
01388                       });
01389                     return(SUCCESS);
01390                 }
01391 
01392             case REXTERNDEF:
01393                 dbgmsg("findsig: REXTERNDEF without signature\n");
01394                 abort();
01395 
01396             default:
01397                 dbgmsg("findsig: unknown expression kind\n");
01398                 abort();
01399         }
01400 #   ifdef DEBUG
01401         findsig_out:
01402 #           ifdef TRACE2
01403                 printf("findsig: %X ", p);
01404                 unparse_file = stdout;
01405                 unparse(p);
01406                 printf(" returning: %X\n", return_val);
01407                 fflush(stdout);
01408                 if (return_val != SUCCESS) {
01409                     unparse(return_val);
01410                     printf("\n");
01411                 }
01412 #           endif
01413             if (!is_ptr(return_val)) {
01414                 dbgmsg("findsig returning bogus value: 0x%X\n", return_val);
01415                 unparse_file = stdout;
01416                 unparse(p);
01417                 printf("\n");
01418                 abort();
01419             }
01420 #           undef return
01421             return(return_val);
01422 #   endif
01423 }
01424 
01425 
01426 /*
01427  * NODE * declsig(p)
01428  *  Returns the signature of the identifier declared by the declaration p
01429  * Sets declerr to either SUCCESS or a pointer to the offending node.
01430  */
01431 NODE *
01432 declsig(p)
01433 NODE * p;
01434 {
01435     boolean old_may_fail;
01436     NODE * q;
01437     switch (p -> kind) {
01438         case DECLARATION:
01439             if (p -> decl_sig_done == SIG_DONE) {
01440                 declerr = SUCCESS;
01441                 return(p -> decl_signature);
01442             }
01443             old_may_fail = may_fail;
01444             may_fail = (may_fail || p -> decl_signature != NIL);
01445             /* Signature of right side should be found if at all possible */
01446             /* It's useful for optimization info, if nothing else.        */
01447             declerr = findsig(p -> decl_denotation,FALSE);
01448 #           ifdef TRACE
01449               printf("declsig: p = %X, declerr = %X\n", p, declerr);
01450 #           endif
01451             if (declerr != SUCCESS) {
01452               if (p -> decl_signature != NIL) {
01453                 declerr = SUCCESS;
01454                 may_fail = old_may_fail;
01455                 return(p -> decl_signature);
01456               }
01457               /* try to get declerr to point to an identifier */
01458                 if(declerr -> kind != LETTERID && declerr -> kind != OPRID) {
01459                     declerr = p -> decl_id;
01460 #                   ifdef TRACE
01461                       printf("Changing decl_err to %X\n", declerr);
01462 #                   endif
01463                 }
01464             } else {
01465                 p -> decl_sig_done = SIG_DONE;
01466                 if (p -> decl_denotation -> signature == ERR_SIG) {
01467                   p -> decl_signature = ERR_SIG;
01468                 } else {
01469                   chgfld(&(p -> decl_signature),
01470                          p -> decl_denotation -> signature);
01471                 }
01472             }
01473             may_fail = old_may_fail;
01474             return(p -> decl_signature);
01475         case PARAMETER:
01476             declerr = SUCCESS;
01477             return(p -> par_signature);
01478         case TYPESIGNATURE:
01479             declerr = SUCCESS;
01480             return(p);
01481         case PRODCONSTRUCTION:
01482         case RECORDCONSTRUCTION:
01483         case UNIONCONSTRUCTION:
01484         case MODPRIMARY:
01485             declerr = findsig(p,FALSE);
01486             return(p -> signature);
01487 #       ifdef DEBUG
01488             default:
01489                 dbgmsg("declsig: Bad declaration pointer: %x, kind=%s\n",
01490                        p, kindname(p->kind));
01491                 abort();
01492 #       endif
01493     }
01494 }
01495 
01496 
01497 /* top level version of findsig. Reports errors */
01498 void
01499 tl_findsig(p,dont_coerce)
01500 NODE *p;
01501 boolean dont_coerce;
01502 {
01503     NODE * q;
01504 
01505     /* Redo any node which may still require coercion */
01506       switch (p -> kind) {
01507         case GUARDEDLIST:
01508         case LOOPDENOTATION:
01509             chgsig(p, NIL);
01510             /* and clear sig_done: */
01511         case FUNCCONSTR:
01512             p -> sig_done = SIG_UNKNOWN;
01513       }
01514     q = findsig(p,dont_coerce);
01515     if (q != SUCCESS) {
01516         if (q -> kind == LETTERID || q -> kind == OPRID) {
01517             errmsg1(q,"circular signature dependency involving %s",
01518                     getname(q -> id_str_table_index));
01519         } else {
01520             errmsg0(q,"Circular signature dependency");
01521         }
01522         if (p -> kind == FUNCCONSTR) {
01523             p -> signature -> fsig_result_sig = ERR_SIG;
01524         } else {
01525             p -> signature = ERR_SIG;
01526         }
01527         p -> sig_done = SIG_DONE;
01528     }
01529     /* clear dontsubst list */
01530         while (dontsubst != NIL) {
01531             dontsubst = cn_del_hd(dontsubst);
01532         }
01533 }

Generated on Fri Jan 25 10:39:46 2008 for russell by  doxygen 1.5.4