001: // Copyright (c) Corporation for National Research Initiatives
002:
003: package org.python.compiler;
004:
005: import java.io.*;
006: import java.util.*;
007: import org.python.parser.*;
008: import org.python.parser.ast.*;
009: import org.python.core.Py;
010: import org.python.core.PyException;
011:
012: class PyIntegerConstant extends Constant implements ClassConstants {
013: int value;
014:
015: public PyIntegerConstant(int value) {
016: this .value = value;
017: }
018:
019: public void get(Code c) throws IOException {
020: c.getstatic(module.classfile.name, name, $pyInteger);
021: }
022:
023: public void put(Code c) throws IOException {
024: module.classfile.addField(name, $pyInteger, access);
025: c.iconst(value);
026: int mref_newInteger = c.pool.Methodref("org/python/core/Py",
027: "newInteger", "(I)" + $pyInteger);
028: c.invokestatic(mref_newInteger);
029: c.putstatic(module.classfile.name, name, $pyInteger);
030: }
031:
032: public int hashCode() {
033: return value;
034: }
035:
036: public boolean equals(Object o) {
037: if (o instanceof PyIntegerConstant)
038: return ((PyIntegerConstant) o).value == value;
039: else
040: return false;
041: }
042: }
043:
044: class PyFloatConstant extends Constant implements ClassConstants {
045: double value;
046:
047: public PyFloatConstant(double value) {
048: this .value = value;
049: }
050:
051: public void get(Code c) throws IOException {
052: c.getstatic(module.classfile.name, name, $pyFloat);
053: }
054:
055: public void put(Code c) throws IOException {
056: module.classfile.addField(name, $pyFloat, access);
057: c.ldc(c.pool.Double(value));
058: int mref_newFloat = c.pool.Methodref("org/python/core/Py",
059: "newFloat", "(D)" + $pyFloat);
060: c.invokestatic(mref_newFloat);
061: c.putstatic(module.classfile.name, name, $pyFloat);
062: }
063:
064: public int hashCode() {
065: return (int) value;
066: }
067:
068: public boolean equals(Object o) {
069: if (o instanceof PyFloatConstant)
070: return ((PyFloatConstant) o).value == value;
071: else
072: return false;
073: }
074: }
075:
076: class PyComplexConstant extends Constant implements ClassConstants {
077: double value;
078:
079: public PyComplexConstant(double value) {
080: this .value = value;
081: }
082:
083: public void get(Code c) throws IOException {
084: c.getstatic(module.classfile.name, name, $pyComplex);
085: }
086:
087: public void put(Code c) throws IOException {
088: module.classfile.addField(name, $pyComplex, access);
089: c.ldc(c.pool.Double(value));
090: int mref_newImaginary = c.pool.Methodref("org/python/core/Py",
091: "newImaginary", "(D)" + $pyComplex);
092: c.invokestatic(mref_newImaginary);
093: c.putstatic(module.classfile.name, name, $pyComplex);
094: }
095:
096: public int hashCode() {
097: return (int) value;
098: }
099:
100: public boolean equals(Object o) {
101: if (o instanceof PyComplexConstant)
102: return ((PyComplexConstant) o).value == value;
103: else
104: return false;
105: }
106: }
107:
108: class PyStringConstant extends Constant implements ClassConstants {
109: String value;
110:
111: public PyStringConstant(String value) {
112: this .value = value;
113: }
114:
115: public void get(Code c) throws IOException {
116: c.getstatic(module.classfile.name, name, $pyStr);
117: }
118:
119: public void put(Code c) throws IOException {
120: module.classfile.addField(name, $pyStr, access);
121: c.ldc(value);
122: int mref_newString = c.pool.Methodref("org/python/core/Py",
123: "newString", "(" + $str + ")" + $pyStr);
124: c.invokestatic(mref_newString);
125: c.putstatic(module.classfile.name, name, $pyStr);
126: }
127:
128: public int hashCode() {
129: return value.hashCode();
130: }
131:
132: public boolean equals(Object o) {
133: if (o instanceof PyStringConstant)
134: return ((PyStringConstant) o).value.equals(value);
135: else
136: return false;
137: }
138: }
139:
140: class PyUnicodeConstant extends Constant implements ClassConstants {
141: String value;
142:
143: public PyUnicodeConstant(String value) {
144: this .value = value;
145: }
146:
147: public void get(Code c) throws IOException {
148: c.getstatic(module.classfile.name, name, $pyUnicode);
149: }
150:
151: public void put(Code c) throws IOException {
152: module.classfile.addField(name, $pyUnicode, access);
153: c.ldc(value);
154: int mref_newString = c.pool.Methodref("org/python/core/Py",
155: "newUnicode", "(" + $str + ")" + $pyUnicode);
156: c.invokestatic(mref_newString);
157: c.putstatic(module.classfile.name, name, $pyUnicode);
158: }
159:
160: public int hashCode() {
161: return value.hashCode();
162: }
163:
164: public boolean equals(Object o) {
165: if (o instanceof PyUnicodeConstant)
166: return ((PyUnicodeConstant) o).value.equals(value);
167: else
168: return false;
169: }
170: }
171:
172: class PyLongConstant extends Constant implements ClassConstants {
173: String value;
174:
175: public PyLongConstant(String value) {
176: this .value = value;
177: }
178:
179: public void get(Code c) throws IOException {
180: c.getstatic(module.classfile.name, name, $pyLong);
181: }
182:
183: public void put(Code c) throws IOException {
184: module.classfile.addField(name, $pyLong, access);
185: c.ldc(value);
186: int mref_newLong = c.pool.Methodref("org/python/core/Py",
187: "newLong", "(" + $str + ")" + $pyLong);
188: c.invokestatic(mref_newLong);
189: c.putstatic(module.classfile.name, name, $pyLong);
190: }
191:
192: public int hashCode() {
193: return value.hashCode();
194: }
195:
196: public boolean equals(Object o) {
197: if (o instanceof PyLongConstant)
198: return ((PyLongConstant) o).value.equals(value);
199: else
200: return false;
201: }
202: }
203:
204: class PyCodeConstant extends Constant implements ClassConstants {
205: public String co_name;
206: public int argcount;
207: public String[] names;
208: public int id;
209: public int co_firstlineno;
210: public boolean arglist, keywordlist;
211: String fname;
212:
213: // for nested scopes
214: public String[] cellvars;
215: public String[] freevars;
216: public int jy_npurecell;
217:
218: public int moreflags;
219:
220: public PyCodeConstant() {
221: ;
222: }
223:
224: public void get(Code c) throws IOException {
225: c.getstatic(module.classfile.name, name, $pyCode);
226: }
227:
228: public void put(Code c) throws IOException {
229: module.classfile.addField(name, $pyCode, access);
230: c.iconst(argcount);
231:
232: //Make all names
233: if (names != null) {
234: CodeCompiler.makeStrings(c, names, names.length);
235: } else { // classdef
236: CodeCompiler.makeStrings(c, null, 0);
237: }
238:
239: c.aload(1);
240: c.ldc(co_name);
241: c.iconst(co_firstlineno);
242:
243: c.iconst(arglist ? 1 : 0);
244: c.iconst(keywordlist ? 1 : 0);
245:
246: int mref_self = c.pool.Fieldref(module.classfile.name, "self",
247: "L" + module.classfile.name + ";");
248: c.getstatic(mref_self);
249: //c.aconst_null();
250:
251: c.iconst(id);
252:
253: if (cellvars != null)
254: CodeCompiler.makeStrings(c, cellvars, cellvars.length);
255: else
256: c.aconst_null();
257: if (freevars != null)
258: CodeCompiler.makeStrings(c, freevars, freevars.length);
259: else
260: c.aconst_null();
261:
262: c.iconst(jy_npurecell);
263:
264: c.iconst(moreflags);
265:
266: int mref_newCode = c.pool.Methodref("org/python/core/Py",
267: "newCode", "(I" + $strArr + $str + $str + "IZZ"
268: + $pyFuncTbl + "I" + $strArr + $strArr + "II)"
269: + $pyCode);
270:
271: c.invokestatic(mref_newCode);
272: //c.aconst_null();
273: c.putstatic(module.classfile.name, name, $pyCode);
274: }
275: }
276:
277: public class Module implements ClassConstants, CompilationContext {
278: ClassFile classfile;
279: Constant filename;
280: String sfilename;
281: public Constant mainCode;
282: public boolean linenumbers;
283: public boolean setFile = true;
284: Future futures;
285: Hashtable scopes;
286:
287: public Module(String name, String filename, boolean linenumbers) {
288: this .linenumbers = linenumbers;
289: classfile = new ClassFile(name,
290: "org/python/core/PyFunctionTable",
291: ClassFile.SYNCHRONIZED | ClassFile.PUBLIC);
292: constants = new Hashtable();
293: sfilename = filename;
294: if (filename != null)
295: this .filename = PyString(filename);
296: else
297: this .filename = null;
298: codes = new Vector();
299: futures = new Future();
300: scopes = new Hashtable();
301: }
302:
303: public Module(String name) {
304: this (name, name + ".py", true);
305: }
306:
307: // This block of code handles the pool of Python Constants
308: Hashtable constants;
309:
310: private Constant findConstant(Constant c) {
311: Constant ret = (Constant) constants.get(c);
312: if (ret != null)
313: return ret;
314: ret = c;
315: c.module = this ;
316: //More sophisticated name mappings might be nice
317: c.name = "_" + constants.size();
318: constants.put(ret, ret);
319: return ret;
320: }
321:
322: public Constant PyInteger(int value) {
323: return findConstant(new PyIntegerConstant(value));
324: }
325:
326: public Constant PyFloat(double value) {
327: return findConstant(new PyFloatConstant(value));
328: }
329:
330: public Constant PyComplex(double value) {
331: return findConstant(new PyComplexConstant(value));
332: }
333:
334: public Constant PyString(String value) {
335: return findConstant(new PyStringConstant(value));
336: }
337:
338: public Constant PyUnicode(String value) {
339: return findConstant(new PyUnicodeConstant(value));
340: }
341:
342: public Constant PyLong(String value) {
343: return findConstant(new PyLongConstant(value));
344: }
345:
346: /*public PyCodeConstant PyCode(SimpleNode tree, String name,
347: ArgListCompiler ac,
348: boolean fast_locals, boolean class_body)
349: throws Exception {
350: return PyCode(tree, name, ac, fast_locals, class_body, false, 0);
351: }
352: public PyCodeConstant PyCode(SimpleNode tree, String name,
353: ArgListCompiler ac,
354: boolean fast_locals, boolean class_body,
355: int firstlineno)
356: throws Exception {
357: return PyCode(tree, name, ac, fast_locals, class_body, false,
358: firstlineno);
359: }
360: public PyCodeConstant PyCode(SimpleNode tree, String name,
361: ArgListCompiler ac,
362: boolean fast_locals, boolean class_body,
363: boolean printResults)
364: throws Exception {
365: return PyCode(tree, name, ac, fast_locals, class_body, printResults, 0);
366: }*/
367:
368: Vector codes;
369:
370: private boolean isJavaIdentifier(String s) {
371: char[] chars = s.toCharArray();
372: if (chars.length == 0)
373: return false;
374: if (!Character.isJavaIdentifierStart(chars[0]))
375: return false;
376:
377: for (int i = 1; i < chars.length; i++) {
378: if (!Character.isJavaIdentifierPart(chars[i]))
379: return false;
380: }
381: return true;
382: }
383:
384: private String[] toNameAr(Vector names, boolean nullok) {
385: int sz = names.size();
386: if (sz == 0 && nullok)
387: return null;
388: String[] nameArray = new String[sz];
389: names.copyInto(nameArray);
390: return nameArray;
391: }
392:
393: private int to_cell;
394:
395: public PyCodeConstant PyCode(modType tree, String name,
396: boolean fast_locals, String className, boolean classBody,
397: boolean printResults, int firstlineno, ScopeInfo scope)
398: throws Exception {
399: return PyCode(tree, name, fast_locals, className, classBody,
400: printResults, firstlineno, scope, null);
401: }
402:
403: public PyCodeConstant PyCode(modType tree, String name,
404: boolean fast_locals, String className, boolean classBody,
405: boolean printResults, int firstlineno, ScopeInfo scope,
406: org.python.core.CompilerFlags cflags) throws Exception {
407: PyCodeConstant code = new PyCodeConstant();
408: ArgListCompiler ac = (scope != null) ? scope.ac : null;
409:
410: if (ac != null) {
411: code.arglist = ac.arglist;
412: code.keywordlist = ac.keywordlist;
413: code.argcount = ac.names.size();
414: }
415:
416: code.co_name = name;
417: code.co_firstlineno = firstlineno;
418: code.id = codes.size();
419:
420: //Better names in the future?
421: if (isJavaIdentifier(name))
422: code.fname = name + "$" + code.id;
423: else
424: code.fname = "f$" + code.id;
425:
426: codes.addElement(code);
427:
428: Code c = classfile.addMethod(code.fname, "(" + $pyFrame + ")"
429: + $pyObj, ClassFile.PUBLIC);
430:
431: CodeCompiler compiler = new CodeCompiler(this , printResults);
432:
433: Label genswitch = c.getLabel();
434: if (scope.generator) {
435: c.goto_(genswitch);
436: }
437: Label start = c.getLabel();
438: start.setPosition();
439:
440: //Do something to add init_code to tree
441: if (ac != null && ac.init_code.size() > 0) {
442: ac.appendInitCode((Suite) tree);
443: }
444:
445: if (scope != null) {
446: int nparamcell = scope.jy_paramcells.size();
447: if (nparamcell > 0) {
448: if (to_cell == 0) {
449: to_cell = classfile.pool.Methodref(
450: "org/python/core/PyFrame", "to_cell",
451: "(II)V");
452: }
453: Hashtable tbl = scope.tbl;
454: Vector paramcells = scope.jy_paramcells;
455: for (int i = 0; i < nparamcell; i++) {
456: c.aload(1);
457: SymInfo syminf = (SymInfo) tbl.get(paramcells
458: .elementAt(i));
459: c.iconst(syminf.locals_index);
460: c.iconst(syminf.env_index);
461: c.invokevirtual(to_cell);
462: }
463: }
464: }
465:
466: compiler.parse(tree, c, fast_locals, className, classBody,
467: scope, cflags);
468:
469: if (scope.generator) {
470: genswitch.setPosition();
471: c.aload(1);
472: if (compiler.f_lasti == 0) {
473: compiler.f_lasti = c.pool.Fieldref(
474: "org/python/core/PyFrame", "f_lasti", "I");
475: }
476: c.getfield(compiler.f_lasti);
477:
478: Label[] yields = new Label[compiler.yields.size() + 1];
479:
480: yields[0] = start;
481: for (int i = 1; i < yields.length; i++) {
482: yields[i] = (Label) compiler.yields.elementAt(i - 1);
483: }
484: c.tableswitch(start, 0, yields);
485: // XXX: Generate an error
486: }
487:
488: // !classdef only
489: if (!classBody)
490: code.names = toNameAr(compiler.names, false);
491:
492: if (scope != null) {
493: code.cellvars = toNameAr(scope.cellvars, true);
494: code.freevars = toNameAr(scope.freevars, true);
495: code.jy_npurecell = scope.jy_npurecell;
496: }
497:
498: if (compiler.optimizeGlobals) {
499: code.moreflags |= org.python.core.PyTableCode.CO_OPTIMIZED;
500: }
501: if (compiler.my_scope.generator) {
502: code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR;
503: }
504: if (cflags != null) {
505: if (cflags.generator_allowed) {
506: code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR_ALLOWED;
507: }
508: if (cflags.division) {
509: code.moreflags |= org.python.core.PyTableCode.CO_FUTUREDIVISION;
510: }
511: }
512:
513: code.module = this ;
514: code.name = code.fname;
515: return code;
516: }
517:
518: //This block of code writes out the various standard methods
519: public void addInit() throws IOException {
520: Code c = classfile.addMethod("<init>", "(Ljava/lang/String;)V",
521: ClassFile.PUBLIC);
522: c.aload(0);
523: c.invokespecial(c.pool.Methodref(
524: "org/python/core/PyFunctionTable", "<init>", "()V"));
525: addConstants(c);
526: }
527:
528: public void addRunnable() throws IOException {
529: Code c = classfile.addMethod("getMain", "()" + $pyCode,
530: ClassFile.PUBLIC);
531: mainCode.get(c);
532: c.areturn();
533: }
534:
535: public void addMain() throws IOException {
536: Code c = classfile.addMethod("main", "(" + $strArr + ")V",
537: ClassFile.PUBLIC | ClassFile.STATIC);
538: c.new_(c.pool.Class(classfile.name));
539: c.dup();
540: c.ldc(classfile.name);
541: c.invokespecial(c.pool.Methodref(classfile.name, "<init>", "("
542: + $str + ")V"));
543: c.aload(0);
544: c.invokestatic(c.pool.Methodref("org/python/core/Py",
545: "runMain", "(" + $pyRunnable + $strArr + ")V"));
546: c.return_();
547: }
548:
549: public void addConstants(Code c) throws IOException {
550: classfile.addField("self", "L" + classfile.name + ";",
551: ClassFile.STATIC | ClassFile.FINAL);
552: c.aload(0);
553: c.putstatic(c.pool.Fieldref(classfile.name, "self", "L"
554: + classfile.name + ";"));
555:
556: Enumeration e = constants.elements();
557:
558: while (e.hasMoreElements()) {
559: Constant constant = (Constant) e.nextElement();
560: constant.put(c);
561: }
562:
563: for (int i = 0; i < codes.size(); i++) {
564: PyCodeConstant pyc = (PyCodeConstant) codes.elementAt(i);
565: pyc.put(c);
566: }
567:
568: c.return_();
569: }
570:
571: public void addFunctions() throws IOException {
572: Code code = classfile.addMethod("call_function", "(I"
573: + $pyFrame + ")" + $pyObj, ClassFile.PUBLIC);
574:
575: code.aload(0);
576: code.aload(2);
577: Label def = code.getLabel();
578: Label[] labels = new Label[codes.size()];
579: int i;
580: for (i = 0; i < labels.length; i++)
581: labels[i] = code.getLabel();
582:
583: //Get index for function to call
584: code.iload(1);
585:
586: code.tableswitch(def, 0, labels);
587: for (i = 0; i < labels.length; i++) {
588: labels[i].setPosition();
589: code
590: .invokevirtual(
591: classfile.name,
592: ((PyCodeConstant) codes.elementAt(i)).fname,
593: "(" + $pyFrame + ")" + $pyObj);
594: code.areturn();
595: code.stack += 2;
596: }
597: def.setPosition();
598:
599: //Should probably throw internal exception here
600: code.aconst_null();
601: code.areturn();
602:
603: }
604:
605: public void write(OutputStream stream) throws IOException {
606: addInit();
607: addRunnable();
608: addMain();
609:
610: addFunctions();
611:
612: classfile.addInterface("org/python/core/PyRunnable");
613: if (sfilename != null) {
614: classfile.addAttribute(new SourceFile(sfilename,
615: classfile.pool));
616: }
617: classfile.addAttribute(new APIVersion(
618: org.python.core.imp.APIVersion, classfile.pool));
619: classfile.write(stream);
620: }
621:
622: // Implementation of CompilationContext
623: public Future getFutures() {
624: return futures;
625: }
626:
627: public String getFilename() {
628: return sfilename;
629: }
630:
631: public ScopeInfo getScopeInfo(SimpleNode node) {
632: return (ScopeInfo) scopes.get(node);
633: }
634:
635: public void error(String msg, boolean err, SimpleNode node)
636: throws Exception {
637: if (!err) {
638: try {
639: Py.warning(Py.SyntaxWarning, msg,
640: (sfilename != null) ? sfilename : "?",
641: node.beginLine, null, Py.None);
642: return;
643: } catch (PyException e) {
644: if (!Py.matchException(e, Py.SyntaxWarning))
645: throw e;
646: }
647: }
648: throw new ParseException(msg, node);
649: }
650:
651: public static void compile(modType node, OutputStream ostream,
652: String name, String filename, boolean linenumbers,
653: boolean printResults, boolean setFile,
654: org.python.core.CompilerFlags cflags) throws Exception {
655: Module module = new Module(name, filename, linenumbers);
656: module.setFile = setFile;
657: module.futures.preprocessFutures(node, cflags);
658: new ScopesCompiler(module, module.scopes).parse(node);
659:
660: //Add __doc__ if it exists
661: //Add __file__ for filename (if it exists?)
662:
663: Constant main = module.PyCode(node, "?", false, null, false,
664: printResults, 0, module.getScopeInfo(node), cflags);
665: module.mainCode = main;
666: module.write(ostream);
667: }
668: }
|