1 package gnu.expr; 2 import gnu.mapping.*; 3 import gnu.bytecode.*; 4 import gnu.mapping.Location; import gnu.text.*; 6 import java.io.*; 7 import gnu.kawa.reflect.StaticFieldLocation; 8 import java.net.URL ; 9 10 14 15 public class ModuleExp extends LambdaExp 16 implements Externalizable 17 { 18 public static final int EXPORT_SPECIFIED = LambdaExp.NEXT_AVAIL_FLAG; 19 public static final int STATIC_SPECIFIED = EXPORT_SPECIFIED << 1; 20 public static final int NONSTATIC_SPECIFIED = STATIC_SPECIFIED << 1; 21 public static final int SUPERTYPE_SPECIFIED = NONSTATIC_SPECIFIED << 1; 22 public static final int STATIC_RUN_SPECIFIED = SUPERTYPE_SPECIFIED << 1; 23 public static final int LAZY_DECLARATIONS = STATIC_RUN_SPECIFIED << 1; 24 public static final int IMMEDIATE = LAZY_DECLARATIONS << 1; 25 26 public String getJavaName () 27 { 28 String name = getName(); 29 return name == null ? "lambda" : Compilation.mangleName(name, 0); 30 } 31 32 public ModuleExp () 33 { 34 } 35 36 37 public static String dumpZipPrefix; 38 39 static int lastZipCounter; 40 41 48 public static int interactiveCounter; 49 50 public static Class evalToClass (Compilation comp, URL url) 51 { 52 ModuleExp mexp = comp.getModule(); 53 SourceMessages messages = comp.getMessages(); 54 try 55 { 56 ArrayClassLoader loader = new ArrayClassLoader (); 57 if (url == null) 58 { 59 CallContext ctx = CallContext.getInstance(); 60 String base = ctx.getBaseUri(); 61 url = URI_utils.toURL(base); 62 } 63 loader.setResourceContext(url); 64 comp.loader = loader; 65 66 comp.minfo.loadByStages(Compilation.COMPILED); 67 68 if (messages.seenErrors()) 69 return null; 70 71 java.util.zip.ZipOutputStream zout = null; 72 if (dumpZipPrefix != null) 73 { 74 StringBuffer zipname = new StringBuffer (dumpZipPrefix); 75 76 lastZipCounter++; 77 if (interactiveCounter > lastZipCounter) 78 lastZipCounter = interactiveCounter; 79 zipname.append(lastZipCounter); 80 zipname.append(".zip"); 81 java.io.FileOutputStream zfout 82 = new java.io.FileOutputStream (zipname.toString()); 83 zout = new java.util.zip.ZipOutputStream (zfout); 84 } 85 86 for (int iClass = 0; iClass < comp.numClasses; iClass++) 87 { 88 ClassType clas = comp.classes[iClass]; 89 String className = clas.getName (); 90 byte[] classBytes = clas.writeToArray (); 91 loader.addClass(className, classBytes); 92 clas.cleanupAfterCompilation(); 94 95 if (zout != null) 96 { 97 String clname = className.replace ('.', '/') + ".class"; 98 java.util.zip.ZipEntry zent 99 = new java.util.zip.ZipEntry (clname); 100 zent.setSize(classBytes.length); 101 java.util.zip.CRC32 crc = new java.util.zip.CRC32 (); 102 crc.update(classBytes); 103 zent.setCrc(crc.getValue()); 104 zent.setMethod(java.util.zip.ZipEntry.STORED); 105 zout.putNextEntry(zent); 106 zout.write(classBytes); 107 } 108 } 109 if (zout != null) 110 { 111 zout.close (); 112 } 113 114 118 119 Class clas = null; 120 for (int iClass = 0; iClass < comp.numClasses; iClass++) 121 { 122 ClassType ctype = comp.classes[iClass]; 123 Class cclass = loader.loadClass(ctype.getName(), false); 124 ctype.setReflectClass(cclass); 125 ctype.setExisting(true); 126 if (iClass == 0) 127 clas = cclass; 128 } 129 130 ModuleInfo minfo = comp.minfo; 131 minfo.moduleClass = clas; 132 int ndeps = minfo.numDependencies; 133 134 for (int idep = 0; idep < ndeps; idep++) 135 { 136 ModuleInfo dep = minfo.dependencies[idep]; 137 if (dep.moduleClass == null) 138 dep.moduleClass = evalToClass(dep.comp, null); 139 comp.loader.addClass(dep.moduleClass); 140 } 141 142 return clas; 143 } 144 catch (java.io.IOException ex) 145 { 146 throw new WrappedException("I/O error in lambda eval", ex); 147 } 148 catch (ClassNotFoundException ex) 149 { 150 throw new WrappedException("class not found in lambda eval", ex); 151 } 152 catch (Throwable ex) 153 { 154 comp.error('f', "internal compile error - caught "+ex); 155 throw WrappedException.wrapIfNeeded(ex); 156 } 157 } 158 159 160 public static boolean alwaysCompile = false; 161 162 public final static boolean evalModule (Environment env, CallContext ctx, 163 Compilation comp, URL url, 164 OutPort msg) 165 throws Throwable 166 { 167 comp.getLanguage().resolve(comp); 168 ModuleExp mexp = comp.getModule(); 169 Environment orig_env = Environment.getCurrent(); 170 Compilation orig_comp = Compilation.getCurrent(); 171 SourceMessages messages = comp.getMessages(); 172 ClassLoader savedLoader = null; 173 Thread thread = null; try 175 { 176 if (env != orig_env) 177 Environment.setCurrent(env); 178 if (comp != orig_comp) 179 Compilation.setCurrent(comp); 180 181 if (alwaysCompile || comp.mustCompile) 182 comp.addMainClass(mexp); 183 184 comp.walkModule(mexp); 185 comp.setState(Compilation.WALKED); 186 187 if (msg != null ? messages.checkErrors(msg, 20) : messages.seenErrors()) 188 return false; 189 190 if (! alwaysCompile && ! comp.mustCompile) 191 { if (Compilation.debugPrintFinalExpr) 193 { 194 msg.println ("[Evaluating final module \""+mexp.getName()+"\":"); 195 mexp.print(msg); 196 msg.println(']'); 197 msg.flush(); 198 } 199 mexp.body.apply(ctx); 200 } 201 else 202 { 203 if (comp.mainClass == null) 204 comp.addMainClass(mexp); 205 206 try 207 { 208 Class clas = evalToClass(comp, url); 209 if (clas == null) 210 return false; 211 try 212 { 213 thread = Thread.currentThread(); 214 savedLoader = thread.getContextClassLoader(); 215 thread.setContextClassLoader(clas.getClassLoader()); 216 } 217 catch (Throwable ex) 218 { 219 thread = null; 220 } 221 222 Object inst; 223 try 224 { 225 inst = clas.getDeclaredField("$instance").get(null); 226 } 227 catch (NoSuchFieldException ex) 228 { 229 inst = clas.newInstance(); 230 } 231 232 for (Declaration decl = mexp.firstDecl(); 234 decl != null; decl = decl.nextDecl()) 235 { 236 Object dname = decl.getSymbol(); 237 if (decl.isPrivate() || dname == null) 238 continue; 239 Field fld = decl.field; 240 Symbol sym = dname instanceof Symbol ? (Symbol) dname 241 : Symbol.make("", dname.toString().intern()); 242 Object property = comp.getLanguage() 243 .getEnvPropertyFor(decl); 244 Expression dvalue = decl.getValue(); 248 if (decl.getFlag(Declaration.PROCEDURE|Declaration.IS_CONSTANT|Declaration.INDIRECT_BINDING) 249 && ! (dvalue instanceof ReferenceExp 250 && ((ReferenceExp) dvalue).getBinding().needsContext())) 251 { 252 Object value; 253 if (dvalue instanceof QuoteExp 254 && dvalue != QuoteExp.undefined_exp) 255 value = ((QuoteExp) dvalue).getValue(); 256 else 257 value = decl.field.getReflectField().get(null); 258 if (decl.isIndirectBinding()) 259 env.addLocation(sym, property, (Location) value); 260 else 261 env.define(sym, property, value); 262 } 264 else 265 { 266 StaticFieldLocation loc 267 = new StaticFieldLocation(fld.getDeclaringClass(), 268 fld.getName()); 269 loc.setDeclaration(decl); 270 env.addLocation(sym, property, loc); 271 } 272 } 273 if (msg != null ? messages.checkErrors(msg, 20) 274 : messages.seenErrors()) 275 return false; 276 if (inst instanceof ModuleBody) 277 ((ModuleBody) inst).run(ctx); 278 } 279 catch (IllegalAccessException ex) 280 { 281 throw new RuntimeException ("class illegal access: in lambda eval"); 282 } 283 } 284 ctx.runUntilDone(); 285 } 286 finally 287 { 288 if (env != orig_env) 289 Environment.setCurrent(orig_env); 290 if (comp != orig_comp) 291 Compilation.setCurrent(orig_comp); 292 if (thread != null) 293 thread.setContextClassLoader(savedLoader); 294 } 295 return true; 296 } 297 298 ClassType superType; 299 ClassType[] interfaces; 300 301 ModuleInfo info; 302 303 public final ClassType getSuperType() { return superType; } 304 public final void setSuperType(ClassType s) { superType = s; } 305 public final ClassType[] getInterfaces() { return interfaces; } 306 public final void setInterfaces(ClassType[] s) { interfaces = s; } 307 308 public final boolean isStatic () 309 { 310 return (getFlag(STATIC_SPECIFIED) 313 || ((gnu.expr.Compilation.moduleStatic > 0 314 || getFlag(IMMEDIATE)) 315 && ! getFlag(SUPERTYPE_SPECIFIED) 316 && ! getFlag(NONSTATIC_SPECIFIED))); 317 } 318 319 320 public boolean staticInitRun () 321 { 322 return (isStatic() 323 && (getFlag(STATIC_RUN_SPECIFIED) 324 || Compilation.moduleStatic == 2)); 325 } 326 327 public void allocChildClasses (Compilation comp) 328 { 329 declareClosureEnv(); 330 if (! comp.usingCPStyle()) 331 return; 332 allocFrame(comp); 333 } 334 335 void allocFields (Compilation comp) 336 { 337 for (Declaration decl = firstDecl(); 344 decl != null; decl = decl.nextDecl()) 345 { 346 if ((decl.isSimple() && ! decl.isPublic()) || decl.field != null) 347 continue; 348 if (decl.getFlag(Declaration.IS_UNKNOWN) 349 && decl.getFlag(Declaration.CAN_READ|Declaration.CAN_CALL)) 352 decl.makeField(comp, null); 353 } 354 for (Declaration decl = firstDecl(); 355 decl != null; decl = decl.nextDecl()) 356 { 357 if (decl.field != null) 358 continue; 359 Expression value = decl.getValue(); 360 if (((decl.isSimple() && ! decl.isPublic())) 361 && ! decl.isNamespaceDecl() 363 && ! (decl.getFlag(Declaration.IS_CONSTANT) 364 && decl.getFlag(Declaration.CAN_READ|Declaration.CAN_CALL)) 365 && ! (value instanceof ClassExp)) 366 continue; 367 if (decl.getFlag(Declaration.IS_UNKNOWN)) 368 continue; 369 if (value instanceof ModuleExp) continue; 371 if (value instanceof LambdaExp && ! (value instanceof ClassExp)) 372 { 373 ((LambdaExp) value).allocFieldFor(comp); 374 } 375 else 376 { 377 if (! (decl.getFlag(Declaration.IS_CONSTANT) || decl.isAlias()) 378 || value == QuoteExp.undefined_exp) 379 value = null; 380 decl.makeField(comp, value); 381 } 382 } 383 } 384 385 protected Expression walk (ExpWalker walker) 386 { 387 return walker.walkModuleExp(this); 388 } 389 390 public void print (OutPort out) 391 { 392 out.startLogicalBlock("(Module/", ")", 2); 393 Object sym = getSymbol(); 394 if (sym != null) 395 { 396 out.print(sym); 397 out.print('/'); 398 } 399 out.print(id); 400 out.print('/'); 401 out.writeSpaceFill(); 402 out.startLogicalBlock("(", false, ")"); 403 Declaration decl = firstDecl(); 404 if (decl != null) 405 { 406 out.print("Declarations:"); 407 for (; decl != null; decl = decl.nextDecl()) 408 { 409 out.writeSpaceFill(); 410 decl.printInfo(out); 411 } 412 } 413 out.endLogicalBlock(")"); 414 out.writeSpaceLinear(); 415 if (body == null) 416 out.print("<null body>"); 417 else 418 body.print (out); 419 out.endLogicalBlock(")"); 420 } 421 422 public Declaration firstDecl () 423 { 424 synchronized (this) 425 { 426 if (getFlag(LAZY_DECLARATIONS)) 427 info.setupModuleExp(); 428 } 429 return decls; 430 } 431 432 435 public ClassType classFor (Compilation comp) 436 { 437 if (type != null && type != Compilation.typeProcedure) 438 return (ClassType) type; 439 String fileName = getFileName(); 440 File file = null; 441 String mname = getName(); 442 if (mname != null) 443 fileName = mname; 444 else if (fileName == null) 445 { 446 fileName = getName(); 447 if (fileName == null) 448 fileName = "$unnamed_input_file$"; 449 } 450 else if (filename.equals("-") || filename.equals("<stdin>")) 451 { 452 fileName = getName(); 453 if (fileName == null) 454 fileName = "$stdin$"; 455 } 456 else 457 { 458 file = new File(fileName); 459 fileName = file.getName(); 460 int dotIndex = fileName.lastIndexOf('.'); 461 if (dotIndex > 0) 462 fileName = fileName.substring (0, dotIndex); 463 } 464 String parent; 465 String className; 466 if (getName() == null) 467 setName(fileName); 468 fileName = Compilation.mangleNameIfNeeded(fileName); 469 if (comp.classPrefix.length() == 0 470 && file != null 471 && ! file.isAbsolute() 472 && (parent = file.getParent()) != null 473 && parent.length() > 0 && parent.indexOf("..") < 0) 475 { 476 parent = parent.replaceAll(System.getProperty("file.separator"), "/"); 477 if (parent.startsWith("./")) 478 parent = parent.substring(2); 479 className = parent.equals(".") ? fileName 480 : Compilation.mangleURI(parent) + "." + fileName; 481 } 482 else 483 className = comp.classPrefix + fileName; 484 ClassType clas = new ClassType(className); 485 setType(clas); 486 if (comp.mainLambda == this) 487 { 488 if (comp.mainClass == null) 489 comp.mainClass = clas; 490 else if (! className.equals(comp.mainClass.getName())) 491 comp.error('e', "inconsistent main class name: "+className 492 +" - old name: "+comp.mainClass.getName()); 493 } 494 return clas; 495 } 496 497 public void writeExternal(ObjectOutput out) throws IOException 498 { 499 String name = null; 500 if (type != null && type != Compilation.typeProcedure 501 && ! type.isExisting()) 502 out.writeObject(type); 506 else 507 { 508 if (name == null) 509 name = getName(); 510 if (name == null) 511 name = getFileName(); 512 out.writeObject(name); 513 } 514 } 515 516 public void readExternal(ObjectInput in) 517 throws IOException, ClassNotFoundException 518 { 519 Object name = in.readObject(); 520 if (name instanceof ClassType) 521 { 522 type = (ClassType) name; 523 setName(type.getName()); 524 } 525 else 526 setName((String ) name); 527 flags |= LAZY_DECLARATIONS; 528 } 529 } 530 | Popular Tags |