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

Go to the documentation of this file.
00001 # define DEBUG
00002 
00003 # ifdef DEBUG
00004 #   define IFDEBUG(x) x
00005 # else
00006 #   define IFDEBUG(x)
00007 # endif
00008 
00009 # define TRACE
00010 # undef TRACE
00011 
00012 # include <stdio.h>
00013 # include "parm.h"
00014 
00015 # include "stree/ststructs.mh"
00016 
00017 # include "sigs.h"
00018 
00019 extern int comp_index;
00020 
00021 extern NODE * declerr;
00022 
00023 extern boolean may_fail;
00024 
00025 extern FILE * unparse_file;
00026 
00027 NODE * finddecl1();
00028 
00029 NODE * prev_def();
00030 
00031 boolean def_match();
00032 
00033 NODE * unshare();
00034 
00035 NODE * subst();
00036 
00037 /*
00038  * finddecl(id)
00039  *
00040  *  Find the appropriate declaration for id.  If id_appl is non-NIL
00041  * use the fact that it is being used as an operator with the given
00042  * argument list.  If signature is non-NIL use the fact that an explicit
00043  * signature was given.
00044  * "Finding the declaration" involves setting the
00045  * sel_type and last_definition fields to their final value (if possible)
00046  * On success the def_found field is set.  (Nothing whatsoever is
00047  * done if this field was originally set.)
00048  *  It is assumed that the signatures of all surrounding use list types
00049  * are known.
00050  *  Returns SUCCESS or a node pointer to indicate cyclic dependencies
00051  * in the same way as findsig does.
00052  *  It is assumed that the signatures of the arguments (if any) are known.
00053  */
00054 
00055 /* check for multiple declarations later.                  */
00056 
00057 NODE *
00058 finddecl(id)
00059 NODE * id;
00060 {
00061     NODE * q;
00062 
00063     if (id -> id_appl == NIL) {
00064         return(finddecl1(id, id -> id_appl, TRUE));
00065     } else {
00066         /* Try for an exact match first */
00067             q = finddecl1(id, id -> id_appl, TRUE);
00068         if (q != SUCCESS || id -> id_def_found)
00069             return(q);
00070         /* Now try for a match requiring coercions */
00071             return(finddecl1(id, id -> id_appl, FALSE));
00072     }
00073 }
00074 
00075 /* 
00076  *  Identical to the above except:
00077  * Any arguments to which id may have been applied are passed explicitly.
00078  * If exact is TRUE only definitions giving exact argument parameter
00079  * matches are allowed.  Otherwise the effect of possible coercions is
00080  * anticipated.
00081  */
00082 
00083 NODE *
00084 finddecl1(id, appl, exact)
00085 NODE * id, * appl;
00086 boolean exact;
00087 {
00088     NODE * usl;     /* use list currently being searched for identifier */
00089     NODE * q;
00090     NODE * curr_defn;   /* definition currently being examined  */
00091     NODE * prev_defn;   /* For partial uniqueness check         */
00092     NODE * args;
00093 
00094     if (id -> id_def_found) return(SUCCESS);
00095     if (id -> sel_type == NIL) {
00096         curr_defn = id -> id_last_definition;
00097         while( curr_defn != NIL ) {
00098             q = declsig(curr_defn);
00099             if (declerr != SUCCESS) {
00100                 if (may_fail || prev_def(curr_defn) != NIL) {
00101                   return(declerr);
00102                 } else {
00103                   /* may as well assume it's this one */
00104                   id -> id_last_definition = curr_defn;
00105                   id -> id_def_found = TRUE;
00106                   return(SUCCESS);
00107                 }
00108             }
00109             if(def_match(q, id -> signature, appl, id, exact)) {
00110                 id -> id_last_definition = curr_defn;
00111                 id -> id_def_found = TRUE;
00112 #               ifdef TRACE
00113                     unparse_file = stdout;
00114                     printf("Found definition for ");
00115                     unparse(id);
00116                     printf("\n");
00117 #               endif
00118                 /* Make a partial check for uniqueness of declaration */
00119                   if (curr_defn -> kind == DECLARATION
00120                       && (prev_defn = prev_def(curr_defn)) != NIL
00121                       && prev_defn -> kind == DECLARATION
00122                       && curr_defn -> decl_scope == prev_defn -> decl_scope) {
00123                       q = declsig(prev_defn);
00124                       if (declerr == SUCCESS && q != ERR_SIG &&
00125                           def_match(q, id -> signature, appl, id, exact)) {
00126                         extern int yynerrs;
00127                         errmsg1(id, "Ambiguous reference to %s", 
00128                                 getname(id -> id_str_table_index));
00129                       }
00130                   }
00131                 return(SUCCESS);
00132             } else {
00133 #               ifdef TRACE
00134                     unparse_file = stdout;
00135                     printf("Def_match failed for ");
00136                     unparse(id);
00137                     printf("\nDeclaration sig:");
00138                     unparse(q);
00139                     printf("\n");
00140 #               endif
00141                 curr_defn = prev_def(curr_defn);
00142             }
00143         }
00144         if (appl != NIL) {
00145           /* Try to infer a selection from an argument type */
00146             args = appl -> ap_args;
00147 #           ifdef DEBUG
00148                 if (appl -> kind != APPLICATION) {
00149                     dbgmsg("finndecl1: bad application\n");
00150                     abort();
00151                 }
00152 #           endif
00153             begin_maplist(p, args) {
00154                 NODE * arg_sig = p -> signature; /* signature used in infering */
00155                                                  /* arg "type"                 */
00156                 NODE * arg_type;
00157 
00158                 if (arg_sig == ERR_SIG) continue;
00159                 IFDEBUG(
00160                     if (arg_sig == NIL) {
00161                         dbgmsg("finddecl: unknown arg signature\n");
00162                         abort();
00163                     }
00164                 )
00165                 if (arg_sig -> kind == FUNCSIGNATURE) {
00166                     arg_sig = arg_sig -> fsig_result_sig;
00167                     if (arg_sig == ERR_SIG) continue;
00168                 }
00169                 if (arg_sig -> kind == VALSIGNATURE) {
00170                     arg_type = arg_sig -> val_denotation;
00171                 } else if (arg_sig -> kind == VARSIGNATURE) {
00172                     arg_type = arg_sig -> var_denotation;
00173                 } else {
00174                     continue;
00175                 }
00176                 /* ignore forgetting coercions */
00177                   if(arg_type -> kind == MODPRIMARY
00178                      && arg_type -> mp_type_modifier == NIL) {
00179                       arg_type = arg_type -> mp_primary;
00180                   }
00181                 if((q = findsig(arg_type, FALSE)) != SUCCESS) {
00182                   if (!may_fail ||     /* <-- */
00183                       (length(args) == 1 ||
00184                        comp_st(first(args) -> signature, last(args) -> signature,
00185                               NIL, NIL) == 0)) {
00186                     /* May as well guess this type (This is silly, but ...) */
00187                     initfld(&(id -> sel_type), unshare(arg_type));
00188                     id -> id_def_found = TRUE;
00189                     return(SUCCESS);
00190                   } else {
00191                     return(q);
00192                   }
00193                 }
00194                 IFDEBUG(
00195                     if(arg_type -> signature == NIL) {
00196                         dbgmsg("finddecl: no type signature\n");
00197                         prtree(arg_type);
00198                         printf("sig_done = %d\n", arg_type -> sig_done);
00199                     }
00200                 )
00201                 if (arg_type -> signature == ERR_SIG) {
00202                     continue;
00203                 }
00204                 if (arg_type -> signature -> kind == TYPESIGNATURE) {
00205                     q = getcomp(arg_type -> signature,
00206                                 id, 
00207                                 arg_type,
00208                                 id -> signature, NIL,
00209                                 appl, exact);
00210                 } else {
00211                     /* leave error for checksigs to find */
00212                         q = NIL;
00213                 }
00214                 if (q != NIL) {
00215                     initsig(id, q);
00216                     initfld(&(id -> sel_type), unshare(arg_type));
00217                     id -> id_def_found = TRUE;
00218                     id -> sel_index = comp_index;
00219                     id -> sig_done = SIG_DONE;
00220                     return(SUCCESS);
00221                 }
00222             } end_maplist;
00223         }
00224         /* Try to infer a selection from a use list type */
00225             usl = id -> id_use_list;
00226             while(usl != NIL) {
00227 #               ifdef DEBUG
00228                     if (usl -> kind != USELIST) {
00229                         dbgmsg("finddecl: bad use list\n");
00230                     }
00231 #               endif
00232                 maplist(p, usl -> usl_type_list, {
00233                     IFDEBUG(
00234                         if (p -> signature == NIL) {
00235                             dbgmsg("finddecl: use list type without sig\n");
00236                             prtree(p);
00237                         }
00238                     )
00239                     if (p -> signature == ERR_SIG 
00240                         || p -> signature -> kind == TYPESIGNATURE)
00241                         q = getcomp(p -> signature,
00242                                     id,
00243                                     p,
00244                                     id -> signature, NIL,
00245                                     appl, exact);
00246                     else
00247                         /* leave error for checksigs to find */
00248                         q = NIL;
00249                     if (q != NIL) {
00250                         initsig(id, q);
00251                         initfld(&(id -> sel_type), unshare(p));
00252                         id -> id_def_found = TRUE;
00253                         id -> sel_index = comp_index;
00254                         id -> sig_done = SIG_DONE;
00255                         return(SUCCESS);
00256                     }
00257                 });
00258                 usl = usl -> usl_previous_list;
00259             }
00260         /* Didn't find it.  Return SUCCESS anyway to indicate no problem */
00261         /* with signatures.                                              */
00262             return(SUCCESS);
00263     } else {
00264         id -> id_def_found = TRUE;
00265         return(SUCCESS);
00266     }
00267 }
00268 
00269 /*
00270  *  findstdecl(string_pointer)
00271  *
00272  * analogous to the above except deals with strings rather than identifiers.
00273  * Checks that explicitly specified type (if any) is appropriate.
00274  * Leaves (or sets) selection type to NIL if nothing appropriate is found.
00275  */
00276 NODE *
00277 findstdecl(string)
00278 NODE * string;
00279 {
00280     NODE * usl;
00281     boolean found_it = 0;
00282     NODE * q;
00283 
00284     if (string -> sel_type == NIL) {
00285         /* Try to infer a selection from a use list type */
00286             usl = string -> str_use_list;
00287             while(usl != NIL && !found_it) {
00288 #               ifdef DEBUG
00289                     if (usl -> kind != USELIST) {
00290                         dbgmsg("finddecl: bad use list\n");
00291                     }
00292 #               endif
00293                 maplist(p, usl -> usl_type_list, {
00294                     IFDEBUG(
00295                         if (p -> signature == NIL) {
00296                             dbgmsg("finddecl: use list type without sig\n");
00297                         }
00298                     )
00299                     if (p -> signature == ERR_SIG) {
00300                         found_it = TRUE;
00301                     } else if (p -> signature -> kind == TYPESIGNATURE) {
00302                         found_it = hasstring(p -> signature, string);
00303                     } else {
00304                         /* leave error for checksigs to find */
00305                         found_it = FALSE;
00306                     }
00307                     if(found_it) {
00308                         initfld(&(string -> sel_type), unshare(p));
00309                         break;
00310                     }
00311                 });
00312                 usl = usl -> usl_previous_list;
00313             }
00314     } else /* type explicitly specified */ {
00315         if ((q = findsig(string -> sel_type, FALSE)) != SUCCESS) {
00316             return(q);
00317         }
00318         if (string -> sel_type -> signature == ERR_SIG) {
00319             return(SUCCESS);
00320         }
00321         if (!hasstring(string -> sel_type -> signature, string)) {
00322             chgfld(&(string -> sel_type), NIL);
00323         }
00324     }
00325     return(SUCCESS);
00326 }
00327 
00328 /*
00329  *  prev_def(def_pointer)
00330  *
00331  *  Returns the value of the previous definition field in the node pointed
00332  * to by def_pointer.
00333  */
00334 
00335 NODE *
00336 prev_def(def)
00337 NODE * def;
00338 {
00339     switch(def -> kind) {
00340         case DECLARATION:
00341             return(def -> decl_previous_definition);
00342         case PARAMETER:
00343             return(def -> par_previous_definition);
00344         case TYPESIGNATURE:
00345             return(def -> ts_previous_definition);
00346         case PRODCONSTRUCTION:
00347         case UNIONCONSTRUCTION:
00348             return(def -> prod_previous_definition);
00349         case RECORDCONSTRUCTION:
00350             return(def -> rec_previous_definition);
00351         case MODPRIMARY:
00352             switch (def -> mp_type_modifier -> kind) {
00353                 case WITHLIST:
00354                     return(def -> mp_type_modifier -> wl_previous_definition);
00355                 case EXPORTLIST:
00356                 case HIDELIST:
00357                     return(def -> mp_type_modifier -> el_previous_definition);
00358 #               ifdef DEBUG
00359                     default:
00360                         dbgmsg("prev_def: bad type modifier\n");
00361 #               endif
00362             }
00363 #       ifdef DEBUG
00364             default:
00365                 dbgmsg("prev_def: bad definition field\n");
00366 #       endif
00367     }
00368 }
00369 
00370 /*
00371  * sig_structure(sig)
00372  *
00373  *  Return a signature equivalent to sig that is not an identifier
00374  *  Assumes that a validity check was performed earlier.
00375  */
00376 NODE * sig_structure(sig)
00377 NODE * sig;
00378 {
00379     NODE * result = sig;
00380 
00381     while (result -> kind == LETTERID || result -> kind == OPRID
00382            && result -> id_last_definition -> kind == DECLARATION
00383            && result -> id_last_definition -> decl_sig_transp) {
00384         result = result -> id_last_definition -> decl_denotation;
00385     }
00386     return(result);
00387 }
00388 
00389 
00390 /*
00391  * def_match( definition_signature, given_signature,
00392  *            application, op, exact )
00393  *
00394  * returns TRUE iff definition_signature is the same as given_signature
00395  * (if any) and - if application is given - is a function signature
00396  * with parameter signatures which match the argument list.
00397  *  The operator op is sometimes need to infer missing arguments.
00398  */ 
00399 
00400 
00401 boolean
00402 def_match( sig, sig2, appl, op, exact )
00403 NODE * sig, * sig2, * appl;
00404 NODE * op;
00405 boolean exact;
00406 {
00407     register NODE * arg_sig;
00408     NODE * args;
00409     NODE * void_decl;
00410     NODE * arg_type;
00411     NODE * new_args;
00412     int num_args, num_params;
00413 
00414     if (appl != NIL) {
00415 #       ifdef DEBUG
00416             if (appl -> kind != APPLICATION) {
00417                 dbgmsg("def_match: bad application\n");
00418                 abort();
00419             }
00420 #       endif
00421         args = appl -> ap_args;
00422         void_decl = appl -> ap_void_decl;
00423     } else {
00424         args = NIL;
00425         void_decl = NIL;
00426     }
00427     if (sig == ERR_SIG)
00428         return(TRUE);
00429     if (sig -> kind == LETTERID || sig -> kind == OPRID) {
00430 #       ifdef TRACE
00431             printf("Replacing signature transparent identifier\n");
00432 #       endif
00433         sig = sig_structure(sig);
00434     }
00435     if (sig2 != NIL && sig2 != ERR_SIG && comp_st(sig, sig2, NIL, NIL) != 0) {
00436 #       ifdef TRACE
00437             printf("Failed to match explicit signature\n");
00438 #       endif
00439         return(FALSE);
00440     }
00441     if (args == NIL)
00442         return(TRUE);
00443     if (sig -> kind != FUNCSIGNATURE) {
00444 #       ifdef TRACE
00445             printf("Non-function id with a specified application\n");
00446 #       endif
00447         return(FALSE);
00448     }
00449     num_args = length(args);
00450     num_params = length(sig -> fsig_param_list);
00451     if (num_args < num_params) {
00452         new_args = infer_args(args,
00453                               sig -> fsig_param_list,
00454                               void_decl, op);
00455 #       ifdef TRACE
00456             printf("Inferred arguments\n");
00457 #       endif
00458     } else {
00459         new_args = args;
00460     }
00461     if (num_args > num_params ||
00462         num_args < num_params && new_args == NIL) {
00463 #       ifdef TRACE
00464             printf("Incorrect number of arguments\n");
00465 #       endif
00466         return(FALSE);
00467     }
00468     begin_map2lists(p, new_args, q, sig -> fsig_param_list) {
00469         NODE * par_sig = q -> par_signature;
00470         NODE * s_par_sig;
00471 
00472         s_par_sig = subst(par_sig,
00473                           sig -> fsig_param_list,
00474                           new_args);
00475         arg_sig = p -> signature;
00476         if (arg_sig == ERR_SIG || s_par_sig == ERR_SIG) {
00477             if (s_par_sig != NIL && s_par_sig != ERR_SIG) {
00478                 vfree(s_par_sig);
00479             }
00480             return(TRUE);
00481         }
00482         /* If we're looking for an approximate match,  */
00483         /* make sure s_par_sig is an identifier only   */
00484         /* if it's a parameter identifier.             */
00485           if (!exact) {
00486             if (s_par_sig -> kind == LETTERID || s_par_sig -> kind == OPRID) {
00487                    s_par_sig = sig_structure(s_par_sig);
00488 #                  ifdef TRACE
00489                      unparse_file = stdout;
00490                      printf("Changed parameter signature to ");
00491                      unparse(s_par_sig);
00492                      printf("\n");
00493 #                  endif
00494             }
00495           }
00496         lock(s_par_sig);
00497         if (exact || s_par_sig -> kind != VALSIGNATURE) {
00498             if (!amatch(arg_sig, s_par_sig)) {
00499                 vfree(unlock(s_par_sig));
00500 #               ifdef TRACE
00501                     printf("Failed exact match\n");
00502 #               endif
00503                 return(FALSE);
00504             }
00505         } else {
00506           if (arg_sig -> kind == LETTERID || arg_sig -> kind == OPRID) {
00507                 arg_sig = sig_structure(arg_sig);
00508 #               ifdef TRACE
00509                   unparse_file = stdout;
00510                   printf("Changed argument signature to ");
00511                   unparse(arg_sig);
00512                   printf("\n");
00513 #               endif
00514           }
00515           switch (arg_sig -> kind) {
00516             case TYPESIGNATURE:
00517                 vfree(unlock(s_par_sig));
00518 #               ifdef TRACE
00519                     printf("Attempted val-type match\n");
00520 #               endif
00521                 return(FALSE);
00522             case FUNCSIGNATURE:
00523                 if (!is_empty(arg_sig -> fsig_param_list)) {
00524                     vfree(unlock(s_par_sig));
00525 #                   ifdef TRACE
00526                         printf("Application coercion failed - args\n");
00527 #                   endif
00528                     return(FALSE);
00529                 }
00530                 if (comp_st(arg_sig -> fsig_result_sig,
00531                             s_par_sig, NIL, NIL) != 0) {
00532                     vfree(unlock(s_par_sig));
00533 #                   ifdef TRACE
00534                         printf("Application coercion failed - result\n");
00535 #                   endif
00536                     return(FALSE);
00537                 }
00538                 break;
00539             case VARSIGNATURE:
00540                 if (comp_st(arg_sig -> var_denotation,
00541                             s_par_sig -> val_denotation, NIL, NIL) != 0) {
00542                     vfree(unlock(s_par_sig));
00543 #                   ifdef TRACE
00544                         printf("ValueOf coercion failed\n");
00545 #                   endif
00546                     return(FALSE);
00547                 }
00548                 break;
00549             case VALSIGNATURE:
00550                 if (comp_st(arg_sig -> val_denotation,
00551                             s_par_sig -> val_denotation, NIL, NIL) != 0) {
00552                     vfree(unlock(s_par_sig));
00553 #                   ifdef TRACE
00554                       {
00555                         extern NODE * diff_p, * diff_q;
00556                         printf("Val signature comparison failed with diff_p = ");
00557                         unparse_file = stdout;
00558                         unparse(diff_p);
00559                         printf("; diff_q = ");
00560                         unparse(diff_q);
00561                         printf("\n");
00562                       }
00563 #                   endif
00564                     return(FALSE);
00565                 }
00566                 break;
00567             IFDEBUG(
00568                 default:
00569                     dbgmsg("def_match: bad argument signature:%X\n", arg_sig);
00570                     prtree(p);
00571                     abort();
00572             )
00573           }
00574         }
00575         vfree(unlock(s_par_sig));
00576     }end_map2lists;
00577     return(TRUE);
00578 }

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