1 package gnu.expr; 2 import gnu.bytecode.Type; 3 4 7 8 public class FindTailCalls extends ExpWalker 9 { 10 public static void findTailCalls (Expression exp, Compilation comp) 11 { 12 FindTailCalls walker = new FindTailCalls(); 13 walker.setContext(comp); 14 walker.walk(exp); 15 } 16 17 boolean inTailContext = true; 18 19 protected Expression walkApplyExp(ApplyExp exp) 20 { 21 if (inTailContext) 22 exp.setTailCall(true); 23 exp.context = currentLambda; 24 boolean save = inTailContext; 25 LambdaExp lexp = null; 26 try 27 { 28 inTailContext = false; 29 boolean isAppendValues = false; 30 if (exp.func instanceof ReferenceExp) 31 { 32 ReferenceExp func = (ReferenceExp) exp.func; 33 Declaration binding = Declaration.followAliases(func.binding); 34 if (binding != null) 35 { 36 if (! binding.getFlag(Declaration.STATIC_SPECIFIED)) 40 { 41 exp.nextCall = binding.firstCall; 42 binding.firstCall = exp; 43 } 44 Compilation comp = getCompilation(); 45 binding.setCanCall(); 46 if (! comp.mustCompile) 47 binding.setCanRead(); 49 Expression value = binding.getValue(); 50 if (value instanceof LambdaExp) 51 lexp = (LambdaExp) value; 52 } 53 } 54 else if (exp.func instanceof LambdaExp 55 && ! (exp.func instanceof ClassExp)) 56 { 57 lexp = (LambdaExp) exp.func; 58 walkLambdaExp(lexp, false); 59 lexp.setCanCall(true); 60 } 61 else if (exp.func instanceof QuoteExp 62 && (((QuoteExp) exp.func).getValue() 63 == gnu.kawa.functions.AppendValues.appendValues)) 64 isAppendValues = true; 65 else 66 exp.func = (Expression) exp.func.walk(this); 67 if (lexp != null) 68 { 69 if (lexp.returnContinuation == exp) ; else if (lexp == currentLambda && save) 71 ; else if (lexp.returnContinuation == null) 73 lexp.returnContinuation = exp; 74 else 75 lexp.returnContinuation = LambdaExp.unknownContinuation; 76 } 77 if (isAppendValues && exp.args.length > 0) 78 { 79 int last = exp.args.length - 1; 80 exp.args = walkExps(exp.args, last); 81 inTailContext = save; 82 exp.args[last] = walk(exp.args[last]); 83 } 84 else 85 exp.args = walkExps(exp.args); 86 return exp; 87 } 88 finally 89 { 90 inTailContext = save; 91 } 92 } 93 94 protected Expression walkBeginExp(BeginExp exp) 95 { 96 boolean save = inTailContext; 97 try 98 { 99 int n = exp.length - 1; 100 for (int i = 0; i <= n; i++) 101 { 102 inTailContext = (i == n) && save; 103 exp.exps[i] = (Expression) exp.exps[i].walk(this); 104 } 105 return exp; 106 } 107 finally 108 { 109 inTailContext = save; 110 } 111 } 112 113 protected Expression walkFluidLetExp (FluidLetExp exp) 114 { 115 for (Declaration decl = exp.firstDecl(); 116 decl != null; decl = decl.nextDecl()) 117 { 118 decl.setCanRead(true); 119 decl.setCanWrite(true); 120 if (decl.base != null) 121 { 122 decl.base.setCanRead(true); 123 decl.base.setCanWrite(true); 124 } 125 } 126 boolean save = inTailContext; 127 inTailContext = false; 128 try 129 { 130 return super.walkFluidLetExp(exp); 131 } 132 finally 133 { 134 inTailContext = save; 135 } 136 } 137 138 protected Expression walkLetExp (LetExp exp) 139 { 140 int n = exp.inits.length; 141 boolean save = inTailContext; 142 Declaration decl; 143 try 144 { 145 inTailContext = false; 146 147 decl = exp.firstDecl(); 148 for (int i = 0; i < n; i++, decl = decl.nextDecl()) 149 { 150 Expression init = walkSetExp (decl, exp.inits[i]); 151 if (init == QuoteExp.undefined_exp) 153 { 154 Expression value = decl.getValue(); 155 if (value instanceof LambdaExp 156 || (value != init && value instanceof QuoteExp)) 157 init = value; 158 } 159 exp.inits[i] = init; 160 } 161 } 162 finally 163 { 164 inTailContext = save; 165 } 166 exp.body = (Expression) exp.body.walk(this); 167 walkDecls(exp); 168 return exp; 169 } 170 171 public void walkDecls (ScopeExp exp) 172 { 173 Declaration decl = exp.firstDecl(); 174 for (; decl != null; decl = decl.nextDecl()) 175 { 176 Expression value = decl.getValue(); 177 if (value instanceof LambdaExp) 178 { 179 LambdaExp lexp = (LambdaExp) value; 180 if (decl.getCanRead()) 181 lexp.setCanRead(true); 182 if (decl.getCanCall()) 183 lexp.setCanCall(true); 184 } 185 if (decl.getFlag(Declaration.EXPORT_SPECIFIED) 186 && value instanceof ReferenceExp) 187 { 188 ReferenceExp rexp = (ReferenceExp) value; 189 Declaration context = rexp.contextDecl(); 190 if (context != null && context.isPrivate()) 191 context.setFlag(Declaration.EXTERNAL_ACCESS); 192 } 193 } 194 } 195 196 protected Expression walkIfExp (IfExp exp) 197 { 198 boolean save = inTailContext; 199 try 200 { 201 inTailContext = false; 202 exp.test = (Expression) exp.test.walk(this); 203 } 204 finally 205 { 206 inTailContext = save; 207 } 208 exp.then_clause = (Expression) exp.then_clause.walk(this); 209 Expression else_clause = exp.else_clause; 210 if (else_clause != null) 211 exp.else_clause = (Expression) else_clause.walk(this); 212 return exp; 213 } 214 215 protected Expression walkLambdaExp (LambdaExp exp) 216 { 217 walkLambdaExp (exp, true); 218 return exp; 219 } 220 221 final void walkLambdaExp (LambdaExp exp, boolean canRead) 222 { 223 boolean save = inTailContext; 224 LambdaExp parent = currentLambda; 225 currentLambda = exp; 226 if (canRead) 227 exp.setCanRead(true); 228 try 229 { 230 inTailContext = false; 231 if (exp.defaultArgs != null) 232 exp.defaultArgs = walkExps(exp.defaultArgs); 233 inTailContext = exp.getInlineOnly() ? save : true; 234 if (exitValue == null && exp.body != null) 235 exp.body = (Expression) exp.body.walk(this); 236 } 237 finally 238 { 239 inTailContext = save; 240 currentLambda = parent; 241 } 242 243 walkDecls(exp); 244 245 for (LambdaExp child = exp.firstChild; child != null; 246 child = child.nextSibling) 247 { 248 if (child.getCanRead() 249 || child.isClassMethod() 250 || child.min_args != child.max_args) 251 child.flags |= LambdaExp.CANNOT_INLINE; 252 else 253 { 254 ApplyExp caller = child.returnContinuation; 255 if (caller != LambdaExp.unknownContinuation 256 && ! comp.usingCPStyle()) 257 { 258 child.setInlineOnly(true); 259 } 260 } 261 } 262 263 for (LambdaExp child = exp.firstChild; child != null; 264 child = child.nextSibling) 265 { 266 if ((child.flags & (LambdaExp.CANNOT_INLINE|LambdaExp.INLINE_ONLY))!=0) 267 continue; 268 294 } 295 } 296 297 301 protected Expression walkClassExp (ClassExp exp) 302 { 303 boolean save = inTailContext; 304 LambdaExp parent = currentLambda; 305 currentLambda = exp; 306 exp.setCanRead(true); 307 try 308 { 309 inTailContext = false; 310 for (LambdaExp child = exp.firstChild; 311 child != null && exitValue == null; child = child.nextSibling) 312 walkLambdaExp(child, false); 313 } 314 finally 315 { 316 inTailContext = save; 317 currentLambda = parent; 318 } 319 320 return exp; 321 } 322 323 protected Expression walkReferenceExp (ReferenceExp exp) 324 { 325 Declaration decl = Declaration.followAliases(exp.binding); 326 if (decl != null) 327 { 328 if (decl.type == Type.void_type) 333 return QuoteExp.voidExp; 334 decl.setCanRead(true); 335 } 336 Declaration ctx = exp.contextDecl(); 337 if (ctx != null) 338 ctx.setCanRead(true); 339 return exp; 340 } 341 342 final Expression walkSetExp (Declaration decl, Expression value) 343 { 344 if (decl != null && decl.getValue() == value 345 && value instanceof LambdaExp && ! (value instanceof ClassExp) 346 && ! decl.isPublic()) 347 { 348 LambdaExp lexp = (LambdaExp) value; 349 walkLambdaExp(lexp, false); 350 return lexp; 351 } 352 else 353 return (Expression) value.walk(this); 354 } 355 356 protected Expression walkSetExp (SetExp exp) 357 { 358 boolean save = inTailContext; 359 try 360 { 361 inTailContext = false; 362 Declaration decl = exp.binding; 363 if (decl != null && decl.isAlias()) 364 { 365 if (exp.isDefining()) 366 { 367 exp.new_value = (Expression) exp.new_value.walk(this); 368 return exp; 369 } 370 decl = Declaration.followAliases(decl); 371 } 372 if (decl != null) 373 decl.setCanWrite(); 374 Declaration ctx = exp.contextDecl(); 375 if (ctx != null) 376 ctx.setCanRead(true); 377 Expression value = walkSetExp(decl, exp.new_value); 378 if (decl != null && decl.context instanceof LetExp 379 && value == decl.getValue() 380 && (value instanceof LambdaExp || value instanceof QuoteExp)) 381 { 382 return QuoteExp.voidExp; 385 } 386 exp.new_value = value; 387 return exp; 388 } 389 finally 390 { 391 inTailContext = save; 392 } 393 } 394 395 protected Expression walkTryExp (TryExp exp) 396 { 397 boolean save = inTailContext; 398 try 399 { 400 inTailContext = false; 401 return super.walkTryExp(exp); 402 } 403 finally 404 { 405 inTailContext = save; 406 } 407 } 408 409 protected Expression walkSynchronizedExp (SynchronizedExp exp) 410 { 411 boolean save = inTailContext; 412 try 413 { 414 inTailContext = false; 415 return super.walkSynchronizedExp(exp); 416 } 417 finally 418 { 419 inTailContext = save; 420 } 421 } 422 } 423 | Popular Tags |