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

Go to the documentation of this file.
00001 # define TRACE
00002 # undef TRACE
00003 # include "parm.h"
00004 
00005 # include <stdio.h>
00006 
00007 # include "stree/ststructs.mh"
00008 
00009 # include "decl_pairs.h"
00010 
00011 # include "is_local.h"
00012 
00013 # include "../pass4/sigs.h"
00014 
00015 extern int stplinks[];
00016 extern int stsigs[];
00017 
00018 extern FILE * unparse_file;
00019 
00020 /*
00021  *   Compare two syntax trees, imposing an arbitrary order, except that
00022  * WORDELSE is infinitely large.
00023  *   If tsigp and tsigq are given, they are assumed to be the next enclosing
00024  * type signatures.  Tsigp and tsigq are taken to be corresponding
00025  * declarations; an identifier in p referring to tsigp matches an identifier
00026  * in q referring to tsigq.
00027  *  The variables diff_p and diff_q are set to the first corresponding
00028  * subtrees that differ, if there are any, and if one of them is an
00029  * identifier which appears with NIL sel_type in an expression context.
00030  * They are set to NIL if this is not the case.
00031  * (This is used for missing argument inference.)
00032  *  The imposed ordering is consistent in that two sets of matching
00033  * signatures with all identifiers pointing to their correct declarations
00034  * will get ordered consistently.  This means that a string is considered
00035  * equivalent to its expansion, and a MODPRIMARY node indicating forgetting
00036  * is ignored.
00037  *   The left-hand-side of a signature transparent declaration is
00038  * identified with its right-hand-side.
00039  *
00040  *  The precise ordering is as follows:
00041  *
00042  *      0.  NIL is less than anything else.
00043  *      1.  If either tree consists of a WORDELSE node, it is greater.
00044  *      2.  If the kind fields differ, the ordering is that of the kind
00045  *          values.  OPRID and LETTERID are treated as identical.
00046  *          If 2 lists have different lengths they are ordered
00047  *          by length. 
00048  *      3.  If both nodes are identifier nodes (other than operation 
00049  *          names) then
00050  *          (a)  if they point to the same declaration they are 
00051  *               equal.
00052  *          (b)  if they point to corresponding declarations inside
00053  *               p and q they are equal
00054  *          (c)  if one points to a declaration inside the subtree
00055  *               and one points outside, the inside one is less.
00056  *          (d)  if none of the above applies the nodes are
00057  *               ordered by the preorder numbers of the declarations.
00058  *      4.  If none of the above applies the ordering is the
00059  *          lexicographic ordering (derived from this ordering) of
00060  *          the subtrees.  (The ordering of the fields within a
00061  *          node is arbitrary.)
00062  */
00063 NODE * outer_p, * outer_q;
00064 
00065 NODE * diff_p, * diff_q;
00066 
00067 comp_st(p,q,tsigp,tsigq)
00068 NODE *p, *q , *tsigp, *tsigq;
00069 {
00070     register int i;
00071 
00072     outer_p = p;
00073     outer_q = q;
00074     diff_p = NIL;
00075     diff_q = NIL;
00076     clr_dlist;
00077     if (tsigp != NIL && tsigq != NIL) {
00078       add_dlist(tsigp, tsigq);
00079     }
00080     i = comp1_st(p, q, tsigp, tsigq, FALSE);
00081 #   ifdef TRACE
00082       unparse_file = stdout;
00083       printf("comp_st: comparing %x and %x (", p, q);
00084       unparse(p);
00085       printf(" and ");
00086       unparse(q);
00087       printf(")\n");
00088       if (tsigp != NIL && tsigq != NIL) {
00089         printf("\tinside types %x and %x (", tsigp, tsigq);
00090         unparse(tsigp);
00091         printf(" and ");
00092         unparse(tsigq);
00093         printf(")\n");
00094       }
00095       printf("comp_st: returning %d\n", i);
00096 #   endif
00097     return(i);
00098 }
00099 
00100 /* The following is used both by the above and called directly by amatch */
00101 /* in pass4       */
00102 
00103 comp1_st(p, q, tsigp, tsigq, exact) 
00104                             /* exact indicates declarations , parameters, */
00105                             /* and identifiers at the top level should    */
00106                             /* match exactly, i.e. id names should match. */
00107                             /* exact should be true only if one of these  */
00108                             /* kinds of nodes or a list thereof appears   */
00109                             /* at the top level of both trees.            */
00110 
00111 NODE *p, *q, *tsigp, *tsigq;
00112 boolean exact;
00113 {
00114     register NODE **r;  /* pointer to next field of p to be recursively     */
00115                         /* examined.                                        */
00116     register NODE **s;  /* corresponding pointer for q                      */
00117     register int plinkv;/* bit vector specifying primary link fields of *p  */
00118                         /* shifted so that the most significant bit         */
00119                         /* corresponds to q.                                */
00120     register int sigv;  /* vector specifying links leading from expressions */
00121                         /* to signatures.                                   */
00122     int i,j;
00123     if (q == NIL) return(p != NIL /* 0 if both NIL, 1 o.w. */);
00124     if (p == NIL) return(-1);
00125     if (p == q) return(0);        /* only an optimization */
00126     if (p == ERR_SIG || q == ERR_SIG) return(0);
00127     if (p -> kind == WORDELSE) return(q -> kind != WORDELSE);
00128     if (q -> kind == WORDELSE) return(-1);
00129     /* make sure strings match their expansions */
00130         if ((p -> kind == QSTR || p -> kind == UQSTR)
00131             && p -> sel_type != NIL) {
00132             if (p -> str_expansion == NIL) {
00133                 chgfld(&(p -> str_expansion), expand_str(p));
00134             }
00135             p = p -> str_expansion;
00136         }
00137         if ((q -> kind == QSTR || q -> kind == UQSTR)
00138             && q -> sel_type != NIL) {
00139             if (q -> str_expansion == NIL) {
00140                 chgfld(&(q -> str_expansion), expand_str(q));
00141             }
00142             q = q -> str_expansion;
00143         }
00144     /* Don't consider MODPRIMARY nodes representing forgetting   */
00145     /* Map left-hand-sides of signature transparent declarations */
00146     /* to their right-hand-sides.                                */
00147       for (;;) {
00148         if (p -> kind == MODPRIMARY && p -> mp_type_modifier == NIL) {
00149             p = p -> mp_primary;
00150         } else if (q -> kind == MODPRIMARY && q -> mp_type_modifier == NIL) {
00151             q = q -> mp_primary;
00152         } else if (!exact
00153                    && (p -> kind == LETTERID || p -> kind == OPRID)
00154                    && p -> sel_type == NIL
00155                    && p -> id_last_definition != NIL
00156                    && p -> id_last_definition -> kind == DECLARATION
00157                    && p -> id_last_definition -> decl_sig_transp
00158                    && p -> id_last_definition -> post_num < p -> post_num) {
00159             p = p -> id_last_definition -> decl_denotation;
00160         } else if (!exact
00161                    && (q -> kind == LETTERID || q -> kind == OPRID)
00162                    && q -> sel_type == NIL
00163                    && q -> id_last_definition != NIL
00164                    && q -> id_last_definition -> kind == DECLARATION
00165                    && q -> id_last_definition -> decl_sig_transp
00166                    && q -> id_last_definition -> post_num < q -> post_num) {
00167             q = q -> id_last_definition -> decl_denotation;
00168         } else {
00169             break;
00170         }
00171       }
00172     if (p -> kind != LETTERID && p -> kind != OPRID
00173         || q -> kind != LETTERID && q -> kind != OPRID) {
00174         if (p -> kind == LETTERID || p -> kind == OPRID
00175             || q -> kind == LETTERID || q -> kind == OPRID) {
00176             diff_p = p;
00177             diff_q = q;
00178         }
00179         if (p -> kind > q -> kind) return(1);
00180         if (p -> kind < q -> kind) return(-1);
00181     }
00182     /* kind fields are equal */
00183         switch(p->kind) {
00184             case LETTERID:
00185             case OPRID:
00186               {
00187                 int p_indx;     /* string table index for p */
00188                 int q_indx;
00189                 NODE * p_decl;  /* declaration for p        */
00190                 NODE * q_decl;
00191 
00192                 p_indx = p -> id_str_table_index;
00193                 q_indx = q -> id_str_table_index;
00194                 if(exact
00195                    || p -> sel_type != NIL
00196                    || q -> sel_type != NIL) {
00197 #                   ifdef DEBUG
00198                         if (p_indx == -1 || q_indx == -1) {
00199                             dbgmsg("comp_st: local type id in wrong context\n");
00200                         }
00201 #                   endif
00202                     if(p_indx < q_indx)
00203                         return(-1);
00204                     if(p_indx > q_indx)
00205                         return(1);
00206                     return(comp1_st(p -> sel_type, q -> sel_type), tsigp, tsigq, FALSE);
00207                 } else {
00208                     p_decl = p -> id_last_definition;
00209                     q_decl = q -> id_last_definition;
00210 #                   ifdef DEBUG
00211                         if(p_indx==-1 && tsigp==NIL || q_indx==-1 && tsigq==NIL) {
00212                             dbgmsg("comp_st: bad use of local type id\n");
00213                             abort();
00214                         }
00215 #                   endif
00216                     if (p_indx == -1) p_decl = tsigp;
00217                     if (q_indx == -1) q_decl = tsigq;
00218                     if (p_decl != NIL && q_decl != NIL
00219                         && p_decl -> pre_num == q_decl -> pre_num) {
00220                         return(0);
00221                     }
00222                     if (p_decl != NIL && q_decl != NIL &&
00223                         dl_match(p_decl, q_decl)) {
00224                         return(0);
00225                     }
00226                     if (p_decl == NIL && q_decl == NIL
00227                         && p_indx == q_indx) {
00228                         return(0);
00229                     }
00230                     /* They're different */
00231                     diff_p = p;
00232                     diff_q = q;
00233                     if (p_decl == NIL && q_decl == NIL) {
00234                       if(p_indx < q_indx) {
00235                           return(-1);
00236                       } else {
00237                           return(1);
00238                       }
00239                     }
00240                     if (q_decl == NIL) return (1);
00241                     if (p_decl == NIL) return (-1);
00242                     if (is_descendant(q_decl, outer_q)
00243                         && !is_descendant(p_decl, outer_p)) {
00244                         return(1);
00245                     }
00246                     if (is_descendant(p_decl, outer_p)
00247                         && !is_descendant(q_decl, outer_q)) {
00248                         return(-1);
00249                     }
00250                     if (p_decl -> pre_num  > q_decl -> pre_num) {
00251                         return(1);
00252                     } else {
00253                         return(-1);
00254                     }
00255                 }
00256               }
00257 
00258             case QSTR:
00259             case UQSTR:
00260                 i = strcmp(p -> str_string, q -> str_string);
00261                 if (i != 0)
00262                     return(i);
00263                 else
00264                     return(comp1_st(p -> sel_type, q -> sel_type), tsigp, tsigq, FALSE);
00265 
00266             case FUNCCONSTR:
00267                 i = length(p->signature->fsig_param_list);
00268                 j = length(q->signature->fsig_param_list);
00269                 if (i > j) return(1);
00270                 if (i < j) return(-1);
00271                 map2lists (s, p -> signature -> fsig_param_list,
00272                            r, q -> signature -> fsig_param_list, {
00273                     add_dlist(s, r);
00274                 });
00275                 map2lists (s, p -> signature -> fsig_param_list,
00276                            r, q -> signature -> fsig_param_list, {
00277                     if ((i = comp1_st(s -> par_signature, r -> par_signature,
00278                                       tsigp, tsigq, FALSE)) != 0) {
00279                         return(i);
00280                     }
00281                 });
00282                 return(
00283                     comp1_st(p -> fc_body, q -> fc_body, tsigp, tsigq, FALSE)
00284                 );
00285 
00286             case EXTERNDEF:
00287                 return(strcmp(p -> ext_name, q -> ext_name));
00288 
00289             case REXTERNDEF:
00290                 return(strcmp(p -> r_ext_name, q -> r_ext_name));
00291 
00292             case FUNCSIGNATURE:
00293                 i = length(p->fsig_param_list);
00294                 j = length(q->fsig_param_list);
00295                 if (i > j) return(1);
00296                 if (i < j) return(-1);
00297                 map2lists (s, p -> fsig_param_list,
00298                            r, q -> fsig_param_list, {
00299                     add_dlist(s, r);
00300                 });
00301                 map2lists (s, p -> fsig_param_list,
00302                            r, q -> fsig_param_list, {
00303                     i = comp1_st(s->par_signature, r->par_signature,
00304                                  tsigp,tsigq,FALSE);
00305                     if (i != 0) {
00306                         return(i);
00307                     }
00308                 });
00309                 return(comp1_st(p -> fsig_result_sig, q-> fsig_result_sig,
00310                                 tsigp, tsigq, FALSE));
00311 
00312             case TYPESIGNATURE:
00313                 add_dlist(p,q);
00314                 return(comp1_st(p->ts_clist, q->ts_clist, p, q, FALSE));
00315 
00316             case PARAMETER:
00317 #               ifdef DEBUG
00318                 if(!exact) {
00319                     /* should never get here */
00320                         dbgmsg("comp_st: bad parameter\n");
00321                         prtree(p);
00322                         abort();
00323                 }
00324 #               endif
00325                 return(comp1_st(p -> par_id, q -> par_id, tsigp, tsigq, TRUE));
00326 
00327             case DECLARATION:
00328 #               ifdef DEBUG
00329                 if(!exact) {
00330                     /* should have been processed in BLOCKDENOTATION */
00331                         dbgmsg("comp_st: bad declaration\n");
00332                 }
00333 #               endif
00334                 {
00335                     int i;
00336                     i = comp1_st(p -> decl_id, q -> decl_id, tsigp, tsigq, tsigq, TRUE);
00337                     if (i != 0) return(i);
00338                 }
00339                 return(comp1_st(p -> decl_denotation,
00340                                 q -> decl_denotation, tsigp, tsigq, FALSE));
00341 
00342             case BLOCKDENOTATION:
00343                 i = length(p -> bld_declaration_list);
00344                 j = length(q -> bld_declaration_list);
00345                 if(i > j) return(1);
00346                 if(i < j) return(-1);
00347                 map2lists(s, p -> bld_declaration_list,
00348                           r, q -> bld_declaration_list, {
00349                     add_dlist(s, r);
00350                 });
00351                 map2lists(s, p -> bld_declaration_list,
00352                           r, q -> bld_declaration_list, {
00353                     i = comp1_st(s -> decl_denotation, 
00354                                  r -> decl_denotation, tsigp, tsigq, FALSE);
00355                     if(i != 0) return(i);
00356                 });
00357                 return(comp1_st(p -> bld_den_seq,
00358                                 q -> bld_den_seq, tsigp,tsigq,FALSE));
00359 
00360             case RECORDELEMENT:
00361                 {
00362                     int i;
00363                     i = comp1_st(p -> re_id, q -> re_id, tsigp, tsigq, TRUE);
00364                     if (i != 0)
00365                         return(i);
00366                     else
00367                         return(comp1_st(p -> re_denotation,
00368                                         q -> re_denotation, tsigp, tsigq, FALSE));
00369                 }
00370 
00371             case TSCOMPONENT:
00372                 {
00373                     int i;
00374                     i = comp1_st(p -> tsc_id, q -> tsc_id, tsigp, tsigq, TRUE);
00375                     if (i != 0)
00376                         return(i);
00377                     else
00378                         return(comp1_st(p -> tsc_signature,
00379                                         q -> tsc_signature, tsigp, tsigq, FALSE));
00380                 }
00381 
00382             case DEFCHARSIGS:
00383                 {
00384                     unsigned * vp;  /* pointers to current bitvectors */
00385                     unsigned * vq;
00386 
00387                     vp = (unsigned *) &(p -> dcs_0);
00388                     vq = (unsigned *) &(q -> dcs_0);
00389                     for (i = 0; i < NVECTORS; i++) {
00390                         if (*vp < *vq) return (-1);
00391                         if (*vp > *vq) return (1);
00392                         vp++; vq++;
00393                     }
00394                     return(0);
00395                 }
00396 
00397             case UNIONCONSTRUCTION:
00398             case PRODCONSTRUCTION:
00399                 /* check to make sure that field names match */
00400                     map2lists(s, p -> prod_components,
00401                               r, q -> prod_components, {
00402                         i = comp1_st(s -> par_id, r -> par_id,
00403                                      tsigp, tsigq, TRUE);
00404                         if (i != 0) return(i);
00405                     });
00406 
00407                 if (p -> kind == PRODCONSTRUCTION) {
00408                   /* add identifiers to definitions list */
00409                     map2lists(s, p -> prod_components,
00410                               r, q -> prod_components, {
00411                         add_dlist(s, r);
00412                     });
00413                     add_dlist(p,q);
00414                 }
00415                 
00416                 /* check that signatures match */
00417                     map2lists(s, p -> prod_components,
00418                               r, q -> prod_components, {
00419                         i = comp1_st(s -> par_signature, r -> par_signature,
00420                                      tsigp, tsigq, FALSE);
00421                         if (i != 0) return(i);
00422                     });
00423 
00424                 /* both products or unions are identical */
00425                 return(0);
00426 
00427             case MODPRIMARY:
00428                 add_dlist(p,q);
00429                 goto lex_order;
00430 
00431             case WITHLIST:
00432                 exact = TRUE;
00433                 /* and now continue: */
00434             default:
00435             lex_order:
00436                 /* recursively examine subtrees */
00437                     if (is_list(p)) {
00438 #                       ifdef DEBUG
00439                             if(!is_list(q)) {
00440                                 dbgmsg("comp_st: inconsistent lists\n");
00441                             }
00442 #                       endif
00443                         i = length(p);
00444                         j = length(q);
00445                         if (i > j) return(1);
00446                         if (i < j) return(-1);
00447                         map2lists(e1, p, e2, q, {
00448                            if ((i = comp1_st(e1, e2, tsigp, tsigq, exact)) != 0)
00449                                return(i);
00450                         });
00451                     } else {
00452                         plinkv = stplinks[p -> kind];
00453                         sigv = stsigs[p -> kind];
00454                         r = (NODE **) p;
00455                         s = (NODE **) q;
00456                         while ( plinkv != 0 ) {
00457                             if ( plinkv < 0 /* msb is set */ && sigv >= 0) {
00458                                 if ((i = comp1_st(*r, *s, tsigp, tsigq, exact)) != 0)
00459                                     return(i);
00460                             }
00461                             r++;
00462                             s++;
00463                             plinkv <<= 1;
00464                             sigv <<= 1;
00465                         }
00466                     }
00467                     return(0);
00468         }
00469 }

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