00001
00002
00003
00004
00005
00006 # include "parm.h"
00007 # include <stdio.h>
00008 # include "stree/ststructs.mh"
00009 # include "../pass3/is_local.h"
00010
00011 extern FILE * unparse_file;
00012
00013 extern boolean Vflag;
00014 extern boolean Oflag;
00015 extern boolean Nflag;
00016
00017 extern NODE * insrtptr;
00018
00019 static boolean surr_loop = FALSE;
00020
00021
00022
00023
00024
00025
00026
00027 static boolean callcc_call = FALSE;
00028
00029
00030
00031
00032
00033
00034
00035 boolean bld_analyze(arg)
00036 NODE **arg;
00037 {
00038 NODE * p = *arg;
00039 boolean r = FALSE;
00040
00041
00042 if (p -> signature -> kind == SIGNATURESIG) return(FALSE);
00043
00044 switch(p -> kind) {
00045 case BLOCKDENOTATION:
00046 {
00047 boolean Osurr_loop = surr_loop;
00048 boolean nontr_decl = FALSE;
00049 boolean contains_closure = FALSE;
00050 extern boolean calls_callcc();
00051
00052 maplist(s, p -> bld_declaration_list, {
00053 if (s -> decl_needed) {
00054
00055 nontr_decl = TRUE;
00056 }
00057 });
00058 if (nontr_decl) {
00059
00060 if (surr_loop || callcc_call) {
00061 p -> bld_flags |= INSIDE_LOOP;
00062 }
00063 surr_loop = FALSE;
00064 }
00065 maplist(v, p -> bld_declaration_list, {
00066 contains_closure |= bld_analyze(&(v -> decl_denotation));
00067 });
00068 maplistp(v, p -> bld_den_seq, {
00069 contains_closure |= bld_analyze(v);
00070 });
00071 if (contains_closure) {
00072 p -> bld_flags |= CONTAINS_CLOSURE;
00073 }
00074 if (callcc_call) {
00075 if (Oflag) {
00076 if (calls_callcc(p)) {
00077 p -> bld_flags |= CALLCC_CALL;
00078 }
00079 } else if (!Nflag) {
00080 p -> bld_flags |= CALLCC_CALL;
00081 }
00082 }
00083 if ((p -> bld_flags & (CONTAINS_CLOSURE | CALLCC_CALL))
00084 && (p -> bld_flags & INSIDE_LOOP)
00085 && is_descendant(p, insrtptr)) {
00086 p -> bld_flags |= REQUIRES_AR;
00087
00088
00089
00090
00091 if (Vflag) {
00092 findvl(p -> vlineno);
00093 printf("Block requires a.r. (file: %s, line: %d)\n",
00094 getname(getfn()), getrl());
00095 if (Osurr_loop) {
00096 printf("\t- explicit surrounding loop\n");
00097 }
00098 if (callcc_call) {
00099 printf("\t- possible Callcc call in function may create loop\n");
00100 }
00101 if (p -> bld_flags & CONTAINS_CLOSURE) {
00102 printf("\t- embedded closure\n");
00103 }
00104 if (p -> bld_flags & CALLCC_CALL) {
00105 printf("\t- possible embedded Callcc call\n");
00106 }
00107 }
00108 }
00109 r |= contains_closure;
00110 surr_loop = Osurr_loop;
00111 }
00112 break;
00113
00114 case MODPRIMARY:
00115 if (p -> mp_type_modifier != NIL
00116 && p -> mp_type_modifier -> kind == WITHLIST) {
00117 boolean Osurr_loop = surr_loop;
00118 boolean captures_cont;
00119
00120 surr_loop = FALSE;
00121 maplist(v, p -> mp_type_modifier -> wl_component_list, {
00122 r |= bld_analyze(&(v -> decl_denotation));
00123 });
00124 if (callcc_call) {
00125 if (Oflag) {
00126 captures_cont = calls_callcc(p);
00127 } else {
00128 if (Nflag) {
00129 captures_cont = FALSE;
00130 } else {
00131 captures_cont = TRUE;
00132 }
00133 }
00134 } else {
00135 captures_cont = FALSE;
00136 }
00137 if (Osurr_loop || callcc_call) {
00138
00139
00140
00141 NODE * block = mknode(BLOCKDENOTATION,
00142 emptylist(), mklist(p, -1));
00143
00144 block -> vlineno = p -> vlineno;
00145 block -> signature = p -> signature;
00146 block -> sig_done = SIG_DONE;
00147 if ((r || captures_cont) && p -> mp_needed) {
00148 block -> bld_flags = INSIDE_LOOP;
00149 if (is_descendant(p, insrtptr)) {
00150 block -> bld_flags |= REQUIRES_AR;
00151 if (Vflag) {
00152 findvl(p -> vlineno);
00153 printf("Introducing block with a.r. for type modification (file: %s, line: %d)\n",
00154 getname(getfn()), getrl());
00155 printf("\t - type modification: ");
00156 unparse_file = stdout;
00157 unparse(p);
00158 printf("\n");
00159 if (Osurr_loop) {
00160 printf("\t- explicit surrounding loop\n");
00161 }
00162 if (callcc_call) {
00163 printf("\t- possible Callcc call in function may create loop\n");
00164 }
00165 if (r) {
00166 printf("\t- embedded closure\n");
00167 }
00168 if (captures_cont) {
00169 printf("\t- possible embedded Callcc call\n");
00170 }
00171 }
00172 }
00173 if (r) {
00174 block -> bld_flags |= CONTAINS_CLOSURE;
00175 }
00176 if (captures_cont) {
00177 block -> bld_flags |= CALLCC_CALL;
00178 }
00179 }
00180 *arg = block;
00181 }
00182 surr_loop = Osurr_loop;
00183 }
00184 r |= bld_analyze(&(p -> mp_primary));
00185 break;
00186
00187 case APPLICATION:
00188 r = bld_analyze(&(p -> ap_operator));
00189 maplistp(v, p -> ap_args, r |= bld_analyze(v));
00190 break;
00191
00192 case LOOPDENOTATION:
00193 {
00194 boolean Osurr_loop = surr_loop;
00195
00196 surr_loop = TRUE;
00197 maplist(v, p -> gl_list, {
00198 r |= bld_analyze(&(v -> ge_guard));
00199 r |= bld_analyze(&(v -> ge_element));
00200 });
00201 surr_loop = Osurr_loop;
00202 }
00203 break;
00204
00205 case QSTR:
00206 case UQSTR:
00207 {
00208 boolean Osurr_loop = surr_loop;
00209
00210 surr_loop = TRUE;
00211 bld_analyze(&(p -> sel_type));
00212 surr_loop = Osurr_loop;
00213 }
00214 break;
00215
00216 case GUARDEDLIST:
00217 maplist(v, p-> gl_list, {
00218 r |= bld_analyze(&(v -> ge_guard));
00219 r |= bld_analyze(&(v -> ge_element));
00220 });
00221 break;
00222
00223 case OPRID:
00224 case LETTERID:
00225 if (p -> sel_type != NIL) {
00226 r |= bld_analyze(&(p -> sel_type));
00227 }
00228 break;
00229
00230 case FUNCCONSTR:
00231 if (p -> fc_body -> kind == EXTERNDEF) return;
00232 {
00233 boolean Ocallcc_call = callcc_call;
00234 boolean Osurr_loop = surr_loop;
00235
00236 callcc_call = !(p -> fc_complexity & NO_CALLCC);
00237 if (Nflag) callcc_call = FALSE;
00238 surr_loop = FALSE;
00239
00240 r |= (p -> fc_complexity & NEED_CL);
00241 r |= bld_analyze(&(p -> fc_body));
00242
00243 callcc_call = Ocallcc_call;
00244 surr_loop = Osurr_loop;
00245 }
00246 break;
00247
00248 case REXTERNDEF:
00249 break;
00250
00251 case USELIST:
00252 maplistp(q, p -> usl_den_seq, r |= bld_analyze(q));
00253 break;
00254
00255 case EXTENSION:
00256 r = bld_analyze(&(p -> ext_denotation));
00257 break;
00258
00259 case RECORDCONSTRUCTION:
00260 maplist(s, p -> rec_component_list, {
00261 r |= bld_analyze(&(s -> re_denotation));
00262 });
00263 break;
00264
00265 case WORDELSE:
00266 break;
00267
00268 case PRODCONSTRUCTION:
00269 case UNIONCONSTRUCTION:
00270 case ENUMERATION:
00271
00272 break;
00273
00274 default:
00275 dbgmsg("bld_analyze: Bad kind: %d\n", p -> kind);
00276 }
00277 return(r);
00278 }