C:/Users/Dennis/src/lang/russell.orig/src/pass3/sigids.c

Go to the documentation of this file.
00001 # define DEBUG
00002 
00003 # define TRACE
00004 # undef TRACE
00005 /* Fix up references to identifiers within signatures.  Note          */
00006 /* that by our specially contrived restrictions this can be done      */
00007 /* before the signature deduction phase.                              */
00008 
00009 /* This pass also fixes up the def_found                              */
00010 /* of identifiers explicitly selected from a type.                    */
00011 
00012 /* String expansions are added inside signatures.                     */
00013 
00014 /* fc_code_label fields are filled in.                                */
00015 
00016 /* Ap_void_decl fields are filled in.                                 */
00017 
00018 /* fsig_slink_known fields are set for signature of function */
00019 /* constructions.  They are then propagated by pass4.        */
00020 
00021 /* NO_SURR_LOOPS flags are filled in for BLOCKDENOTATIONs.   */
00022 /* no_surr_loop fields in MODPRIMARY's are set appropriately */
00023 
00024 
00025 # include <stdio.h>
00026 # include <ctype.h>
00027 # include "parm.h"
00028 
00029 # include "stree/ststructs.mh"
00030 
00031 # include "../pass4/sigs.h"
00032 
00033 # include "is_local.h"
00034 
00035 char * getname();
00036 
00037 extern FILE * unparse_file;
00038 extern int stplinks[];
00039 extern int yynerrs;
00040 extern char * entry_name;
00041 
00042 static int fn_count = 0;
00043 
00044 static boolean insig = FALSE;     /* currently looking at signature         */
00045 
00046 static NODE * curr_void_decl = NIL;
00047 
00048 static NODE * curr_sig_transp = NIL;
00049                                   /* Innermost signature transparent       */
00050                                   /* declaration, whose r.h.s is currently */
00051                                   /* being processed.                      */
00052 
00053 static boolean in_loop = FALSE;
00054 
00055 extern NODE * var_Void;
00056 
00057 extern NODE * sig_Signature;
00058 
00059 void check_sig();       /* Checks that an expression has the form of a */
00060                         /* signature.                                  */
00061 
00062 
00063 /* Fix up the subtree headed by p */
00064 sigids(p)
00065 NODE * p;
00066 {
00067     register int * q;   /* pointer to next field of p to be recursively     */
00068                         /* examined.                                        */
00069     register int v;     /* bit vector specifying primary link fields of *p  */
00070                         /* shifted so that the most significant bit         */
00071                         /* corresponds to q.                                */
00072     boolean old_insig = insig;
00073     boolean old_in_loop = in_loop;
00074     NODE * old_void_decl = curr_void_decl;
00075     NODE * old_sig_transp = curr_sig_transp;
00076 
00077     if (p == NIL) return;
00078     switch( p -> kind ) {
00079         case OPRID:
00080         case LETTERID:
00081             if ( p -> sel_type != NIL ) {
00082                 p -> id_last_definition = NIL;
00083                 p -> id_def_found = TRUE;
00084                 sigids( p -> sel_type);
00085             } else if (insig) {
00086 #               ifdef TRACE
00087                     printf("Finding declaration of %s, curr_sig_transp = %X, def = %X\n",
00088                            getname(p -> id_str_table_index), curr_sig_transp,
00089                            p -> id_last_definition);
00090 #               endif
00091                 if (p -> signature != NIL && p -> sig_done != SIG_DONE) {
00092                     /* user specifed signature */
00093                     errmsg0(p,
00094                             "Warning - signatures in signatures are ignored");
00095                     yynerrs--;
00096                 }
00097                 if (curr_sig_transp != NIL
00098                     && p -> id_last_definition != NIL) {
00099                     NODE * def = p -> id_last_definition;
00100                     NODE * imid = curr_sig_transp -> decl_innermost_id;
00101 
00102                     /* Update innermost id of curr_sig_transp */
00103                       if (def -> kind == DECLARATION) {
00104                         NODE * id_def;
00105 
00106                         /* Check that it's not a forward reference */
00107                           if (def -> post_num >= p -> post_num) {
00108                             errmsg1(p, "Forward reference to %s in === declaration",
00109                                     getname(p -> id_str_table_index));
00110                           }
00111                         if (def -> decl_sig_transp) {
00112                             id_def = def -> decl_innermost_id;
00113                         } else {
00114                             id_def = def;
00115                         }
00116                         if (id_def != NIL &&
00117                             (imid == NIL
00118                              || is_descendant(id_def, imid -> decl_scope))) {
00119                             curr_sig_transp -> decl_innermost_id = id_def;
00120 #                           ifdef TRACE
00121                                 unparse_file = stdout;
00122                                 printf("Setting innermost id of ");
00123                                 unparse(curr_sig_transp -> decl_id);
00124                                 printf(" to ");
00125                                 unparse(id_def -> decl_id);
00126                                 printf("\n");
00127 #                           endif
00128 #                           ifdef DEBUG
00129                                 if (id_def -> kind != DECLARATION) {
00130                                     dbgmsg("Sigids: Bad decl_innermost_id\n");
00131                                 }
00132 #                           endif
00133                         }
00134                       }
00135                 }
00136                 /* MAY NEED TO BE SMARTER EVENTUALLY */
00137                 if (p -> id_last_definition == NIL
00138                     && p -> id_str_table_index != -1) {
00139                     /* This hopefully excludes defining instances */
00140                     NODE * usl = p -> id_use_list;
00141                     NODE * sig, * def;
00142 
00143                     while (usl != NIL) {
00144                         maplist(s, usl -> usl_type_list, {
00145                             if ((s -> kind != LETTERID && s -> kind != OPRID)
00146                              || s -> signature != NIL
00147                              || s -> sel_type != NIL) {
00148                                 initfld(&(p -> sel_type), s);
00149                                 goto fixed_it;
00150                             } else {
00151                                 def = s -> id_last_definition;
00152                                 if (def == NIL ||
00153                                     (def -> kind != DECLARATION &&
00154                                     def -> kind != PARAMETER) ||
00155                                     (def -> kind == DECLARATION &&
00156                                     def ->decl_signature == NIL)) {
00157                                     initfld(&(p -> sel_type),s);
00158                                     goto fixed_it;
00159                                 }
00160                                 sig = (def -> kind == PARAMETER) ?
00161                                       def -> par_signature :
00162                                       def -> decl_signature;
00163                                 if (sig -> kind == TYPESIGNATURE &&
00164                                     hascomp(sig, p -> id_str_table_index)) {
00165                                     initfld(&(p -> sel_type), s);
00166                                     goto fixed_it;
00167                                 }
00168                             }
00169                         });
00170                         usl = usl -> usl_previous_list;
00171                     }
00172                     errmsg1(p,"%s undeclared",
00173                         getname(p -> id_str_table_index));
00174                     /* make sure the next pass doesn't run into it again */
00175                         p -> signature = ERR_SIG;
00176                         p -> sig_done = SIG_DONE;
00177                     break;
00178                 }
00179                 fixed_it:
00180                     p -> id_def_found = TRUE;
00181                     sigids(p -> sel_type);
00182             }
00183             check_sig(p -> signature);
00184             sigids( p -> signature );
00185             break;
00186 
00187         case QSTR:
00188         case UQSTR:
00189             if ( p -> sel_type != NIL ) {
00190                 sigids( p -> sel_type);
00191                 initfld(&(p -> str_expansion), expand_str(p));
00192             } else if (insig) {
00193                 /* MAY NEED TO BE SMARTER EVENTUALLY */
00194                 NODE * usl = p -> str_use_list;
00195                 NODE * sig, * def;
00196 
00197                 while (usl != NIL) {
00198                     maplist(s, usl -> usl_type_list, {
00199                         if ((s -> kind != LETTERID && s -> kind != OPRID)
00200                              || s -> signature != NIL
00201                              || s -> sel_type != NIL) {
00202                             initfld(&(p -> sel_type), s);
00203                             goto str_fixed_it;
00204                         } else {
00205                             def = s -> id_last_definition;
00206                             if (def == NIL ||
00207                                 (def -> kind != DECLARATION &&
00208                                  def -> kind != PARAMETER) ||
00209                                 (def -> kind == DECLARATION &&
00210                                  def ->decl_signature == NIL)) {
00211                                 initfld(&(p -> sel_type),s);
00212                                 goto str_fixed_it;
00213                             }
00214                             sig = (def -> kind == PARAMETER) ?
00215                                   def -> par_signature :
00216                                   def -> decl_signature;
00217                             if (sig -> kind == TYPESIGNATURE &&
00218                                 hasstring(sig, p)) {
00219                                 initfld(&(p -> sel_type), s);
00220                                 goto str_fixed_it;
00221                             }
00222                         }
00223                     });
00224                     usl = usl -> usl_previous_list;
00225                 }
00226                 /* no suitable type for the implied selection was found */
00227                 switch(p -> kind) {
00228                     case QSTR:
00229                         errmsg1(p, "No appropriate type for \"%s\" inside signature",
00230                                 p -> str_string);
00231                         break;
00232                     case UQSTR:
00233                         errmsg1(p, "No appropriate type for %s inside signature",
00234                                 p -> str_string);
00235                         break;
00236                 }
00237                 p -> signature = ERR_SIG;
00238                 p -> sig_done = SIG_DONE;
00239                 break;
00240             str_fixed_it:
00241                 initfld(&(p -> str_expansion), expand_str(p));
00242             }
00243             break;
00244 
00245         case RECORDCONSTRUCTION:
00246                 maplist(s, p -> rec_component_list, {
00247                     sigids(s -> re_denotation);
00248                 });
00249             break;
00250 
00251         case FUNCCONSTR:
00252             /* give it a reasonable name */
00253               if (p -> fc_code_label == NIL) {
00254 #               define FN_LN_LEN 16
00255                 char * fn_name =
00256                   (char *) malloc(strlen(entry_name)+FN_LN_LEN);
00257 
00258                 findvl(p -> vlineno);
00259                 sprintf(fn_name,"fn_%s.ln%d_%d",entry_name,getrl(),fn_count++);
00260                 p -> fc_code_label = fn_name;
00261               }
00262             in_loop = FALSE;
00263             /* look for var Void parameters, check that par. sigs are legit. */
00264                 maplist(s, p -> signature -> fsig_param_list, {
00265                     check_sig(s -> par_signature);
00266                     if (comp_st(s -> par_signature,
00267                                 var_Void, NIL, NIL) == 0) {
00268                         curr_void_decl = s;
00269                     }
00270                 });
00271                 insig = TRUE;
00272                 maplist(s, p -> signature -> fsig_param_list, {
00273                     sigids(s -> par_signature);
00274                 });
00275                 check_sig(p -> signature -> fsig_result_sig);
00276                 sigids(p -> signature -> fsig_result_sig);
00277                 insig = old_insig;
00278                 sigids(p -> fc_body);
00279                 p -> signature -> fsig_slink_known = TRUE;
00280                     /* static link is available in this context  */
00281                     /* will be cleared if function is used in    */
00282                     /* a context in which it's not available.    */
00283             break;
00284 
00285         case APPLICATION:
00286             sigids(p -> ap_operator);
00287             sigids(p -> ap_args);
00288             p -> ap_void_decl = curr_void_decl;
00289             break;
00290 
00291         case BLOCKDENOTATION:
00292             if (!in_loop) {
00293                 p -> bld_flags |= NO_SURR_LOOP;
00294             }
00295             sigids(p -> bld_declaration_list);
00296             sigids(p -> bld_den_seq);
00297             break;
00298 
00299         case DECLARATION:
00300             if (p -> decl_denotation -> kind == FUNCCONSTR
00301                 && p -> decl_id -> kind == LETTERID
00302                 && p -> decl_denotation -> fc_code_label == NIL) {
00303               /* try to give it a reasonable name */
00304 #               define FN_NAME_LEN 10
00305                 char * id_name = getname(p -> decl_id -> id_str_table_index);
00306                 if (id_name[0] != '\'') {
00307                   char * fn_name =
00308                     (char *) malloc(strlen(id_name)
00309                                     +strlen(entry_name)+FN_NAME_LEN);
00310                   sprintf(fn_name,"fn_%s.%s_%d",entry_name,id_name,fn_count++);
00311                   p -> decl_denotation -> fc_code_label = fn_name;
00312                 }
00313             }
00314             insig = TRUE; 
00315             check_sig(p -> decl_signature);
00316             sigids(p -> decl_signature);
00317             if (!p -> decl_sig_transp) {
00318                 insig = old_insig;
00319             } else {
00320                 /* Otherwise treat the denotation as a signature */
00321                 curr_sig_transp = p;
00322             }
00323             sigids(p -> decl_denotation);
00324             break;
00325 
00326         case TSCOMPONENT:
00327             check_sig(p -> tsc_signature);
00328             sigids(p -> tsc_signature);
00329             /* skip tsc_id */
00330             break;
00331 
00332         case EXPORTELEMENT:
00333             sigids(p -> ee_export_list);
00334             insig = TRUE;
00335             check_sig(p -> ee_signature);
00336             sigids(p -> ee_signature);
00337             break;
00338 
00339         case REXTERNDEF:
00340             /* Don't bother with the signature */
00341             break;
00342 
00343         case PARAMETER:
00344             insig = TRUE;
00345             check_sig(p -> par_signature);
00346             sigids(p -> par_signature);
00347             /* skip par_id */
00348             break;
00349 
00350         case LOOPDENOTATION:
00351             in_loop = TRUE;
00352             goto dflt;
00353             
00354         case MODPRIMARY:
00355             p -> mp_no_surr_loop = !in_loop;
00356             goto dflt;
00357 
00358         case TYPESIGNATURE:
00359         case FUNCSIGNATURE:
00360         case VALSIGNATURE:
00361         case VARSIGNATURE:
00362             insig = TRUE;
00363             /* and now fix up subtrees */
00364 
00365         default:
00366         dflt:
00367             /* recursively examine subtrees */
00368                 if (is_list(p)) {
00369                     maplist(e, p, {
00370                         sigids(e);
00371                     });
00372                 } else {
00373                     v = stplinks[p -> kind];
00374                     q = (int *) p;
00375                     while ( v != 0 ) {
00376                         if ( v < 0 /* msb is set */) {
00377                             sigids(*q);
00378                         }
00379                         q++;
00380                         v <<= 1;
00381                     }
00382                 }
00383     }
00384     insig = old_insig;
00385     curr_void_decl = old_void_decl;
00386     curr_sig_transp = old_sig_transp;
00387 }
00388 
00389 /* Check whether q is an explicit signature node, or an identifier bound, */
00390 /* via signature transparent declarations, to a signature.                */
00391 void check_sig(q)
00392 NODE *q;
00393 {
00394     register NODE *p = q;
00395 
00396     if (p == NIL) return;
00397     while (   (p -> kind == LETTERID || p -> kind == OPRID)
00398            && p -> sel_type == NIL
00399            && p -> id_last_definition != NIL
00400            && p -> id_last_definition -> kind == DECLARATION
00401            && p -> id_last_definition -> decl_sig_transp
00402            && p -> id_last_definition -> post_num < p -> post_num) {
00403             p = p -> id_last_definition -> decl_denotation;
00404     }
00405     switch (p -> kind) {
00406         case SIGNATURESIG:
00407         case VALSIGNATURE:
00408         case VARSIGNATURE:
00409         case FUNCSIGNATURE:
00410         case TYPESIGNATURE:
00411             break;
00412         default:
00413             if (p -> kind == LETTERID || p -> kind == OPRID) {
00414                 if ( p -> id_last_definition == NIL
00415                      || p -> id_last_definition -> kind != PARAMETER
00416                      || comp_st(p -> id_last_definition -> par_signature,
00417                                 sig_Signature, NIL, NIL) != 0) {
00418                   errmsg1(q,
00419                           "Identifier %s not meaningfully bound to a signature",
00420                           getname(q -> id_str_table_index));
00421                 }
00422             } else {
00423                 errmsg0(q, "Signature expected");
00424             }
00425     }
00426 }

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