C:/Users/Dennis/src/lang/russell.orig/src/pass5c/decl_sort.c

Go to the documentation of this file.
00001 # include "parm.h"
00002 # include <stdio.h>
00003 # include "stree/ststructs.mh"
00004 # include "stree/Array.h"
00005 # include "pass5c/codeutil.h"
00006 
00007 extern int yynerrs;     /* Incremented by errmsg macros */
00008 
00009 Array * (list_to_array());
00010 
00011 /* Return -1, 0, or 1, depending on whether the preorder number of p */
00012 /* is less than, equal to, or greater than, that of q.               */
00013 static int pre_order(p, q)
00014 NODE **p, **q;
00015 {
00016     if ((*p) -> pre_num < (*q) -> pre_num) {
00017         return(-1);
00018     } else if ((*p) -> pre_num > (*q) -> pre_num) {
00019         return(1);
00020     } else {
00021         return(0);
00022     }
00023 }
00024 
00025 /* Return a copy of the list of declarations in its original order,   */
00026 /* that is, sort it by pre-order number.                              */
00027 NODE * decl_sort(decl_l)
00028 NODE * decl_l;
00029 {
00030     Array * a = list_to_array(decl_l);
00031     NODE * result = emptylist();
00032     NODE **p;
00033     int i;
00034 
00035     qsort(a -> a_body, a -> a_size, sizeof(NODE *), pre_order);
00036 
00037     /* Convert back to list form */
00038         for (p = a -> a_body; p < &(a -> a_body[a -> a_size]); p++) {
00039             addright(result, *p);
00040         }
00041 
00042     return(result);
00043 }
00044 
00045 #define NOT_REFD 0x7fffffff
00046 
00047 void label_refd_decls();
00048 void find_forward_refs();
00049 
00050 static NODE * current_scope;  /* pointer to current block of sorting decls */
00051 static NODE * current_mp;     /* pointer to current MODPRIMARY node if     */
00052                               /* sorting with list. NIL o.w.               */
00053 
00054 
00055 /*
00056  *  Fill in decl_can_be_refd fields in the the list of declarations
00057  * decl_l.  These should contain the least preorder number of
00058  * any declaration in the list whose elaboration can require the
00059  * value produced by the declaration under consideration.
00060  *  Then fill in the id_forward_ref fields to label those identifiers
00061  * whose evaluation could result in a reference to a not yet computed
00062  * value.  id_forward_ref fields assume that function abstractions
00063  * appearing directly on the rhs of a declaration are NOT implemented
00064  * by copying globals into the closure.  (Directly means by themselves
00065  * or in a WITH list appearing at the outermost level.)
00066  */
00067 
00068 NODE * label_decls(decl_l)
00069 NODE * decl_l;
00070 {
00071     int len = length(decl_l);
00072     register int i;
00073 
00074     if (len == 0) return(decl_l);
00075     ASSERT(decl_l -> kind == LISTHEADER, "label_decls: bad declaration list\n");
00076     /* initialize static variables */
00077         current_scope = first(decl_l) -> decl_scope;
00078         current_mp = NIL;
00079     /* initialize decl_can_be_refd fields */
00080         maplist(p ,decl_l, {
00081             p -> decl_can_be_refd = NOT_REFD;
00082         });
00083     maplist(p, decl_l, {
00084         /* update decl_can_be_refd fields to reflect references from */
00085         /* within p -> decl_denotation.  Initially ignore function   */
00086         /* constructions.                                            */
00087             switch(p -> decl_denotation -> kind) {
00088               case FUNCCONSTR:
00089                 /* Not generally evaluated during declaration elaboration. */
00090                 /* cl_analyze has to compensate if it wants to copy        */
00091                 /* globals into a closure.                                 */
00092                 break;
00093               case MODPRIMARY:
00094                 {
00095                   NODE * den = p -> decl_denotation;
00096 
00097                   /* Mark the type expression as referenced, but */
00098                   /* omit function constructions in WITH lists.  */
00099                     while (den -> kind == MODPRIMARY) {
00100                         if (den -> mp_type_modifier == NIL
00101                             || den -> mp_type_modifier -> kind == EXPORTLIST
00102                             || den -> mp_type_modifier -> kind == HIDELIST) {
00103                             den = den -> mp_primary;
00104                         } else /* with list */ {
00105                             ASSERT(den -> mp_type_modifier -> kind
00106                                    == WITHLIST, "label_decls: bad mp\n");
00107                             maplist(s, den -> mp_type_modifier
00108                                            -> wl_component_list, {
00109                                 ASSERT(s -> kind == DECLARATION,
00110                                        "label_decls: bad wl\n");
00111                                 if (s -> decl_denotation -> kind != FUNCCONSTR) {
00112                                     label_refd_decls(s -> decl_denotation,
00113                                                      p -> pre_num);
00114                                 }
00115                             });
00116                             den = den -> mp_primary;
00117                         }
00118                     }
00119                     label_refd_decls(den, p -> pre_num);
00120                   break;
00121                 }
00122               default:
00123                 label_refd_decls(p -> decl_denotation, p -> pre_num);
00124                 break;
00125             }
00126     });
00127     /* Fill in id_forward_ref fields */
00128       maplist(p, decl_l, {
00129         if (p -> decl_denotation -> kind == FUNCCONSTR) {
00130             if (p -> decl_can_be_refd != NOT_REFD) {
00131                 find_forward_refs(p -> decl_denotation, p -> decl_can_be_refd);
00132             }
00133         } else {
00134             if (p -> decl_can_be_refd < p -> pre_num) {
00135                 find_forward_refs(p -> decl_denotation, p -> decl_can_be_refd);
00136             } else {
00137                 find_forward_refs(p -> decl_denotation, p -> pre_num);
00138             }
00139         }
00140       });
00141     return(decl_l);
00142 }
00143 
00144 /*
00145  *  Fill in decl_can_be_refd and id_forward_ref fields in the declaration
00146  * list associated with the with list of the given MODPRIMARY node.
00147  * Mp must refer to a with list.  The list of declarations is returned.
00148  */
00149 
00150 LIST
00151 label_wl(mp)
00152 NODE * mp;
00153 {
00154     int len;
00155     NODE * decl_l;
00156            
00157     ASSERT(mp -> kind == MODPRIMARY 
00158            && mp -> mp_type_modifier -> kind == WITHLIST,
00159            "label_wl: bad with list");
00160     decl_l =  mp -> mp_type_modifier -> wl_component_list;
00161     len = length(decl_l);
00162     if (len == 0) return(decl_l);
00163     ASSERT(decl_l -> kind == LISTHEADER, "wl_sort: bad declaration list\n");
00164     /* initialize static variables */
00165         current_scope = NIL;
00166         current_mp = mp;
00167     /* initialize decl_can_be_refd fields */
00168         maplist(p ,decl_l, {
00169             p -> decl_can_be_refd = NOT_REFD;
00170         });
00171     maplist(p, decl_l, {
00172         /* update decl_can_be_refd fields to reflect references from */
00173         /* within p -> decl_denotation.  Initially ignore function   */
00174         /* constructions.                                            */
00175             if (p -> decl_denotation -> kind != FUNCCONSTR) {
00176                 label_refd_decls(p -> decl_denotation, p -> pre_num);
00177             }
00178     });
00179     /* Fill in id_forward_ref fields */
00180       maplist(p, decl_l, {
00181         if (p -> decl_denotation -> kind == FUNCCONSTR) {
00182             if (p -> decl_can_be_refd != NOT_REFD) {
00183                 find_forward_refs(p -> decl_denotation, p -> decl_can_be_refd);
00184             }
00185         } else {
00186             if (p -> decl_can_be_refd < p -> pre_num) {
00187                 find_forward_refs(p -> decl_denotation, p -> decl_can_be_refd);
00188             } else {
00189                 find_forward_refs(p -> decl_denotation, p -> pre_num);
00190             }
00191         }
00192       });
00193     return(decl_l);
00194 }
00195 
00196 
00197 /*
00198  *  Label all declarations whose value may be needed in the evaluation
00199  * of p as being needed by a declaration with pre-order number prenum.
00200  */
00201 void label_refd_decls(p, prenum)
00202 NODE * p;
00203 int prenum;
00204 {
00205     switch(p -> kind) {
00206         case BLOCKDENOTATION:
00207             maplist(s, p -> bld_declaration_list, {
00208                 label_refd_decls(s -> decl_denotation, prenum);
00209             });
00210             maplist(s, p -> bld_den_seq, {
00211                 label_refd_decls(s, prenum);
00212             });
00213             break;
00214 
00215         case USELIST:
00216             maplist(s, p -> usl_type_list, {
00217                 label_refd_decls(s, prenum);
00218             });
00219             maplist(s, p -> usl_den_seq, {
00220                 label_refd_decls(s, prenum);
00221             });
00222             break;
00223 
00224         case APPLICATION:
00225             label_refd_decls(p -> ap_operator, prenum);
00226             maplist(s, p -> ap_args, {
00227                 label_refd_decls(s, prenum);
00228             });
00229             break;
00230 
00231         case EXTENSION:
00232             /* The compiler causes the argument of an extension */
00233             /* to be evaluated.                                 */
00234             label_refd_decls(p -> ext_denotation, prenum);
00235             break;
00236 
00237         case RECORDCONSTRUCTION:
00238             maplist(s, p -> rec_component_list, {
00239                 label_refd_decls(s -> re_denotation, prenum);
00240             });
00241             break;
00242 
00243         case WORDELSE:
00244         case ENUMERATION:
00245         case PRODCONSTRUCTION:
00246         case UNIONCONSTRUCTION:
00247         case EXTERNDEF:
00248         case REXTERNDEF:
00249             /* The "arguments" are not evaluated */
00250             break;
00251 
00252         case MODPRIMARY:
00253             {
00254                 NODE * tm = p -> mp_type_modifier;
00255 
00256                 label_refd_decls(p -> mp_primary, prenum);
00257                 if (tm != NIL && tm -> kind == WITHLIST) {
00258                     maplist(s, tm -> wl_component_list, {
00259                         label_refd_decls(s -> decl_denotation, prenum);
00260                     });
00261                 }
00262             }
00263             break;
00264 
00265         case GUARDEDLIST:
00266         case LOOPDENOTATION:
00267             maplist(s, p -> gl_list, {
00268                 label_refd_decls(s -> ge_guard, prenum);
00269                 label_refd_decls(s -> ge_element, prenum);
00270             });
00271             break;
00272 
00273         case OPRID:
00274         case LETTERID:
00275             ASSERT(p ->  id_str_table_index != -1,
00276                    "label_refd_decls: Funny identifier\n");
00277             if (current_mp == NIL) /* normal declarations */ {
00278                 NODE * def = p -> id_last_definition;
00279 
00280                 if (p -> sel_type != NIL) {
00281                     label_refd_decls(p -> sel_type, prenum);
00282                 } else if (def -> kind == DECLARATION
00283                     && def -> decl_scope == current_scope) {
00284                     /* This is a reference to an identifier in the */
00285                     /* current block.                              */
00286                     if (prenum < def -> decl_can_be_refd) {
00287                         def -> decl_can_be_refd = prenum;
00288                         label_refd_decls(def -> decl_denotation, prenum);
00289                     }
00290                 }
00291             } else /* with list */ {
00292                 NODE * sel_t = p -> sel_type;
00293 
00294                 if (sel_t == NIL) {
00295                     if (p -> id_last_definition == current_mp) {
00296                     /* reference to new type as a whole */
00297                       errmsg0(p, "Warning - forward reference to local type identifier - no runtime check inserted");
00298                       yynerrs--;  /* only a warning */
00299                     }
00300                 } else /* sel_type not NIL */ {
00301 
00302                     if ((   sel_t -> kind == LETTERID
00303                          || sel_t -> kind == OPRID)
00304                          && sel_t -> sel_type == NIL
00305                          && sel_t -> id_last_definition == current_mp) {
00306                         /* obvious selection from local type id          */
00307                         /* update with list component which defines this */
00308                         /* component.                                    */
00309                           maplist(s, current_mp -> mp_type_modifier
00310                                               -> wl_component_list, {
00311                             if (s -> decl_sel_index
00312                                 == p -> sel_index) {
00313                                 /* It refers to this decl */
00314                                 if (prenum < s -> decl_can_be_refd) {
00315                                     s -> decl_can_be_refd = prenum;
00316                                     label_refd_decls(s -> decl_denotation,
00317                                                      prenum);
00318                                 }
00319                             }
00320                           });
00321                     } else {
00322                         label_refd_decls(sel_t, prenum);
00323                     }
00324                 }
00325             }
00326             break;
00327 
00328         case QSTR:
00329         case UQSTR:
00330             if (current_mp != NIL) {
00331                 /* In the case of a with list make sure that constants */
00332                 /* and concatenation operators in string are computed  */
00333                 /* first.                                              */
00334                   if (p -> sel_type -> signature -> ts_string_code != NIL &&
00335                       p -> sel_type -> signature -> ts_element_code != NIL) {
00336                       /* No subexpressions will be evaluated */
00337                   } else {
00338                       label_refd_decls(p -> str_expansion, prenum);
00339                   }
00340             } else {
00341                 /* For declarations we don't care about individual type */
00342                 /* components.  Just process selection type.            */
00343                 label_refd_decls(p -> sel_type, prenum);
00344             }
00345             break;
00346 
00347         case FUNCCONSTR:
00348             /* function is referenced from within decl and may be applied */
00349             label_refd_decls(p -> fc_body, prenum);
00350             break;
00351 
00352 #   ifdef DEBUG
00353         default:
00354             dbgmsg("label_refd_decls: bad kind encountered\n");
00355             abort();
00356 #   endif
00357     }
00358 }
00359 
00360 
00361 /*
00362  *  Find any possible references within p to declarations with pre-order
00363  * number >= prenum.
00364  */
00365 void find_forward_refs(p, prenum)
00366 NODE * p;
00367 int prenum;
00368 {
00369     switch(p -> kind) {
00370         case BLOCKDENOTATION:
00371             maplist(s, p -> bld_declaration_list, {
00372                 find_forward_refs(s -> decl_denotation, prenum);
00373             });
00374             maplist(s, p -> bld_den_seq, {
00375                 find_forward_refs(s, prenum);
00376             });
00377             break;
00378 
00379         case USELIST:
00380             maplist(s, p -> usl_type_list, {
00381                 find_forward_refs(s, prenum);
00382             });
00383             maplist(s, p -> usl_den_seq, {
00384                 find_forward_refs(s, prenum);
00385             });
00386             break;
00387 
00388         case APPLICATION:
00389             find_forward_refs(p -> ap_operator, prenum);
00390             maplist(s, p -> ap_args, {
00391                 find_forward_refs(s, prenum);
00392             });
00393             break;
00394 
00395         case EXTENSION:
00396             /* The compiler causes the argument of an extension */
00397             /* to be evaluated.                                 */
00398             find_forward_refs(p -> ext_denotation, prenum);
00399             break;
00400 
00401         case RECORDCONSTRUCTION:
00402             maplist(s, p -> rec_component_list, {
00403                 find_forward_refs(s -> re_denotation, prenum);
00404             });
00405             break;
00406 
00407         case WORDELSE:
00408         case ENUMERATION:
00409         case PRODCONSTRUCTION:
00410         case UNIONCONSTRUCTION:
00411         case EXTERNDEF:
00412         case REXTERNDEF:
00413             /* The "arguments" are not evaluated */
00414             break;
00415 
00416         case MODPRIMARY:
00417             {
00418                 NODE * tm = p -> mp_type_modifier;
00419 
00420                 find_forward_refs(p -> mp_primary, prenum);
00421                 if (tm != NIL && tm -> kind == WITHLIST) {
00422                     maplist(s, tm -> wl_component_list, {
00423                         label_refd_decls(s -> decl_denotation, prenum);
00424                     });
00425                 }
00426             }
00427             break;
00428 
00429         case GUARDEDLIST:
00430         case LOOPDENOTATION:
00431             maplist(s, p -> gl_list, {
00432                 find_forward_refs(s -> ge_guard, prenum);
00433                 find_forward_refs(s -> ge_element, prenum);
00434             });
00435             break;
00436 
00437         case OPRID:
00438         case LETTERID:
00439             ASSERT(p ->  id_str_table_index != -1,
00440                    "find_forward_refs: Funny identifier\n");
00441             if (current_mp == NIL) /* normal declarations */ {
00442                 NODE * def = p -> id_last_definition;
00443 
00444                 if (p -> sel_type != NIL) {
00445                     find_forward_refs(p -> sel_type, prenum);
00446                 } else if (def -> kind == DECLARATION
00447                     && def -> decl_scope == current_scope) {
00448                     /* This is a reference to an identifier in the */
00449                     /* current block.                              */
00450                     if (prenum <= def -> pre_num) {
00451                         p -> id_forward_ref = TRUE;
00452                     }
00453                 }
00454             } else /* with list */ {
00455                 NODE * sel_t = p -> sel_type;
00456 
00457                 if (sel_t != NIL) {
00458 
00459                     if ((   sel_t -> kind == LETTERID
00460                          || sel_t -> kind == OPRID)
00461                          && sel_t -> sel_type == NIL
00462                          && sel_t -> id_last_definition == current_mp) {
00463                         /* obvious selection from local type id          */
00464                         /* Check for forward reference.                  */
00465                           maplist(s, current_mp -> mp_type_modifier
00466                                               -> wl_component_list, {
00467                             if (s -> decl_sel_index
00468                                 == p -> sel_index) {
00469                                 /* It refers to this decl */
00470                                 if (prenum <= s -> pre_num) {
00471                                     p -> id_forward_ref = TRUE;
00472                                 }
00473                             }
00474                           });
00475                     } else {
00476                         find_forward_refs(sel_t, prenum);
00477                     }
00478                 }
00479             }
00480             break;
00481 
00482         case QSTR:
00483         case UQSTR:
00484             if (current_mp != NIL) {
00485                 /* In the case of a with list make sure that constants */
00486                 /* and concatenation operators in string are not       */
00487                 /* forward references.                                 */
00488                   if (p -> sel_type -> signature -> ts_string_code != NIL &&
00489                       p -> sel_type -> signature -> ts_string_code != NIL) {
00490                       /* No subexpressions will be evaluated */
00491                   } else {
00492                       find_forward_refs(p -> str_expansion, prenum);
00493                   }
00494             } else {
00495                 /* For declarations we don't care about individual type */
00496                 /* components.  Just process selection type.            */
00497                 find_forward_refs(p -> sel_type, prenum);
00498             }
00499             break;
00500 
00501         case FUNCCONSTR:
00502             /* function is referenced from within decl and may be applied */
00503             find_forward_refs(p -> fc_body, prenum);
00504             break;
00505 
00506 #   ifdef DEBUG
00507         default:
00508             dbgmsg("find_forward_refs: bad kind encountered\n");
00509             abort();
00510 #   endif
00511     }
00512 }

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