1 3 package org.python.compiler; 4 5 import java.io.*; 6 import java.util.*; 7 import org.python.parser.*; 8 import org.python.parser.ast.*; 9 import org.python.core.Py; 10 import org.python.core.PyException; 11 12 class PyIntegerConstant extends Constant implements ClassConstants 13 { 14 int value; 15 16 public PyIntegerConstant(int value) { 17 this.value = value; 18 } 19 20 public void get(Code c) throws IOException { 21 c.getstatic(module.classfile.name, name, $pyInteger); 22 } 23 24 public void put(Code c) throws IOException { 25 module.classfile.addField(name, $pyInteger, access); 26 c.iconst(value); 27 int mref_newInteger = c.pool.Methodref( 28 "org/python/core/Py", 29 "newInteger", 30 "(I)" + $pyInteger); 31 c.invokestatic(mref_newInteger); 32 c.putstatic(module.classfile.name, name, $pyInteger); 33 } 34 35 public int hashCode() { 36 return value; 37 } 38 39 public boolean equals(Object o) { 40 if (o instanceof PyIntegerConstant) 41 return ((PyIntegerConstant)o).value == value; 42 else 43 return false; 44 } 45 } 46 47 class PyFloatConstant extends Constant implements ClassConstants 48 { 49 double value; 50 51 public PyFloatConstant(double value) { 52 this.value = value; 53 } 54 55 public void get(Code c) throws IOException { 56 c.getstatic(module.classfile.name, name, $pyFloat); 57 } 58 59 public void put(Code c) throws IOException { 60 module.classfile.addField(name, $pyFloat, access); 61 c.ldc(c.pool.Double(value)); 62 int mref_newFloat = c.pool.Methodref("org/python/core/Py", 63 "newFloat", 64 "(D)" + $pyFloat); 65 c.invokestatic(mref_newFloat); 66 c.putstatic(module.classfile.name, name, $pyFloat); 67 } 68 69 public int hashCode() { 70 return (int)value; 71 } 72 73 public boolean equals(Object o) { 74 if (o instanceof PyFloatConstant) 75 return ((PyFloatConstant)o).value == value; 76 else 77 return false; 78 } 79 } 80 81 class PyComplexConstant extends Constant implements ClassConstants 82 { 83 double value; 84 85 public PyComplexConstant(double value) { 86 this.value = value; 87 } 88 89 public void get(Code c) throws IOException { 90 c.getstatic(module.classfile.name, name, $pyComplex); 91 } 92 93 public void put(Code c) throws IOException { 94 module.classfile.addField(name, $pyComplex, access); 95 c.ldc(c.pool.Double(value)); 96 int mref_newImaginary = c.pool.Methodref( 97 "org/python/core/Py", 98 "newImaginary", 99 "(D)" + $pyComplex); 100 c.invokestatic(mref_newImaginary); 101 c.putstatic(module.classfile.name, name, $pyComplex); 102 } 103 104 public int hashCode() { 105 return (int)value; 106 } 107 108 public boolean equals(Object o) { 109 if (o instanceof PyComplexConstant) 110 return ((PyComplexConstant)o).value == value; 111 else 112 return false; 113 } 114 } 115 116 class PyStringConstant extends Constant implements ClassConstants 117 { 118 String value; 119 120 public PyStringConstant(String value) { 121 this.value = value; 122 } 123 124 public void get(Code c) throws IOException { 125 c.getstatic(module.classfile.name, name, $pyStr); 126 } 127 128 public void put(Code c) throws IOException { 129 module.classfile.addField(name, $pyStr, access); 130 c.ldc(value); 131 int mref_newString = c.pool.Methodref( 132 "org/python/core/Py", 133 "newString", 134 "(" + $str + ")" + $pyStr); 135 c.invokestatic(mref_newString); 136 c.putstatic(module.classfile.name, name, $pyStr); 137 } 138 139 public int hashCode() { 140 return value.hashCode(); 141 } 142 143 public boolean equals(Object o) { 144 if (o instanceof PyStringConstant) 145 return ((PyStringConstant)o).value.equals(value); 146 else 147 return false; 148 } 149 } 150 151 class PyLongConstant extends Constant implements ClassConstants 152 { 153 String value; 154 155 public PyLongConstant(String value) { 156 this.value = value; 157 } 158 159 public void get(Code c) throws IOException { 160 c.getstatic(module.classfile.name, name, $pyLong); 161 } 162 163 public void put(Code c) throws IOException { 164 module.classfile.addField(name, $pyLong, access); 165 c.ldc(value); 166 int mref_newLong = c.pool.Methodref( 167 "org/python/core/Py", 168 "newLong", 169 "(" + $str + ")" + $pyLong); 170 c.invokestatic(mref_newLong); 171 c.putstatic(module.classfile.name, name, $pyLong); 172 } 173 174 public int hashCode() { 175 return value.hashCode(); 176 } 177 178 public boolean equals(Object o) { 179 if (o instanceof PyLongConstant) 180 return ((PyLongConstant)o).value.equals(value); 181 else return false; 182 } 183 } 184 185 class PyCodeConstant extends Constant implements ClassConstants 186 { 187 public String co_name; 188 public int argcount; 189 public String [] names; 190 public int id; 191 public int co_firstlineno; 192 public boolean arglist, keywordlist; 193 String fname; 194 195 public String [] cellvars; 197 public String [] freevars; 198 public int jy_npurecell; 199 200 public int moreflags; 201 202 public PyCodeConstant() { ; 203 } 204 205 public void get(Code c) throws IOException { 206 c.getstatic(module.classfile.name, name, $pyCode); 207 } 208 209 public void put(Code c) throws IOException { 210 module.classfile.addField(name, $pyCode, access); 211 c.iconst(argcount); 212 213 if (names != null) { 215 CodeCompiler.makeStrings(c, names, names.length); 216 } else { CodeCompiler.makeStrings(c, null, 0); 218 } 219 220 c.ldc(((PyStringConstant)module.filename).value); 221 c.ldc(co_name); 222 c.iconst(co_firstlineno); 223 224 c.iconst(arglist ? 1 : 0); 225 c.iconst(keywordlist ? 1 : 0); 226 227 int mref_self = c.pool.Fieldref(module.classfile.name, 228 "self", 229 "L"+module.classfile.name+";"); 230 c.getstatic(mref_self); 231 233 c.iconst(id); 234 235 if (cellvars != null) 236 CodeCompiler.makeStrings(c, cellvars, cellvars.length); 237 else 238 c.aconst_null(); 239 if (freevars != null) 240 CodeCompiler.makeStrings(c, freevars, freevars.length); 241 else 242 c.aconst_null(); 243 244 c.iconst(jy_npurecell); 245 246 c.iconst(moreflags); 247 248 int mref_newCode = c.pool.Methodref( 249 "org/python/core/Py", 250 "newCode", 251 "(I" + $strArr + $str + $str + "IZZ" + $pyFuncTbl + "I" + 252 $strArr + $strArr + "II)" + $pyCode); 253 254 c.invokestatic(mref_newCode); 255 c.putstatic(module.classfile.name, name, $pyCode); 257 } 258 } 259 260 public class Module implements ClassConstants, CompilationContext 261 { 262 ClassFile classfile; 263 Constant filename; 264 String sfilename; 265 public Constant mainCode; 266 public boolean linenumbers; 267 public boolean setFile=true; 268 Future futures; 269 Hashtable scopes; 270 271 public Module(String name, String filename, boolean linenumbers) { 272 this.linenumbers = linenumbers; 273 classfile = new ClassFile(name, "org/python/core/PyFunctionTable", 274 ClassFile.SYNCHRONIZED | ClassFile.PUBLIC); 275 constants = new Hashtable(); 276 sfilename = filename; 277 if (filename != null) 278 this.filename = PyString(filename); 279 else 280 this.filename = null; 281 codes = new Vector(); 282 futures = new Future(); 283 scopes = new Hashtable(); 284 } 285 286 public Module(String name) { 287 this(name, name+".py", true); 288 } 289 290 Hashtable constants; 292 293 private Constant findConstant(Constant c) { 294 Constant ret = (Constant)constants.get(c); 295 if (ret != null) 296 return ret; 297 ret = c; 298 c.module = this; 299 c.name = "_"+constants.size(); 301 constants.put(ret, ret); 302 return ret; 303 } 304 305 public Constant PyInteger(int value) { 306 return findConstant(new PyIntegerConstant(value)); 307 } 308 309 public Constant PyFloat(double value) { 310 return findConstant(new PyFloatConstant(value)); 311 } 312 313 public Constant PyComplex(double value) { 314 return findConstant(new PyComplexConstant(value)); 315 } 316 317 public Constant PyString(String value) { 318 return findConstant(new PyStringConstant(value)); 319 } 320 public Constant PyLong(String value) { 321 return findConstant(new PyLongConstant(value)); 322 } 323 324 345 346 Vector codes; 347 private boolean isJavaIdentifier(String s) { 348 char[] chars = s.toCharArray(); 349 if (chars.length == 0) 350 return false; 351 if (!Character.isJavaIdentifierStart(chars[0])) 352 return false; 353 354 for(int i=1; i<chars.length; i++) { 355 if (!Character.isJavaIdentifierPart(chars[i])) 356 return false; 357 } 358 return true; 359 } 360 361 private static final String [] emptyStringAr = new String [0]; 362 363 private String [] toNameAr(Vector names,boolean nullok) { 364 int sz = names.size(); 365 if (sz ==0 && nullok) return null; 366 String [] nameArray = new String [sz]; 367 names.copyInto(nameArray); 368 return nameArray; 369 } 370 371 372 private int to_cell; 373 374 public PyCodeConstant PyCode(modType tree, String name, 375 boolean fast_locals, String className, 376 boolean classBody, boolean printResults, 377 int firstlineno, ScopeInfo scope) 378 throws Exception 379 { 380 return PyCode(tree,name,fast_locals,className,classBody, 381 printResults,firstlineno,scope,null); 382 } 383 384 385 public PyCodeConstant PyCode(modType tree, String name, 386 boolean fast_locals, String className, 387 boolean classBody, boolean printResults, 388 int firstlineno, 389 ScopeInfo scope, 390 org.python.core.CompilerFlags cflags) 391 throws Exception 392 { 393 PyCodeConstant code = new PyCodeConstant(); 394 ArgListCompiler ac = (scope != null)?scope.ac:null; 395 396 if (ac != null) { 397 code.arglist = ac.arglist; 398 code.keywordlist = ac.keywordlist; 399 code.argcount = ac.names.size(); 400 } 401 402 code.co_name = name; 403 code.co_firstlineno = firstlineno; 404 code.id = codes.size(); 405 406 if (isJavaIdentifier(name)) 408 code.fname = name+"$"+code.id; 409 else 410 code.fname = "f$"+code.id; 411 412 codes.addElement(code); 413 414 Code c = classfile.addMethod( 415 code.fname, 416 "(" + $pyFrame + ")" + $pyObj, 417 ClassFile.PUBLIC); 418 419 CodeCompiler compiler = new CodeCompiler(this, printResults); 420 421 Label genswitch = c.getLabel(); 422 if (scope.generator) { 423 c.goto_(genswitch); 424 } 425 Label start = c.getLabel(); 426 start.setPosition(); 427 428 if (ac != null && ac.init_code.size() > 0) { 430 ac.appendInitCode((Suite) tree); 431 } 432 433 if (scope != null) { 434 int nparamcell = scope.jy_paramcells.size(); 435 if (nparamcell > 0) { 436 if (to_cell == 0) { 437 to_cell = classfile.pool.Methodref("org/python/core/PyFrame", 438 "to_cell","(II)V"); 439 } 440 Hashtable tbl = scope.tbl; 441 Vector paramcells = scope.jy_paramcells; 442 for (int i = 0; i < nparamcell; i++) { 443 c.aload(1); 444 SymInfo syminf = (SymInfo)tbl.get(paramcells.elementAt(i)); 445 c.iconst(syminf.locals_index); 446 c.iconst(syminf.env_index); 447 c.invokevirtual(to_cell); 448 } 449 } 450 } 451 452 compiler.parse(tree, c, fast_locals, className, classBody, 453 scope, cflags); 454 455 if (scope.generator) { 456 genswitch.setPosition(); 457 c.aload(1); 458 if (compiler.f_lasti == 0) { 459 compiler.f_lasti = c.pool.Fieldref( 460 "org/python/core/PyFrame", "f_lasti", "I"); 461 } 462 c.getfield(compiler.f_lasti); 463 464 Label[] yields = new Label[compiler.yields.size()+1]; 465 466 yields[0] = start; 467 for (int i = 1; i < yields.length; i++) { 468 yields[i] = (Label) compiler.yields.elementAt(i-1); 469 } 470 c.tableswitch(start, 0, yields); 471 } 473 474 if (!classBody) code.names = toNameAr(compiler.names,false); 476 477 if (scope != null) { 478 code.cellvars = toNameAr(scope.cellvars,true); 479 code.freevars = toNameAr(scope.freevars,true); 480 code.jy_npurecell = scope.jy_npurecell; 481 } 482 483 if (compiler.optimizeGlobals) { 484 code.moreflags |= org.python.core.PyTableCode.CO_OPTIMIZED; 485 } 486 if (compiler.my_scope.generator) { 487 code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR; 488 } 489 if (cflags != null) { 490 if (cflags.generator_allowed) { 491 code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR_ALLOWED; 492 } 493 if (cflags.division) { 494 code.moreflags |= org.python.core.PyTableCode.CO_FUTUREDIVISION; 495 } 496 } 497 498 code.module = this; 499 code.name = code.fname; 500 return code; 501 } 502 503 public void addInit() throws IOException { 505 Code c = classfile.addMethod("<init>", "()V", ClassFile.PUBLIC); 506 c.aload(0); 507 c.invokespecial(c.pool.Methodref("org/python/core/PyFunctionTable", 508 "<init>", 509 "()V")); 510 c.return_(); 511 } 512 513 public void addRunnable() throws IOException { 514 Code c = classfile.addMethod("getMain", 515 "()" + $pyCode, 516 ClassFile.PUBLIC); 517 mainCode.get(c); 518 c.areturn(); 519 } 520 521 public void addMain() throws IOException { 522 Code c = classfile.addMethod("main", "(" + $str + ")V", 523 ClassFile.PUBLIC | ClassFile.STATIC); 524 525 526 int mref_self = c.pool.Fieldref(classfile.name, 527 "self", 528 "L"+classfile.name+";"); 529 c.getstatic(mref_self); 530 c.aload(0); 531 c.invokestatic(c.pool.Methodref( 532 "org/python/core/Py", 533 "do_main", 534 "(" + $pyRunnable + $strArr + ")V")); 535 c.return_(); 536 } 537 538 public void addConstants() throws IOException { 539 Code c = classfile.addMethod("<clinit>", "()V", ClassFile.STATIC); 540 541 classfile.addField("self", "L"+classfile.name+";", 542 ClassFile.STATIC|ClassFile.FINAL); 543 c.new_(c.pool.Class(classfile.name)); 544 c.dup(); 545 c.invokespecial(c.pool.Methodref(classfile.name, "<init>", "()V")); 546 c.putstatic(c.pool.Fieldref(classfile.name, 547 "self", 548 "L"+classfile.name+";")); 549 550 Enumeration e = constants.elements(); 551 552 while (e.hasMoreElements()) { 553 Constant constant = (Constant)e.nextElement(); 554 constant.put(c); 555 } 556 557 for(int i=0; i<codes.size(); i++) { 558 PyCodeConstant pyc = (PyCodeConstant)codes.elementAt(i); 559 pyc.put(c); 560 } 561 562 c.return_(); 563 } 564 565 public void addFunctions() throws IOException { 566 Code code = classfile.addMethod( 567 "call_function", 568 "(I" + $pyFrame + ")" + $pyObj, 569 ClassFile.PUBLIC); 570 571 Label def = code.getLabel(); 572 Label[] labels = new Label[codes.size()]; 573 int i; 574 for(i=0; i<labels.length; i++) 575 labels[i] = code.getLabel(); 576 577 code.iload(1); 579 580 code.tableswitch(def, 0, labels); 581 for(i=0; i<labels.length; i++) { 582 labels[i].setPosition(); 583 code.aload(0); 584 code.aload(2); 585 code.invokevirtual( 586 classfile.name, 587 ((PyCodeConstant)codes.elementAt(i)).fname, 588 "(" + $pyFrame + ")" + $pyObj); 589 code.areturn(); 590 } 591 def.setPosition(); 592 593 code.aconst_null(); 595 code.areturn(); 596 597 } 598 599 public void write(OutputStream stream) throws IOException { 600 addInit(); 601 addRunnable(); 602 604 addConstants(); 605 addFunctions(); 606 607 classfile.addInterface("org/python/core/PyRunnable"); 608 if (sfilename != null) { 609 classfile.addAttribute(new SourceFile(sfilename, classfile.pool)); 610 } 611 classfile.addAttribute(new APIVersion(org.python.core.imp.APIVersion, 612 classfile.pool)); 613 classfile.write(stream); 614 } 615 616 public Future getFutures() { return futures; } 618 619 public String getFilename() { return sfilename; } 620 621 public ScopeInfo getScopeInfo(SimpleNode node) { 622 return (ScopeInfo) scopes.get(node); 623 } 624 625 public void error(String msg,boolean err,SimpleNode node) 626 throws Exception 627 { 628 if (!err) { 629 try { 630 Py.warning(Py.SyntaxWarning, msg, 631 (sfilename != null) ? sfilename : "?", 632 node.beginLine ,null, Py.None); 633 return; 634 } catch(PyException e) { 635 if (!Py.matchException(e, Py.SyntaxWarning)) 636 throw e; 637 } 638 } 639 throw new ParseException(msg,node); 640 } 641 642 public static void compile(modType node, OutputStream ostream, 643 String name, String filename, 644 boolean linenumbers, boolean printResults, 645 boolean setFile, 646 org.python.core.CompilerFlags cflags) 647 throws Exception 648 { 649 Module module = new Module(name, filename, linenumbers); 650 module.setFile = setFile; 651 module.futures.preprocessFutures(node, cflags); 652 new ScopesCompiler(module, module.scopes).parse(node); 653 654 657 Constant main = module.PyCode(node, "?", false, null, false, 658 printResults, 0, 659 module.getScopeInfo(node), 660 cflags); 661 module.mainCode = main; 662 module.write(ostream); 663 } 664 } 665 | Popular Tags |