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

Go to the documentation of this file.
00001 #define DEBUG
00002 # include <stdio.h>
00003 # include "parm.h"
00004 
00005 # include "stree/ststructs.mh"
00006 
00007 # include "sigs.h"
00008 # include "../pass3/is_local.h"
00009 
00010 boolean impure();
00011 
00012 extern FILE * unparse_file;
00013 
00014 extern int stplinks[];
00015 extern int stsigs[];
00016 extern int yynerrs;
00017 extern boolean Lflag;
00018 extern NODE * var_Void;
00019 
00020 NODE * infunc = NIL;     /* innermost enclosing known type or function  */
00021                          /* denotation, or signature node.              */
00022                          /* NIL if there is none.                       */
00023 
00024 NODE * insig = NIL;      /* enclosing signature, if any                 */
00025 
00026 static int Clevel = -1;   /* Current procedure nesting level */
00027 
00028 
00029 /* make sure that there are no import rule violations within the tree headed */
00030 /* by p, and make sure that none of the identifiers are declared in          */
00031 /* scope.   (scope may be NIL.)                                              */
00032 /* Also set level fields for DECLARATION and MODPRIMARY nodes to reflect     */
00033 /* procedure nesting depth.  (Other related fields are set by allocate in    */
00034 /* pass5.)                                                                   */
00035 
00036 import(p, scope)
00037 NODE * p, * scope;
00038 {
00039     register int * q;   /* pointer to next field of p to be recursively     */
00040                         /* examined.                                        */
00041     register int plinkv;/* bit vector specifying primary link fields of *p  */
00042                         /* shifted so that the most significant bit         */
00043                         /* corresponds to q.                                */
00044     register int sigv;  /* corresponding vector for signature pointers.     */
00045     NODE * old_infunc = infunc;
00046     NODE * old_insig = insig;
00047     int sig_kind;       /* kind of signature of p                           */
00048     boolean is_expression;
00049     NODE * def;
00050 
00051     if (p == NIL || p == ERR_SIG) return;
00052 
00053     switch(p -> kind) {
00054         case BLOCKDENOTATION:
00055         case USELIST:
00056         case APPLICATION:
00057         case ENUMERATION:
00058         case EXTENSION:
00059         case PRODCONSTRUCTION:
00060         case RECORDCONSTRUCTION:
00061         case UNIONCONSTRUCTION:
00062         case MODPRIMARY:
00063         case WORDELSE:
00064         case GUARDEDLIST:
00065         case LOOPDENOTATION:
00066         case OPRID:
00067         case LETTERID:
00068         case QSTR:
00069         case UQSTR:
00070         case FUNCCONSTR:
00071         case REXTERNDEF:
00072             is_expression = TRUE;
00073             break;
00074 
00075         default:
00076             is_expression = FALSE;
00077             break;
00078     }
00079 
00080     if (is_expression && has_sig(p) /* o.w. error or already in signature */) {
00081         sig_kind = p -> signature -> kind;
00082         if (sig_kind == TYPESIGNATURE) {
00083             infunc = p;
00084         }
00085         if (p -> kind == FUNCCONSTR) {
00086             if (impure(p -> signature)) {
00087                 infunc = NIL;
00088             } else {
00089                 infunc = p;
00090             }
00091         }
00092     }
00093 
00094     switch( p -> kind ) {
00095         case OPRID:
00096         case LETTERID:
00097             if ( p -> sel_type != NIL ) {
00098                 import( p -> sel_type, scope);
00099             } else {
00100               if ((def = p -> id_last_definition) == NIL) {
00101                   break;
00102               }
00103               if (scope != NIL
00104                   && def -> kind == DECLARATION
00105                   && (   !(def -> decl_sig_transp)
00106                          && def -> decl_scope == scope
00107                       || def -> decl_sig_transp
00108                          && def -> decl_innermost_id != NIL
00109                          && def -> decl_innermost_id -> decl_scope == scope)) {
00110                 errmsg1(p,
00111                         "Identifier %s contained in signature outside its scope",
00112                         def -> decl_sig_transp?
00113                         getname(def -> decl_innermost_id -> decl_id
00114                                     -> id_str_table_index)
00115                         : getname(p -> id_str_table_index));
00116               }
00117               if (infunc != NIL) {
00118                 if (insig == NIL && has_sig(p) &&
00119                     sig_kind == VARSIGNATURE  && !is_local(p, infunc)) {
00120                     errmsg1(p,
00121                             "Variable %s imported into function or type:",
00122                             getname(p -> id_str_table_index)
00123                     );
00124                     fprintf(stderr, "\t");
00125                     unparse_file = stderr;
00126                     unparse(infunc);
00127                     fprintf(stderr,"\n\tfunction or type signature:\n\t");
00128                     unparse(infunc -> signature);
00129                     fprintf(stderr, "\n");
00130                 }
00131               }
00132             }
00133             break;
00134 
00135         case FUNCCONSTR:
00136             Clevel++;
00137             p -> ar_static_level = Clevel;
00138             /* Don't look at signature */
00139             import(p -> fc_body, scope);
00140             Clevel--;
00141             break;
00142 
00143         case APPLICATION:
00144             import(p -> ap_operator, scope);
00145             import(p -> ap_args, scope);
00146             if (insig == NIL) {
00147               /* Make sure that we didn't substitute a variable into */
00148               /* the signature.                                      */
00149                 insig = p -> signature;
00150                 import(p -> signature, scope);
00151             }
00152             break;
00153 
00154         case BLOCKDENOTATION:
00155             import(p -> bld_declaration_list, scope);
00156             import(p -> bld_den_seq, scope);
00157             if (insig == NIL) {
00158               /* Check export rule */
00159                 insig = p -> signature;
00160                 import(p -> signature, p);
00161             }
00162             break;
00163 
00164         case DECLARATION:
00165             p -> level = Clevel;
00166             import(p -> decl_denotation, scope);
00167             /* All expressions inside signatures produce types;  */
00168             /* they may however not have signatures computed.    */
00169             /* Illegally importing a variable inside a signature */
00170             /* that's declared in the signature is benign and    */
00171             /* not checked.                                      */
00172             infunc = p -> decl_signature;
00173             import(p -> decl_signature, scope);
00174             break;
00175 
00176         case MODPRIMARY:
00177             p -> level = Clevel;
00178             import(p -> mp_primary, scope);
00179             import(p -> mp_type_modifier, scope);
00180             break;
00181 
00182         case QSTR:
00183         case UQSTR:
00184             /* dont bother checking expansion */
00185             break;
00186 
00187         default:
00188             /* recursively examine subtrees */
00189                 if (is_list(p)) {
00190                     maplist(e, p, {
00191                         import(e, scope);
00192                     });
00193                 } else {
00194                     plinkv = stplinks[p -> kind];
00195                     sigv = stsigs[p -> kind];
00196                     q = (int *) p;
00197                     while ( plinkv != 0 ) {
00198                         if ( plinkv < 0 /* msb is set */ && sigv >= 0) {
00199                             import(*q, scope);
00200                         }
00201                         q++;
00202                         plinkv <<= 1;
00203                         sigv <<= 1;
00204                     }
00205                 }
00206     }
00207     infunc = old_infunc;
00208     insig = old_insig;
00209 }
00210 
00211 /* determine whether function signature p refers to an impure function */
00212 boolean impure(p)
00213 NODE *p;
00214 {
00215 #   ifdef DEBUG
00216         if (p -> kind != FUNCSIGNATURE) {
00217             dbgmsg("Bad call to impure\n");
00218         }
00219 #   endif
00220     if (!Lflag) {
00221         return(FALSE);
00222     } else {
00223         NODE * plist = p -> fsig_param_list;
00224     
00225         if (is_empty(plist)
00226             || comp_st(last(plist) -> par_signature,
00227                        var_Void,
00228                        NIL, NIL) != 0) {
00229             return(FALSE);
00230         } else {
00231             return(TRUE);
00232         }
00233     }
00234 }

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