org.python.compiler.CodeCompiler Maven / Gradle / Ivy
Go to download
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
// Copyright (c) Corporation for National Research Initiatives
package org.python.compiler;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
import org.python.core.CompilerFlags;
import org.python.core.PyComplex;
import org.python.core.PyFloat;
import org.python.core.PyInteger;
import org.python.core.PyLong;
import org.python.core.PyObject;
import org.python.parser.ParseException;
import org.python.parser.SimpleNode;
import org.python.parser.Visitor;
import org.python.parser.ast.Assert;
import org.python.parser.ast.Assign;
import org.python.parser.ast.Attribute;
import org.python.parser.ast.AugAssign;
import org.python.parser.ast.BinOp;
import org.python.parser.ast.BoolOp;
import org.python.parser.ast.Break;
import org.python.parser.ast.Call;
import org.python.parser.ast.ClassDef;
import org.python.parser.ast.Compare;
import org.python.parser.ast.Continue;
import org.python.parser.ast.Delete;
import org.python.parser.ast.Dict;
import org.python.parser.ast.Ellipsis;
import org.python.parser.ast.Exec;
import org.python.parser.ast.Expr;
import org.python.parser.ast.Expression;
import org.python.parser.ast.ExtSlice;
import org.python.parser.ast.For;
import org.python.parser.ast.FunctionDef;
import org.python.parser.ast.Global;
import org.python.parser.ast.If;
import org.python.parser.ast.Import;
import org.python.parser.ast.ImportFrom;
import org.python.parser.ast.Index;
import org.python.parser.ast.Interactive;
import org.python.parser.ast.Lambda;
import org.python.parser.ast.List;
import org.python.parser.ast.ListComp;
import org.python.parser.ast.Name;
import org.python.parser.ast.Num;
import org.python.parser.ast.Pass;
import org.python.parser.ast.Print;
import org.python.parser.ast.Raise;
import org.python.parser.ast.Repr;
import org.python.parser.ast.Return;
import org.python.parser.ast.Slice;
import org.python.parser.ast.Str;
import org.python.parser.ast.Subscript;
import org.python.parser.ast.Suite;
import org.python.parser.ast.TryExcept;
import org.python.parser.ast.TryFinally;
import org.python.parser.ast.Tuple;
import org.python.parser.ast.UnaryOp;
import org.python.parser.ast.Unicode;
import org.python.parser.ast.While;
import org.python.parser.ast.Yield;
import org.python.parser.ast.excepthandlerType;
import org.python.parser.ast.exprType;
import org.python.parser.ast.expr_contextType;
import org.python.parser.ast.keywordType;
import org.python.parser.ast.listcompType;
import org.python.parser.ast.modType;
import org.python.parser.ast.stmtType;
public class CodeCompiler extends Visitor
implements ClassConstants //, PythonGrammarTreeConstants
{
public static final Object Exit=new Integer(1);
public static final Object NoExit=null;
public static final int GET=0;
public static final int SET=1;
public static final int DEL=2;
public static final int AUGGET=3;
public static final int AUGSET=4;
public Module module;
public Code code;
public ConstantPool pool;
public CodeCompiler mrefs;
public CompilerFlags cflags;
int temporary;
int augmode;
int augtmp1;
int augtmp2;
int augtmp3;
int augtmp4;
public boolean fast_locals, print_results;
public Hashtable tbl;
public ScopeInfo my_scope;
boolean optimizeGlobals = true;
public Vector names;
public String className;
public Stack continueLabels, breakLabels;
public Stack exceptionHandlers;
public Vector yields = new Vector();
/* break/continue finally's level.
* This is the lowest level in the exceptionHandlers which should
* be executed at break or continue.
* It is saved/updated/restored when compiling loops.
* A similar level for returns is not needed because a new CodeCompiler
* is used for each PyCode, ie. each 'function'.
* When returning through finally's all the exceptionHandlers are executed.
*/
public int bcfLevel = 0;
public CodeCompiler(Module module, boolean print_results) {
this.module = module;
this.print_results = print_results;
mrefs = this;
pool = module.classfile.pool;
continueLabels = new Stack();
breakLabels = new Stack();
exceptionHandlers = new Stack();
}
public int PyNone;
public void getNone() throws IOException {
if (mrefs.PyNone == 0) {
mrefs.PyNone = pool.Fieldref("org/python/core/Py", "None",
$pyObj);
}
code.getstatic(mrefs.PyNone);
}
public void loadFrame() throws Exception {
code.aload(1);
}
int f_lasti;
public void setLastI(int idx) throws Exception {
if (mrefs.f_lasti == 0) {
mrefs.f_lasti = code.pool.Fieldref(
"org/python/core/PyFrame", "f_lasti", "I");
}
loadFrame();
code.iconst(idx);
code.putfield(mrefs.f_lasti);
}
int f_back;
private void loadf_back() throws Exception {
if (mrefs.f_back == 0) {
mrefs.f_back = code.pool.Fieldref(
"org/python/core/PyFrame", "f_back", $pyFrame);
}
code.getfield(f_back);
}
public int storeTop() throws Exception {
int tmp = code.getLocal("org/python/core/PyObject");
code.astore(tmp);
return tmp;
}
public int setline;
public void setline(int line) throws Exception {
//System.out.println("line: "+line+", "+code.stack);
if (module.linenumbers) {
code.setline(line);
loadFrame();
code.iconst(line);
if (mrefs.setline == 0) {
mrefs.setline = pool.Methodref("org/python/core/PyFrame",
"setline", "(I)V");
}
code.invokevirtual(mrefs.setline);
}
}
public void setline(SimpleNode node) throws Exception {
setline(node.beginLine);
}
public void set(SimpleNode node) throws Exception {
int tmp = storeTop();
set(node, tmp);
code.aconst_null();
code.astore(tmp);
code.freeLocal(tmp);
}
boolean inSet = false;
public void set(SimpleNode node, int tmp) throws Exception {
//System.out.println("tmp: "+tmp);
if (inSet) {
System.out.println("recurse set: "+tmp+", "+temporary);
}
temporary = tmp;
visit(node);
}
private void saveAugTmps(SimpleNode node, int count) throws Exception {
if (count >= 4) {
augtmp4 = code.getLocal("org/python/core/PyObject");
code.astore(augtmp4);
}
if (count >= 3) {
augtmp3 = code.getLocal("org/python/core/PyObject");
code.astore(augtmp3);
}
if (count >= 2) {
augtmp2 = code.getLocal("org/python/core/PyObject");
code.astore(augtmp2);
}
augtmp1 = code.getLocal("org/python/core/PyObject");
code.astore(augtmp1);
code.aload(augtmp1);
if (count >= 2)
code.aload(augtmp2);
if (count >= 3)
code.aload(augtmp3);
if (count >= 4)
code.aload(augtmp4);
}
private void restoreAugTmps(SimpleNode node, int count) throws Exception {
code.aload(augtmp1);
code.freeLocal(augtmp1);
if (count == 1)
return;
code.aload(augtmp2);
code.freeLocal(augtmp2);
if (count == 2)
return;
code.aload(augtmp3);
code.freeLocal(augtmp3);
if (count == 3)
return;
code.aload(augtmp4);
code.freeLocal(augtmp4);
}
public void parse(modType node, Code code,
boolean fast_locals, String className,
boolean classBody, ScopeInfo scope, CompilerFlags cflags)
throws Exception
{
this.fast_locals = fast_locals;
this.className = className;
this.code = code;
this.cflags = cflags;
my_scope = scope;
names = scope.names;
tbl = scope.tbl;
optimizeGlobals = fast_locals&&!scope.exec&&!scope.from_import_star;
Object exit = visit(node);
//System.out.println("exit: "+exit+", "+(exit==null));
if (classBody) {
loadFrame();
code.invokevirtual("org/python/core/PyFrame", "getf_locals",
"()" + $pyObj);
code.areturn();
} else {
if (exit == null) {
//System.out.println("no exit");
setLastI(-1);
getNone();
code.areturn();
}
}
}
public Object visitInteractive(Interactive node) throws Exception {
traverse(node);
return null;
}
public Object visitModule(org.python.parser.ast.Module suite)
throws Exception
{
if (mrefs.setglobal == 0) {
mrefs.setglobal = code.pool.Methodref(
"org/python/core/PyFrame", "setglobal",
"(" +$str + $pyObj + ")V");
}
if (suite.body.length > 0 &&
suite.body[0] instanceof Expr &&
((Expr)suite.body[0]).value instanceof Str)
{
loadFrame();
code.ldc("__doc__");
visit(((Expr) suite.body[0]).value);
code.invokevirtual(mrefs.setglobal);
}
if (module.setFile) {
loadFrame();
code.ldc("__file__");
module.filename.get(code);
code.invokevirtual(mrefs.setglobal);
}
traverse(suite);
return null;
}
public Object visitExpression(Expression node) throws Exception {
if (my_scope.generator && node.body != null) {
module.error("'return' with argument inside generator",
true, node);
}
return visitReturn(new Return(node.body, node), true);
}
public int EmptyObjects;
public void makeArray(SimpleNode[] nodes) throws Exception {
int n;
if (nodes == null)
n = 0;
else
n = nodes.length;
if (n == 0) {
if (mrefs.EmptyObjects == 0) {
mrefs.EmptyObjects = code.pool.Fieldref(
"org/python/core/Py", "EmptyObjects", $pyObjArr);
}
code.getstatic(mrefs.EmptyObjects);
} else {
int tmp = code.getLocal("[org/python/core/PyObject");
code.iconst(n);
code.anewarray(code.pool.Class("org/python/core/PyObject"));
code.astore(tmp);
for(int i=0; i 0 && suite[0] instanceof Expr &&
((Expr) suite[0]).value instanceof Str)
{
visit(((Expr) suite[0]).value);
} else {
code.aconst_null();
}
}
int getclosure;
public boolean makeClosure(ScopeInfo scope) throws Exception {
if (scope == null || scope.freevars == null) return false;
int n = scope.freevars.size();
if (n == 0) return false;
if (mrefs.getclosure == 0) {
mrefs.getclosure = code.pool.Methodref(
"org/python/core/PyFrame", "getclosure", "(I)" + $pyObj);
}
int tmp = code.getLocal("[org/python/core/PyObject");
code.iconst(n);
code.anewarray(code.pool.Class("org/python/core/PyObject"));
code.astore(tmp);
Hashtable upTbl = scope.up.tbl;
for(int i=0; i",
"(" + $pyObj + $pyObjArr + $pyCode + $pyObj + ")V");
}
code.invokespecial(mrefs.PyFunction_init);
} else {
if (mrefs.PyFunction_closure_init == 0) {
mrefs.PyFunction_closure_init = code.pool.Methodref(
"org/python/core/PyFunction", "",
"(" + $pyObj + $pyObjArr + $pyCode + $pyObj + $pyObjArr +
")V");
}
code.invokespecial(mrefs.PyFunction_closure_init);
}
set(new Name(node.name, Name.Store, node));
return null;
}
public int printResult;
public Object visitExpr(Expr node) throws Exception {
setline(node);
visit(node.value);
if (print_results) {
if (mrefs.printResult == 0) {
mrefs.printResult = code.pool.Methodref(
"org/python/core/Py",
"printResult", "(" + $pyObj + ")V");
}
code.invokestatic(mrefs.printResult);
} else {
code.pop();
}
return null;
}
public Object visitAssign(Assign node) throws Exception {
setline(node);
visit(node.value);
if (node.targets.length == 1) {
set(node.targets[0]);
return null;
}
int tmp = storeTop();
for (int i=node.targets.length-1; i>=0; i--) {
set(node.targets[i], tmp);
}
code.freeLocal(tmp);
return null;
}
public int print1, print2, print3, print4, print5, print6;
public Object visitPrint(Print node) throws Exception {
setline(node);
int tmp = -1;
int printcomma, printlnv, println;
if (node.dest != null) {
visit(node.dest);
tmp = storeTop();
if (mrefs.print4 == 0) {
mrefs.print4 = pool.Methodref(
"org/python/core/Py", "printComma",
"(" + $pyObj + $pyObj + ")V");
}
printcomma = mrefs.print4;
if (mrefs.print5 == 0) {
mrefs.print5 = pool.Methodref(
"org/python/core/Py", "println",
"(" + $pyObj + $pyObj + ")V");
}
println = mrefs.print5;
if (mrefs.print6 == 0) {
mrefs.print6 = pool.Methodref(
"org/python/core/Py", "printlnv",
"(" + $pyObj + ")V");
}
printlnv = mrefs.print6;
}
else {
if (mrefs.print1 == 0) {
mrefs.print1 = pool.Methodref(
"org/python/core/Py", "printComma",
"(" + $pyObj + ")V");
}
printcomma = mrefs.print1;
if (mrefs.print2 == 0) {
mrefs.print2 = pool.Methodref(
"org/python/core/Py", "println",
"(" + $pyObj + ")V");
}
println = mrefs.print2;
if (mrefs.print3 == 0) {
mrefs.print3 = pool.Methodref(
"org/python/core/Py",
"println", "()V");
}
printlnv = mrefs.print3;
}
if (node.values == null || node.values.length == 0) {
if (node.dest != null)
code.aload(tmp);
code.invokestatic(printlnv);
} else {
for (int i = 0; i < node.values.length; i++) {
if (node.dest != null)
code.aload(tmp);
visit(node.values[i]);
if (node.nl && i == node.values.length - 1) {
code.invokestatic(println);
} else {
code.invokestatic(printcomma);
}
}
}
if (node.dest != null)
code.freeLocal(tmp);
return null;
}
public Object visitDelete(Delete node) throws Exception {
setline(node);
traverse(node);
return null;
}
public Object visitPass(Pass node) throws Exception {
setline(node);
return null;
}
public Object visitBreak(Break node) throws Exception {
//setline(node); Not needed here...
if (breakLabels.empty()) {
throw new ParseException("'break' outside loop", node);
}
doFinallysDownTo(bcfLevel);
code.goto_((Label)breakLabels.peek());
return null;
}
public Object visitContinue(Continue node) throws Exception {
//setline(node); Not needed here...
if (continueLabels.empty()) {
throw new ParseException("'continue' not properly in loop", node);
}
doFinallysDownTo(bcfLevel);
code.goto_((Label)continueLabels.peek());
return Exit;
}
int yield_count = 0;
int f_savedlocals;
public Object visitYield(Yield node) throws Exception {
setline(node);
if (!fast_locals) {
throw new ParseException("'yield' outside function", node);
}
if (inFinallyBody()) {
throw new ParseException("'yield' not allowed in a 'try' "+
"block with a 'finally' clause", node);
}
saveLocals();
visit(node.value);
setLastI(++yield_count);
code.areturn();
Label restart = code.getLabel();
yields.addElement(restart);
restart.setPosition();
restoreLocals();
return null;
}
private boolean inFinallyBody() {
for (int i = 0; i < exceptionHandlers.size(); ++i) {
ExceptionHandler handler =
(ExceptionHandler)exceptionHandlers.elementAt(i);
if (handler.isFinallyHandler()) {
return true;
}
}
return false;
}
private void restoreLocals() throws Exception {
endExceptionHandlers();
Vector v = code.getActiveLocals();
loadFrame();
if (mrefs.f_savedlocals == 0) {
mrefs.f_savedlocals = code.pool.Fieldref(
"org/python/core/PyFrame", "f_savedlocals",
"[Ljava/lang/Object;");
}
code.getfield(mrefs.f_savedlocals);
int locals = code.getLocal("[java/lang/Object");
code.astore(locals);
for (int i = 0; i < v.size(); i++) {
String type = (String) v.elementAt(i);
if (type == null)
continue;
code.aload(locals);
code.iconst(i);
code.aaload();
code.checkcast(code.pool.Class(type));
code.astore(i);
}
code.freeLocal(locals);
restartExceptionHandlers();
}
/**
* Close all the open exception handler ranges. This should be paired
* with restartExceptionHandlers to delimit internal code that
* shouldn't be handled by user handlers. This allows us to set
* variables without the verifier thinking we might jump out of our
* handling with an exception.
*/
private void endExceptionHandlers()
{
Label end = code.getLabelAtPosition();
for (int i = 0; i < exceptionHandlers.size(); ++i) {
ExceptionHandler handler =
(ExceptionHandler)exceptionHandlers.elementAt(i);
handler.exceptionEnds.addElement(end);
}
}
private void restartExceptionHandlers()
{
Label start = code.getLabelAtPosition();
for (int i = 0; i < exceptionHandlers.size(); ++i) {
ExceptionHandler handler =
(ExceptionHandler)exceptionHandlers.elementAt(i);
handler.exceptionStarts.addElement(start);
}
}
private void saveLocals() throws Exception {
Vector v = code.getActiveLocals();
//System.out.println("bs:" + bs);
code.iconst(v.size());
//code.anewarray(code.pool.Class("org/python/core/PyObject"));
code.anewarray(code.pool.Class("java/lang/Object"));
int locals = code.getLocal("[java/lang/Object");
code.astore(locals);
for (int i = 0; i < v.size(); i++) {
String type = (String) v.elementAt(i);
if (type == null)
continue;
code.aload(locals);
code.iconst(i);
//code.checkcast(code.pool.Class("java/lang/Object"));
if (i == 2222) {
code.aconst_null();
} else
code.aload(i);
code.aastore();
}
if (mrefs.f_savedlocals == 0) {
mrefs.f_savedlocals = code.pool.Fieldref(
"org/python/core/PyFrame", "f_savedlocals",
"[Ljava/lang/Object;");
}
loadFrame();
code.aload(locals);
code.putfield(mrefs.f_savedlocals);
code.freeLocal(locals);
}
public Object visitReturn(Return node) throws Exception {
return visitReturn(node, false);
}
public Object visitReturn(Return node, boolean inEval) throws Exception {
setline(node);
if (!inEval && !fast_locals) {
throw new ParseException("'return' outside function", node);
}
int tmp = 0;
if (node.value != null) {
if (my_scope.generator)
throw new ParseException("'return' with argument " +
"inside generator", node);
visit(node.value);
tmp = code.getReturnLocal();
code.astore(tmp);
}
doFinallysDownTo(0);
setLastI(-1);
if (node.value != null) {
code.aload(tmp);
} else {
getNone();
}
code.areturn();
return Exit;
}
public int makeException0, makeException1, makeException2, makeException3;
public Object visitRaise(Raise node) throws Exception {
setline(node);
traverse(node);
if (node.type == null) {
if (mrefs.makeException0 == 0) {
mrefs.makeException0 = code.pool.Methodref(
"org/python/core/Py", "makeException",
"()" + $pyExc);
}
code.invokestatic(mrefs.makeException0);
} else if (node.inst == null) {
if (mrefs.makeException1 == 0) {
mrefs.makeException1 = code.pool.Methodref(
"org/python/core/Py", "makeException",
"(" + $pyObj + ")" + $pyExc);
}
code.invokestatic(mrefs.makeException1);
} else if (node.tback == null) {
if (mrefs.makeException2 == 0) {
mrefs.makeException2 = code.pool.Methodref(
"org/python/core/Py", "makeException",
"(" + $pyObj + $pyObj + ")" + $pyExc);
}
code.invokestatic(mrefs.makeException2);
} else {
if (mrefs.makeException3 == 0) {
mrefs.makeException3 = code.pool.Methodref(
"org/python/core/Py", "makeException",
"(" + $pyObj + $pyObj + $pyObj + ")" + $pyExc);
}
code.invokestatic(mrefs.makeException3);
}
code.athrow();
return Exit;
}
public int importOne, importOneAs;
public Object visitImport(Import node) throws Exception {
setline(node);
for (int i = 0; i < node.names.length; i++) {
String asname = null;
if (node.names[i].asname != null) {
String name = node.names[i].name;
asname = node.names[i].asname;
code.ldc(name);
loadFrame();
if (mrefs.importOneAs == 0) {
mrefs.importOneAs = code.pool.Methodref(
"org/python/core/imp", "importOneAs",
"(" + $str + $pyFrame + ")" + $pyObj);
}
code.invokestatic(mrefs.importOneAs);
} else {
String name = node.names[i].name;
asname = name;
if (asname.indexOf('.') > 0)
asname = asname.substring(0, asname.indexOf('.'));
code.ldc(name);
loadFrame();
if (mrefs.importOne == 0) {
mrefs.importOne = code.pool.Methodref(
"org/python/core/imp", "importOne",
"(" + $str + $pyFrame + ")" + $pyObj);
}
code.invokestatic(mrefs.importOne);
}
set(new Name(asname, Name.Store, node));
}
return null;
}
public int importAll, importFrom;
public Object visitImportFrom(ImportFrom node) throws Exception {
Future.checkFromFuture(node); // future stmt support
setline(node);
code.ldc(node.module);
if (node.names.length > 0) {
String[] names = new String[node.names.length];
String[] asnames = new String[node.names.length];
for (int i = 0; i < node.names.length; i++) {
names[i] = node.names[i].name;
asnames[i] = node.names[i].asname;
if (asnames[i] == null)
asnames[i] = names[i];
}
makeStrings(code, names, names.length);
loadFrame();
if (mrefs.importFrom == 0) {
mrefs.importFrom = code.pool.Methodref(
"org/python/core/imp", "importFrom",
"(" + $str + $strArr + $pyFrame + ")" + $pyObjArr);
}
code.invokestatic(mrefs.importFrom);
int tmp = storeTop();
for (int i = 0; i < node.names.length; i++) {
code.aload(tmp);
code.iconst(i);
code.aaload();
set(new Name(asnames[i], Name.Store, node));
}
code.freeLocal(tmp);
} else {
loadFrame();
if (mrefs.importAll == 0) {
mrefs.importAll = code.pool.Methodref(
"org/python/core/imp", "importAll",
"(" + $str + $pyFrame + ")V");
}
code.invokestatic(mrefs.importAll);
}
return null;
}
public Object visitGlobal(Global node) throws Exception {
return null;
}
public int exec;
public Object visitExec(Exec node) throws Exception {
setline(node);
visit(node.body);
if (node.globals != null) {
visit(node.globals);
} else {
code.aconst_null();
}
if (node.locals != null) {
visit(node.locals);
} else {
code.aconst_null();
}
//do the real work here
if (mrefs.exec == 0) {
mrefs.exec = code.pool.Methodref(
"org/python/core/Py", "exec",
"(" + $pyObj + $pyObj + $pyObj + ")V");
}
code.invokestatic(mrefs.exec);
return null;
}
public int asserttype;
public Object visitAssert(Assert node) throws Exception {
setline(node);
Label end_of_assert = code.getLabel();
/* First do an if __debug__: */
loadFrame();
emitGetGlobal("__debug__");
if (mrefs.nonzero == 0) {
mrefs.nonzero = code.pool.Methodref("org/python/core/PyObject",
"__nonzero__", "()Z");
}
code.invokevirtual(mrefs.nonzero);
code.ifeq(end_of_assert);
/* Now do the body of the assert. If PyObject.__nonzero__ is true,
then the assertion succeeded, the message portion should not be
processed. Otherwise, the message will be processed. */
visit(node.test);
code.invokevirtual(mrefs.nonzero);
/* If evaluation is false, then branch to end of method */
code.ifne(end_of_assert);
/* Push exception type onto stack(Py.AssertionError) */
if (mrefs.asserttype == 0) {
mrefs.asserttype = code.pool.Fieldref(
"org/python/core/Py", "AssertionError",
"Lorg/python/core/PyObject;");
}
code.getstatic(mrefs.asserttype);
/* Visit the message part of the assertion, or pass Py.None */
if( node.msg != null ){
visit(node.msg);
} else{
getNone();
}
if (mrefs.makeException2 == 0) {
mrefs.makeException2 = code.pool.Methodref(
"org/python/core/Py", "makeException",
"(" + $pyObj + $pyObj + ")" + $pyExc);
}
code.invokestatic(mrefs.makeException2);
/* Raise assertion error. Only executes this logic if assertion
failed */
code.athrow();
/* And finally set the label for the end of it all */
end_of_assert.setPosition();
return null;
}
public int nonzero;
public Object doTest(Label end_of_if, If node, int index)
throws Exception
{
Label end_of_suite = code.getLabel();
setline(node.test);
visit(node.test);
if (mrefs.nonzero == 0) {
mrefs.nonzero = code.pool.Methodref("org/python/core/PyObject",
"__nonzero__", "()Z");
}
code.invokevirtual(mrefs.nonzero);
code.ifeq(end_of_suite);
Object exit = suite(node.body);
if (end_of_if != null && exit == null)
code.goto_(end_of_if);
end_of_suite.setPosition();
if (node.orelse != null) {
return suite(node.orelse) != null ? exit : null;
} else {
return null;
}
}
public Object visitIf(If node) throws Exception {
Label end_of_if = null;
if (node.orelse != null)
end_of_if = code.getLabel();
Object exit = doTest(end_of_if, node, 0);
if (end_of_if != null)
end_of_if.setPosition();
return exit;
}
public int beginLoop() {
continueLabels.push(code.getLabel());
breakLabels.push(code.getLabel());
int savebcf = bcfLevel;
bcfLevel = exceptionHandlers.size();
return savebcf;
}
public void finishLoop(int savebcf) {
continueLabels.pop();
breakLabels.pop();
bcfLevel = savebcf;
}
public Object visitWhile(While node) throws Exception {
int savebcf = beginLoop();
Label continue_loop = (Label)continueLabels.peek();
Label break_loop = (Label)breakLabels.peek();
Label start_loop = code.getLabel();
code.goto_(continue_loop);
start_loop.setPosition();
//Do suite
suite(node.body);
continue_loop.setPosition();
setline(node);
//Do test
visit(node.test);
if (mrefs.nonzero == 0) {
mrefs.nonzero = code.pool.Methodref("org/python/core/PyObject",
"__nonzero__", "()Z");
}
code.invokevirtual(mrefs.nonzero);
code.ifne(start_loop);
finishLoop(savebcf);
if (node.orelse != null) {
//Do else
suite(node.orelse);
}
break_loop.setPosition();
// Probably need to detect "guaranteed exits"
return null;
}
public int iter=0;
public int iternext=0;
public Object visitFor(For node) throws Exception {
int savebcf = beginLoop();
Label continue_loop = (Label)continueLabels.peek();
Label break_loop = (Label)breakLabels.peek();
Label start_loop = code.getLabel();
Label next_loop = code.getLabel();
int iter_tmp = code.getLocal("org/python/core/PyObject");
int expr_tmp = code.getLocal("org/python/core/PyObject");
setline(node);
//parse the list
visit(node.iter);
//set up the loop iterator
if (mrefs.iter == 0) {
mrefs.iter = code.pool.Methodref(
"org/python/core/PyObject",
"__iter__", "()" + $pyObj);
}
code.invokevirtual(mrefs.iter);
code.astore(iter_tmp);
//do check at end of loop. Saves one opcode ;-)
code.goto_(next_loop);
start_loop.setPosition();
//set iter variable to current entry in list
set(node.target, expr_tmp);
//evaluate for body
suite(node.body);
continue_loop.setPosition();
next_loop.setPosition();
setline(node);
//get the next element from the list
code.aload(iter_tmp);
if (mrefs.iternext == 0) {
mrefs.iternext = code.pool.Methodref(
"org/python/core/PyObject",
"__iternext__", "()" + $pyObj);
}
code.invokevirtual(mrefs.iternext);
code.astore(expr_tmp);
code.aload(expr_tmp);
//if no more elements then fall through
code.ifnonnull(start_loop);
finishLoop(savebcf);
if (node.orelse != null) {
//Do else clause if provided
suite(node.orelse);
}
break_loop.setPosition();
code.freeLocal(iter_tmp);
code.freeLocal(expr_tmp);
// Probably need to detect "guaranteed exits"
return null;
}
public int match_exception;
public void exceptionTest(int exc, Label end_of_exceptions,
TryExcept node, int index)
throws Exception
{
for (int i = 0; i < node.handlers.length; i++) {
excepthandlerType handler = node.handlers[i];
//setline(name);
Label end_of_self = code.getLabel();
if (handler.type != null) {
code.aload(exc);
//get specific exception
visit(handler.type);
if (mrefs.match_exception == 0) {
mrefs.match_exception = code.pool.Methodref(
"org/python/core/Py", "matchException",
"(" + $pyExc + $pyObj + ")Z");
}
code.invokestatic(mrefs.match_exception);
code.ifeq(end_of_self);
} else {
if (i != node.handlers.length-1) {
throw new ParseException(
"bare except must be last except clause", handler.type);
}
}
if (handler.name != null) {
code.aload(exc);
code.getfield(code.pool.Fieldref("org/python/core/PyException",
"value",
"Lorg/python/core/PyObject;"));
set(handler.name);
}
//do exception body
suite(handler.body);
code.goto_(end_of_exceptions);
end_of_self.setPosition();
}
code.aload(exc);
code.athrow();
}
public int add_traceback;
public Object visitTryFinally(TryFinally node) throws Exception
{
Label start = code.getLabel();
Label end = code.getLabel();
Label handlerStart = code.getLabel();
Label finallyEnd = code.getLabel();
Object ret;
ExceptionHandler inFinally = new ExceptionHandler(node);
// Do protected suite
exceptionHandlers.push(inFinally);
int excLocal = code.getLocal("java/lang/Throwable");
code.aconst_null();
code.astore(excLocal);
start.setPosition();
inFinally.exceptionStarts.addElement(start);
ret = suite(node.body);
end.setPosition();
inFinally.exceptionEnds.addElement(end);
inFinally.bodyDone = true;
exceptionHandlers.pop();
if (ret == NoExit) {
inlineFinally(inFinally);
code.goto_(finallyEnd);
}
// Handle any exceptions that get thrown in suite
handlerStart.setPosition();
code.stack = 1;
code.astore(excLocal);
code.aload(excLocal);
loadFrame();
if (mrefs.add_traceback == 0) {
mrefs.add_traceback = code.pool.Methodref(
"org/python/core/Py", "addTraceback",
"(" + $throwable + $pyFrame + ")V");
}
code.invokestatic(mrefs.add_traceback);
inlineFinally(inFinally);
code.aload(excLocal);
code.checkcast(code.pool.Class("java/lang/Throwable"));
code.athrow();
finallyEnd.setPosition();
code.freeLocal(excLocal);
inFinally.addExceptionHandlers(handlerStart);
// According to any JVM verifiers, this code block might not return
return null;
}
private void inlineFinally(ExceptionHandler handler) throws Exception {
if (!handler.bodyDone) {
// end the previous exception block so inlined finally code doesn't
// get covered by our exception handler.
handler.exceptionEnds.addElement(code.getLabelAtPosition());
// also exiting the try: portion of this particular finally
}
if (handler.isFinallyHandler()) {
suite(handler.node.finalbody);
}
}
private void reenterProtectedBody(ExceptionHandler handler) throws Exception {
// restart exception coverage
handler.exceptionStarts.addElement(code.getLabelAtPosition());
}
/**
* Inline the finally handling code for levels down to the levelth parent
* (0 means all). This takes care to avoid having more nested finallys
* catch exceptions throw by the parent finally code. This also pops off
* all the handlers above level temporarily.
*/
private void doFinallysDownTo(int level) throws Exception {
Stack poppedHandlers = new Stack();
while (exceptionHandlers.size() > level) {
ExceptionHandler handler =
(ExceptionHandler)exceptionHandlers.pop();
inlineFinally(handler);
poppedHandlers.push(handler);
}
while (poppedHandlers.size() > 0) {
ExceptionHandler handler =
(ExceptionHandler)poppedHandlers.pop();
reenterProtectedBody(handler);
exceptionHandlers.push(handler);
}
}
public int set_exception;
public Object visitTryExcept(TryExcept node) throws Exception {
Label start = code.getLabel();
Label end = code.getLabel();
Label handler_start = code.getLabel();
Label handler_end = code.getLabel();
ExceptionHandler handler = new ExceptionHandler();
start.setPosition();
handler.exceptionStarts.addElement(start);
exceptionHandlers.push(handler);
//Do suite
Object exit = suite(node.body);
//System.out.println("exit: "+exit+", "+(exit != null));
exceptionHandlers.pop();
end.setPosition();
handler.exceptionEnds.addElement(end);
if (exit == null)
code.goto_(handler_end);
handler_start.setPosition();
//Stack has eactly one item at start of handler
code.stack = 1;
loadFrame();
if (mrefs.set_exception == 0) {
mrefs.set_exception = code.pool.Methodref(
"org/python/core/Py", "setException",
"(" + $throwable + $pyFrame + ")" + $pyExc);
}
code.invokestatic(mrefs.set_exception);
int exc = code.getFinallyLocal("java/lang/Throwable");
code.astore(exc);
if (node.orelse == null) {
//No else clause to worry about
exceptionTest(exc, handler_end, node, 1);
handler_end.setPosition();
} else {
//Have else clause
Label else_end = code.getLabel();
exceptionTest(exc, else_end, node, 1);
handler_end.setPosition();
//do else clause
suite(node.orelse);
else_end.setPosition();
}
code.freeFinallyLocal(exc);
handler.addExceptionHandlers(handler_start);
return null;
}
public Object visitSuite(Suite node) throws Exception {
return suite(node.body);
}
public Object suite(stmtType[] stmts) throws Exception {
int n = stmts.length;
for(int i = 0; i < n; i++) {
Object exit = visit(stmts[i]);
//System.out.println("exit: "+exit+", "+n+", "+(exit != null));
if (exit != null)
return Exit;
}
return null;
}
public Object visitBoolOp(BoolOp node) throws Exception {
Label end = code.getLabel();
visit(node.values[0]);
for (int i = 1; i < node.values.length; i++) {
code.dup();
if (mrefs.nonzero == 0) {
mrefs.nonzero = code.pool.Methodref("org/python/core/PyObject",
"__nonzero__", "()Z");
}
code.invokevirtual(mrefs.nonzero);
switch (node.op) {
case BoolOp.Or :
code.ifne(end);
break;
case BoolOp.And :
code.ifeq(end);
break;
}
code.pop();
visit(node.values[i]);
}
end.setPosition();
return null;
}
public Object visitCompare(Compare node) throws Exception {
int tmp1 = code.getLocal("org/python/core/PyObject");
int tmp2 = code.getLocal("org/python/core/PyObject");
int op;
if (mrefs.nonzero == 0) {
mrefs.nonzero = code.pool.Methodref("org/python/core/PyObject",
"__nonzero__", "()Z");
}
Label end = code.getLabel();
visit(node.left);
int n = node.ops.length;
for(int i = 0; i < n - 1; i++) {
visit(node.comparators[i]);
code.dup();
code.astore(tmp1);
code.invokevirtual(make_cmpop(node.ops[i]));
code.dup();
code.astore(tmp2);
code.invokevirtual(mrefs.nonzero);
code.ifeq(end);
code.aload(tmp1);
}
visit(node.comparators[n-1]);
code.invokevirtual(make_cmpop(node.ops[n-1]));
if (n > 1) {
code.astore(tmp2);
end.setPosition();
code.aload(tmp2);
}
code.freeLocal(tmp1);
code.freeLocal(tmp2);
return null;
}
int[] compare_ops = new int[11];
public int make_cmpop(int op) throws Exception {
if (compare_ops[op] == 0) {
String name = null;
switch (op) {
case Compare.Eq: name = "_eq"; break;
case Compare.NotEq: name = "_ne"; break;
case Compare.Lt: name = "_lt"; break;
case Compare.LtE: name = "_le"; break;
case Compare.Gt: name = "_gt"; break;
case Compare.GtE: name = "_ge"; break;
case Compare.Is: name = "_is"; break;
case Compare.IsNot: name = "_isnot"; break;
case Compare.In: name = "_in"; break;
case Compare.NotIn: name = "_notin"; break;
}
compare_ops[op] = code.pool.Methodref(
"org/python/core/PyObject", name,
"(" + $pyObj + ")" + $pyObj);
}
return compare_ops[op];
}
static String[] bin_methods = new String[] {
null,
"_add",
"_sub",
"_mul",
"_div",
"_mod",
"_pow",
"_lshift",
"_rshift",
"_or",
"_xor",
"_and",
"_floordiv",
};
int[] bin_ops = new int[13];
public int make_binop(int op) throws Exception {
if (bin_ops[op] == 0) {
String name = bin_methods[op];
if (op == BinOp.Div && module.getFutures().areDivisionOn()) {
name = "_truediv";
}
bin_ops[op] = code.pool.Methodref(
"org/python/core/PyObject", name,
"(" + $pyObj + ")" + $pyObj);
}
return bin_ops[op];
}
public Object visitBinOp(BinOp node) throws Exception {
visit(node.left);
visit(node.right);
code.invokevirtual(make_binop(node.op));
return null;
}
static String[] unary_methods = new String[] {
null,
"__invert__",
"__not__",
"__pos__",
"__neg__",
};
int[] unary_ops = new int[unary_methods.length];
public int make_unaryop(int op) throws Exception {
if (unary_ops[op] == 0) {
String name = unary_methods[op];
unary_ops[op] = code.pool.Methodref(
"org/python/core/PyObject", name, "()" + $pyObj);
}
return unary_ops[op];
}
public Object visitUnaryOp(UnaryOp node) throws Exception {
visit(node.operand);
code.invokevirtual(make_unaryop(node.op));
return null;
}
static String[] aug_methods = new String[] {
null,
"__iadd__",
"__isub__",
"__imul__",
"__idiv__",
"__imod__",
"__ipow__",
"__ilshift__",
"__irshift__",
"__ior__",
"__ixor__",
"__iand__",
"__ifloordiv__",
};
int[] augbin_ops = new int[aug_methods.length];
public int make_augbinop(int op) throws Exception {
if (augbin_ops[op] == 0) {
String name = aug_methods[op];
if (op == BinOp.Div && module.getFutures().areDivisionOn()) {
name = "__itruediv__";
}
augbin_ops[op] = code.pool.Methodref(
"org/python/core/PyObject", name,
"(" + $pyObj + ")" + $pyObj);
}
return augbin_ops[op];
}
public Object visitAugAssign(AugAssign node) throws Exception {
visit(node.value);
int tmp = storeTop();
augmode = expr_contextType.Load;
visit(node.target);
code.aload(tmp);
code.invokevirtual(make_augbinop(node.op));
code.freeLocal(tmp);
temporary = storeTop();
augmode = expr_contextType.Store;
visit(node.target);
code.freeLocal(temporary);
return null;
}
public static void makeStrings(Code c, String[] names, int n)
throws IOException
{
c.iconst(n);
c.anewarray(c.pool.Class("java/lang/String"));
int strings = c.getLocal("[java/lang/String");
c.astore(strings);
for (int i=0; i 0) {
makeArray(values);
makeStrings(code, keys, keys.length);
if (mrefs.call1 == 0) {
mrefs.call1 = code.pool.Methodref(
"org/python/core/PyObject", "__call__",
"(" + $pyObjArr + $strArr + ")" + $pyObj);
}
code.invokevirtual(mrefs.call1);
} else {
switch (values.length) {
case 0:
if (mrefs.calla0 == 0) {
mrefs.calla0 = code.pool.Methodref(
"org/python/core/PyObject", "__call__",
"()" + $pyObj);
}
code.invokevirtual(mrefs.calla0);
break;
case 1:
if (mrefs.calla1 == 0) {
mrefs.calla1 = code.pool.Methodref(
"org/python/core/PyObject", "__call__",
"(" + $pyObj + ")" + $pyObj);
}
visit(values[0]);
code.invokevirtual(mrefs.calla1);
break;
case 2:
if (mrefs.calla2 == 0) {
mrefs.calla2 = code.pool.Methodref(
"org/python/core/PyObject", "__call__",
"(" + $pyObj + $pyObj + ")" + $pyObj);
}
visit(values[0]);
visit(values[1]);
code.invokevirtual(mrefs.calla2);
break;
case 3:
if (mrefs.calla3 == 0) {
mrefs.calla3 = code.pool.Methodref(
"org/python/core/PyObject", "__call__",
"(" + $pyObj + $pyObj + $pyObj + ")" + $pyObj);
}
visit(values[0]);
visit(values[1]);
visit(values[2]);
code.invokevirtual(mrefs.calla3);
break;
case 4:
if (mrefs.calla4 == 0) {
mrefs.calla4 = code.pool.Methodref(
"org/python/core/PyObject", "__call__",
"(" + $pyObj + $pyObj + $pyObj + $pyObj + ")" +
$pyObj);
}
visit(values[0]);
visit(values[1]);
visit(values[2]);
visit(values[3]);
code.invokevirtual(mrefs.calla4);
break;
default:
makeArray(values);
if (mrefs.call2 == 0) {
mrefs.call2 = code.pool.Methodref(
"org/python/core/PyObject", "__call__",
"(" + $pyObjArr + ")" + $pyObj);
}
code.invokevirtual(mrefs.call2);
break;
}
}
return null;
}
public int getslice, setslice, delslice;
public Object Slice(Subscript node, Slice slice) throws Exception {
int ctx = node.ctx;
if (ctx == node.AugStore && augmode == node.Store) {
restoreAugTmps(node, 4);
ctx = node.Store;
} else {
visit(node.value);
if (slice.lower != null)
visit(slice.lower);
else
code.aconst_null();
if (slice.upper != null)
visit(slice.upper);
else
code.aconst_null();
if (slice.step != null)
visit(slice.step);
else
code.aconst_null();
if (node.ctx == node.AugStore && augmode == node.Load) {
saveAugTmps(node, 4);
ctx = node.Load;
}
}
switch (ctx) {
case Subscript.Del:
if (mrefs.delslice == 0) {
mrefs.delslice = code.pool.Methodref(
"org/python/core/PyObject", "__delslice__",
"(" + $pyObj + $pyObj + $pyObj + ")V");
}
code.invokevirtual(mrefs.delslice);
return null;
case Subscript.Load:
if (mrefs.getslice == 0) {
mrefs.getslice = code.pool.Methodref(
"org/python/core/PyObject", "__getslice__",
"(" + $pyObj + $pyObj + $pyObj + ")" + $pyObj);
}
code.invokevirtual(mrefs.getslice);
return null;
case Subscript.Store:
code.aload(temporary);
if (mrefs.setslice == 0) {
mrefs.setslice = code.pool.Methodref(
"org/python/core/PyObject", "__setslice__",
"(" + $pyObj + $pyObj + $pyObj + $pyObj + ")V");
}
code.invokevirtual(mrefs.setslice);
return null;
}
return null;
}
public int getitem, delitem, setitem;
public Object visitSubscript(Subscript node) throws Exception {
if (node.slice instanceof Slice) {
return Slice(node, (Slice) node.slice);
}
int ctx = node.ctx;
if (node.ctx == node.AugStore && augmode == node.Store) {
restoreAugTmps(node, 2);
ctx = node.Store;
} else {
visit(node.value);
visit(node.slice);
if (node.ctx == node.AugStore && augmode == node.Load) {
saveAugTmps(node, 2);
ctx = node.Load;
}
}
switch (ctx) {
case Subscript.Del:
if (mrefs.delitem == 0) {
mrefs.delitem = code.pool.Methodref(
"org/python/core/PyObject", "__delitem__",
"(" + $pyObj + ")V");
}
code.invokevirtual(mrefs.delitem);
return null;
case Subscript.Load:
if (mrefs.getitem == 0) {
mrefs.getitem = code.pool.Methodref(
"org/python/core/PyObject", "__getitem__",
"(" + $pyObj + ")" + $pyObj);
}
code.invokevirtual(mrefs.getitem);
return null;
case Subscript.Store:
code.aload(temporary);
if (mrefs.setitem == 0) {
mrefs.setitem = code.pool.Methodref(
"org/python/core/PyObject", "__setitem__",
"(" + $pyObj + $pyObj + ")V");
}
code.invokevirtual(mrefs.setitem);
return null;
}
return null;
}
public Object visitIndex(Index node) throws Exception {
traverse(node);
return null;
}
public Object visitExtSlice(ExtSlice node) throws Exception {
code.new_(code.pool.Class("org/python/core/PyTuple"));
code.dup();
makeArray(node.dims);
if (mrefs.PyTuple_init == 0) {
mrefs.PyTuple_init = code.pool.Methodref(
"org/python/core/PyTuple", "",
"(" + $pyObjArr + ")V");
}
code.invokespecial(mrefs.PyTuple_init);
return null;
}
public int getattr, delattr, setattr;
public Object visitAttribute(Attribute node) throws Exception {
int ctx = node.ctx;
if (node.ctx == node.AugStore && augmode == node.Store) {
restoreAugTmps(node, 2);
ctx = node.Store;
} else {
visit(node.value);
code.ldc(getName(node.attr));
if (node.ctx == node.AugStore && augmode == node.Load) {
saveAugTmps(node, 2);
ctx = node.Load;
}
}
switch (ctx) {
case Attribute.Del:
if (mrefs.delattr == 0) {
mrefs.delattr = code.pool.Methodref(
"org/python/core/PyObject", "__delattr__",
"(" + $str + ")V");
}
code.invokevirtual(mrefs.delattr);
return null;
case Attribute.Load:
if (mrefs.getattr == 0) {
mrefs.getattr = code.pool.Methodref(
"org/python/core/PyObject", "__getattr__",
"(" + $str + ")" + $pyObj);
}
code.invokevirtual(mrefs.getattr);
return null;
case Attribute.Store:
code.aload(temporary);
if (mrefs.setattr == 0) {
mrefs.setattr = code.pool.Methodref(
"org/python/core/PyObject", "__setattr__",
"(" + $str + $pyObj + ")V");
}
code.invokevirtual(mrefs.setattr);
return null;
}
return null;
}
public int getitem2, unpackSequence;
public Object seqSet(exprType[] nodes) throws Exception {
if (mrefs.unpackSequence == 0) {
mrefs.unpackSequence = code.pool.Methodref(
"org/python/core/Py",
"unpackSequence",
"(" + $pyObj + "I)" + $pyObjArr);
}
code.aload(temporary);
code.iconst(nodes.length);
code.invokestatic(mrefs.unpackSequence);
int tmp = code.getLocal("[org/python/core/PyObject");
code.astore(tmp);
for (int i = 0; i < nodes.length; i++) {
code.aload(tmp);
code.iconst(i);
code.aaload();
set(nodes[i]);
}
code.freeLocal(tmp);
return null;
}
public Object seqDel(exprType[] nodes) throws Exception {
for (int i = 0; i < nodes.length; i++) {
visit(nodes[i]);
}
return null;
}
public int PyTuple_init, PyList_init, PyDictionary_init;
public Object visitTuple(Tuple node) throws Exception {
/* if (mode ==AUGSET)
throw new ParseException(
"augmented assign to tuple not possible", node); */
if (node.ctx == node.Store) return seqSet(node.elts);
if (node.ctx == node.Del) return seqDel(node.elts);
code.new_(code.pool.Class("org/python/core/PyTuple"));
code.dup();
makeArray(node.elts);
if (mrefs.PyTuple_init == 0) {
mrefs.PyTuple_init = code.pool.Methodref(
"org/python/core/PyTuple", "",
"(" + $pyObjArr + ")V");
}
code.invokespecial(mrefs.PyTuple_init);
return null;
}
/*
public Object fplist(SimpleNode node) throws Exception {
if (mode == SET) return seqSet(node);
throw new ParseException("in fplist node", node);
}
*/
public Object visitList(List node) throws Exception {
/* if (mode ==AUGSET)
throw new ParseException(
"augmented assign to list not possible", node); */
if (node.ctx == node.Store) return seqSet(node.elts);
if (node.ctx == node.Del) return seqDel(node.elts);
code.new_(code.pool.Class("org/python/core/PyList"));
code.dup();
makeArray(node.elts);
if (mrefs.PyList_init == 0) {
mrefs.PyList_init = code.pool.Methodref(
"org/python/core/PyList", "",
"(" + $pyObjArr + ")V");
}
code.invokespecial(mrefs.PyList_init);
return null;
}
int list_comprehension_count = 0;
public int PyList_init2;
public Object visitListComp(ListComp node) throws Exception {
code.new_(code.pool.Class("org/python/core/PyList"));
code.dup();
if (mrefs.PyList_init2 == 0) {
mrefs.PyList_init2 = code.pool.Methodref(
"org/python/core/PyList", "", "()V");
}
code.invokespecial(mrefs.PyList_init2);
code.dup();
code.ldc("append");
if (mrefs.getattr == 0) {
mrefs.getattr = code.pool.Methodref(
"org/python/core/PyObject", "__getattr__",
"(" + $str + ")" + $pyObj);
}
code.invokevirtual(mrefs.getattr);
String tmp_append = "_[" + (++list_comprehension_count) + "]";
set(new Name(tmp_append, Name.Store, node));
stmtType n = new Expr(new Call(new Name(tmp_append, Name.Load, node),
new exprType[] { node.elt },
new keywordType[0], null, null, node),
node);
for (int i = node.generators.length - 1; i >= 0; i--) {
listcompType lc = node.generators[i];
for (int j = lc.ifs.length - 1; j >= 0; j--) {
n = new If(lc.ifs[j], new stmtType[] { n }, null, lc.ifs[j]);
}
n = new For(lc.target, lc.iter, new stmtType[] { n }, null, lc);
}
visit(n);
visit(new Delete(new exprType[] { new Name(tmp_append, Name.Del) }));
return null;
}
public Object visitDict(Dict node) throws Exception {
code.new_(code.pool.Class("org/python/core/PyDictionary"));
code.dup();
SimpleNode[] elts = new SimpleNode[node.keys.length * 2];
for (int i = 0; i < node.keys.length; i++) {
elts[i * 2] = node.keys[i];
elts[i * 2 + 1] = node.values[i];
}
makeArray(elts);
if (mrefs.PyDictionary_init == 0) {
mrefs.PyDictionary_init = code.pool.Methodref(
"org/python/core/PyDictionary", "",
"(" + $pyObjArr + ")V");
}
code.invokespecial(mrefs.PyDictionary_init);
return null;
}
public Object visitRepr(Repr node) throws Exception {
visit(node.value);
code.invokevirtual("org/python/core/PyObject", "__repr__",
"()" + $pyStr);
return null;
}
public int PyFunction_init1,PyFunction_closure_init1;
public Object visitLambda(Lambda node) throws Exception {
String name = "";
//Add a return node onto the outside of suite;
modType retSuite = new Suite(new stmtType[] {
new Return(node.body, node) }, node);
setline(node);
code.new_(code.pool.Class("org/python/core/PyFunction"));
code.dup();
loadFrame();
if (mrefs.f_globals == 0) {
mrefs.f_globals = code.pool.Fieldref("org/python/core/PyFrame",
"f_globals", $pyObj);
}
code.getfield(mrefs.f_globals);
ScopeInfo scope = module.getScopeInfo(node);
makeArray(scope.ac.getDefaults());
scope.setup_closure();
scope.dump();
module.PyCode(retSuite, name, true, className,
false, false, node.beginLine, scope, cflags).get(code);
if (!makeClosure(scope)) {
if (mrefs.PyFunction_init1 == 0) {
mrefs.PyFunction_init1 = code.pool.Methodref(
"org/python/core/PyFunction", "",
"(" + $pyObj + $pyObjArr + $pyCode + ")V");
}
code.invokespecial(mrefs.PyFunction_init1);
} else {
if (mrefs.PyFunction_closure_init1 == 0) {
mrefs.PyFunction_closure_init1 = code.pool.Methodref(
"org/python/core/PyFunction", "",
"(" + $pyObj + $pyObjArr + $pyCode + $pyObjArr + ")V");
}
code.invokespecial(mrefs.PyFunction_closure_init1);
}
return null;
}
public int Ellipsis;
public Object visitEllipsis(Ellipsis node) throws Exception {
if (mrefs.Ellipsis == 0) {
mrefs.Ellipsis = code.pool.Fieldref(
"org/python/core/Py", "Ellipsis",
"Lorg/python/core/PyObject;");
}
code.getstatic(mrefs.Ellipsis);
return null;
}
public int PySlice_init;
public Object visitSlice(Slice node) throws Exception {
code.new_(code.pool.Class("org/python/core/PySlice"));
code.dup();
if (node.lower == null) getNone(); else visit(node.lower);
if (node.upper == null) getNone(); else visit(node.upper);
if (node.step == null) getNone(); else visit(node.step);
if (mrefs.PySlice_init == 0) {
mrefs.PySlice_init = code.pool.Methodref(
"org/python/core/PySlice", "",
"(" + $pyObj + $pyObj + $pyObj + ")V");
}
code.invokespecial(mrefs.PySlice_init);
return null;
}
public int makeClass,makeClass_closure;
public Object visitClassDef(ClassDef node) throws Exception {
setline(node);
//Get class name
String name = getName(node.name);
//System.out.println("name: "+name);
code.ldc(name);
makeArray(node.bases);
ScopeInfo scope = module.getScopeInfo(node);
scope.setup_closure();
scope.dump();
//Make code object out of suite
module.PyCode(new Suite(node.body, node), name, false, name,
true, false, node.beginLine, scope, cflags).get(code);
//Get doc string (if there)
getDocString(node.body);
//Make class out of name, bases, and code
if (!makeClosure(scope)) {
if (mrefs.makeClass == 0) {
mrefs.makeClass = code.pool.Methodref(
"org/python/core/Py", "makeClass",
"(" + $str + $pyObjArr + $pyCode + $pyObj + ")" + $pyObj);
}
code.invokestatic(mrefs.makeClass);
} else {
if (mrefs.makeClass_closure == 0) {
mrefs.makeClass_closure = code.pool.Methodref(
"org/python/core/Py", "makeClass",
"(" + $str + $pyObjArr + $pyCode + $pyObj + $pyObjArr + ")" +
$pyObj);
}
code.invokestatic(mrefs.makeClass_closure);
}
//Assign this new class to the given name
set(new Name(node.name, Name.Store, node));
return null;
}
public Object visitNum(Num node) throws Exception {
if (node.n instanceof PyInteger) {
module.PyInteger(((PyInteger) node.n).getValue()).get(code);
} else if (node.n instanceof PyLong) {
module.PyLong(((PyObject)node.n).__str__().toString()).get(code);
} else if (node.n instanceof PyFloat) {
module.PyFloat(((PyFloat) node.n).getValue()).get(code);
} else if (node.n instanceof PyComplex) {
module.PyComplex(((PyComplex) node.n).imag).get(code);
}
return null;
}
private String getName(String name) {
if (className != null && name.startsWith("__") &&
!name.endsWith("__"))
{
//remove leading '_' from classname
int i = 0;
while (className.charAt(i) == '_')
i++;
return "_"+className.substring(i)+name;
}
return name;
}
int getglobal, getlocal1, getlocal2;
int setglobal, setlocal1, setlocal2;
int delglobal, dellocal1, dellocal2;
int getderef,setderef;
void emitGetGlobal(String name) throws Exception {
code.ldc(name);
if (mrefs.getglobal == 0) {
mrefs.getglobal = code.pool.Methodref(
"org/python/core/PyFrame", "getglobal",
"(" + $str + ")" + $pyObj);
}
code.invokevirtual(mrefs.getglobal);
}
public Object visitName(Name node) throws Exception {
String name;
if (fast_locals)
name = node.id;
else
name = getName(node.id);
SymInfo syminf = (SymInfo)tbl.get(name);
int ctx = node.ctx;
if (ctx == node.AugStore) {
ctx = augmode;
}
switch (ctx) {
case Name.Load:
loadFrame();
if (syminf != null) {
int flags = syminf.flags;
if ((flags&ScopeInfo.GLOBAL) !=0 || optimizeGlobals&&
(flags&(ScopeInfo.BOUND|ScopeInfo.CELL|
ScopeInfo.FREE))==0) {
emitGetGlobal(name);
return null;
}
if (fast_locals) {
if ((flags&ScopeInfo.CELL) != 0) {
code.iconst(syminf.env_index);
if (mrefs.getderef == 0) {
mrefs.getderef = code.pool.Methodref(
"org/python/core/PyFrame", "getderef",
"(I)" + $pyObj);
}
code.invokevirtual(mrefs.getderef);
return null;
}
if ((flags&ScopeInfo.BOUND) != 0) {
code.iconst(syminf.locals_index);
if (mrefs.getlocal2 == 0) {
mrefs.getlocal2 = code.pool.Methodref(
"org/python/core/PyFrame", "getlocal",
"(I)" + $pyObj);
}
code.invokevirtual(mrefs.getlocal2);
return null;
}
}
if ((flags&ScopeInfo.FREE) != 0 &&
(flags&ScopeInfo.BOUND) == 0) {
code.iconst(syminf.env_index);
if (mrefs.getderef == 0) {
mrefs.getderef = code.pool.Methodref(
"org/python/core/PyFrame", "getderef",
"(I)" + $pyObj);
}
code.invokevirtual(mrefs.getderef);
return null;
}
}
code.ldc(name);
if (mrefs.getlocal1 == 0) {
mrefs.getlocal1 = code.pool.Methodref(
"org/python/core/PyFrame", "getname",
"(" + $str + ")" + $pyObj);
}
code.invokevirtual(mrefs.getlocal1);
return null;
case Name.Store:
loadFrame();
if (syminf != null && (syminf.flags&ScopeInfo.GLOBAL) != 0) {
code.ldc(name);
code.aload(temporary);
if (mrefs.setglobal == 0) {
mrefs.setglobal = code.pool.Methodref(
"org/python/core/PyFrame", "setglobal",
"(" + $str + $pyObj + ")V");
}
code.invokevirtual(mrefs.setglobal);
} else {
if (!fast_locals) {
code.ldc(name);
code.aload(temporary);
if (mrefs.setlocal1 == 0) {
mrefs.setlocal1 = code.pool.Methodref(
"org/python/core/PyFrame", "setlocal",
"(" + $str + $pyObj + ")V");
}
code.invokevirtual(mrefs.setlocal1);
} else {
if (syminf == null) {
System.err.println("internal compiler error: "+node);
}
if ((syminf.flags&ScopeInfo.CELL) != 0) {
code.iconst(syminf.env_index);
code.aload(temporary);
if (mrefs.setderef == 0) {
mrefs.setderef = code.pool.Methodref(
"org/python/core/PyFrame", "setderef",
"(I" + $pyObj + ")V");
}
code.invokevirtual(mrefs.setderef);
} else {
code.iconst(syminf.locals_index);
code.aload(temporary);
if (mrefs.setlocal2 == 0) {
mrefs.setlocal2 = code.pool.Methodref(
"org/python/core/PyFrame", "setlocal",
"(I" + $pyObj + ")V");
}
code.invokevirtual(mrefs.setlocal2);
}
}
}
return null;
case Name.Del: {
loadFrame();
if (syminf != null && (syminf.flags&ScopeInfo.GLOBAL) != 0) {
code.ldc(name);
if (mrefs.delglobal == 0) {
mrefs.delglobal = code.pool.Methodref(
"org/python/core/PyFrame", "delglobal",
"(" + $str + ")V");
}
code.invokevirtual(mrefs.delglobal);
} else {
if (!fast_locals) {
code.ldc(name);
if (mrefs.dellocal1 == 0) {
mrefs.dellocal1 = code.pool.Methodref(
"org/python/core/PyFrame", "dellocal",
"(" + $str + ")V");
}
code.invokevirtual(mrefs.dellocal1);
} else {
if (syminf == null) {
System.err.println("internal compiler error: "+node);
}
if ((syminf.flags&ScopeInfo.CELL) != 0) {
module.error("can not delete variable '"+name+
"' referenced in nested scope",true,node);
}
code.iconst(syminf.locals_index);
if (mrefs.dellocal2 == 0) {
mrefs.dellocal2 = code.pool.Methodref(
"org/python/core/PyFrame", "dellocal",
"(I)V");
}
code.invokevirtual(mrefs.dellocal2);
}
}
return null; }
}
return null;
}
public Object visitUnicode(Unicode node) throws Exception {
String s = node.s;
if (s.length() > 32767) {
throw new ParseException(
"string constant too large (more than 32767 characters)",
node);
}
module.PyUnicode(s).get(code);
return null;
}
public Object visitStr(Str node) throws Exception {
String s = node.s;
if (s.length() > 32767) {
throw new ParseException(
"string constant too large (more than 32767 characters)",
node);
}
module.PyString(s).get(code);
return null;
}
protected Object unhandled_node(SimpleNode node) throws Exception {
throw new Exception("Unhandled node " + node);
}
/**
* Data about a given exception range whether a try:finally: or a
* try:except:. The finally needs to inline the finally block for
* each exit of the try: section, so we carry around that data for it.
*
* Both of these need to stop exception coverage of an area that is either
* the inlined finally of a parent try:finally: or the reentry block after
* a yield. Thus we keep around a set of exception ranges that the
* catch block will eventually handle.
*/
class ExceptionHandler {
/**
* Each handler gets several exception ranges, this is because inlined
* finally exit code shouldn't be covered by the exception handler of
* that finally block. Thus each time we inline the finally code, we
* stop one range and then enter a new one.
*
* We also need to stop coverage for the recovery of the locals after
* a yield.
*/
public Vector exceptionStarts = new Vector();
public Vector exceptionEnds = new Vector();
public boolean bodyDone = false;
public TryFinally node = null;
public ExceptionHandler() {
}
public ExceptionHandler(TryFinally n) {
node = n;
}
public boolean isFinallyHandler() {
return node != null;
}
public void addExceptionHandlers(Label handlerStart) throws Exception {
int throwable = code.pool.Class("java/lang/Throwable");
for (int i = 0; i < exceptionStarts.size(); ++i) {
Label start = (Label)exceptionStarts.elementAt(i);
Label end = (Label)exceptionEnds.elementAt(i);
if (start.getPosition() != end.getPosition()) {
code.addExceptionHandler(
(Label)exceptionStarts.elementAt(i),
(Label)exceptionEnds.elementAt(i),
handlerStart,
throwable);
}
}
}
}
}