/src/org/python/compiler/CodeCompiler.java
Java | 2443 lines | 1949 code | 366 blank | 128 comment | 370 complexity | 1397420fd7ba05d3a2c32bdaecccbfe2 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- // Copyright (c) Corporation for National Research Initiatives
- package org.python.compiler;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Map;
- import java.util.Stack;
- import java.util.Vector;
- import org.python.antlr.ParseException;
- import org.python.antlr.PythonTree;
- import org.python.antlr.Visitor;
- import org.python.antlr.ast.Assert;
- import org.python.antlr.ast.Assign;
- import org.python.antlr.ast.Attribute;
- import org.python.antlr.ast.AugAssign;
- import org.python.antlr.ast.BinOp;
- import org.python.antlr.ast.BoolOp;
- import org.python.antlr.ast.Break;
- import org.python.antlr.ast.Call;
- import org.python.antlr.ast.ClassDef;
- import org.python.antlr.ast.Compare;
- import org.python.antlr.ast.Continue;
- import org.python.antlr.ast.Delete;
- import org.python.antlr.ast.Dict;
- import org.python.antlr.ast.Ellipsis;
- import org.python.antlr.ast.ExceptHandler;
- import org.python.antlr.ast.Exec;
- import org.python.antlr.ast.Expr;
- import org.python.antlr.ast.Expression;
- import org.python.antlr.ast.ExtSlice;
- import org.python.antlr.ast.For;
- import org.python.antlr.ast.FunctionDef;
- import org.python.antlr.ast.GeneratorExp;
- import org.python.antlr.ast.Global;
- import org.python.antlr.ast.If;
- import org.python.antlr.ast.IfExp;
- import org.python.antlr.ast.Import;
- import org.python.antlr.ast.ImportFrom;
- import org.python.antlr.ast.Index;
- import org.python.antlr.ast.Interactive;
- import org.python.antlr.ast.Lambda;
- import org.python.antlr.ast.List;
- import org.python.antlr.ast.ListComp;
- import org.python.antlr.ast.Name;
- import org.python.antlr.ast.Num;
- import org.python.antlr.ast.Pass;
- import org.python.antlr.ast.Print;
- import org.python.antlr.ast.Raise;
- import org.python.antlr.ast.Repr;
- import org.python.antlr.ast.Return;
- import org.python.antlr.ast.Slice;
- import org.python.antlr.ast.Str;
- import org.python.antlr.ast.Subscript;
- import org.python.antlr.ast.Suite;
- import org.python.antlr.ast.TryExcept;
- import org.python.antlr.ast.TryFinally;
- import org.python.antlr.ast.Tuple;
- import org.python.antlr.ast.UnaryOp;
- import org.python.antlr.ast.While;
- import org.python.antlr.ast.With;
- import org.python.antlr.ast.Yield;
- import org.python.antlr.ast.alias;
- import org.python.antlr.ast.cmpopType;
- import org.python.antlr.ast.comprehension;
- import org.python.antlr.ast.expr_contextType;
- import org.python.antlr.ast.keyword;
- import org.python.antlr.ast.operatorType;
- import org.python.antlr.base.expr;
- import org.python.antlr.base.mod;
- import org.python.antlr.base.stmt;
- import org.python.core.CompilerFlags;
- import org.python.core.ContextGuard;
- import org.python.core.ContextManager;
- 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.core.PyString;
- import org.python.core.PyUnicode;
- import org.objectweb.asm.ClassWriter;
- import org.objectweb.asm.Label;
- import org.objectweb.asm.Opcodes;
- import org.objectweb.asm.Type;
- import org.objectweb.asm.commons.Method;
- public class CodeCompiler extends Visitor implements Opcodes, 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 ClassWriter cw;
- public Code code;
- public CodeCompiler mrefs;
- public CompilerFlags cflags;
- int temporary;
- expr_contextType augmode;
- int augtmp1;
- int augtmp2;
- int augtmp3;
- int augtmp4;
- public boolean fast_locals, print_results;
- public Map<String, SymInfo> 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;
- int yield_count = 0;
-
- private Stack<String> stack = new Stack<String>();
- public CodeCompiler(Module module, boolean print_results) {
- this.module = module;
- this.print_results = print_results;
- mrefs = this;
- cw = module.classfile.cw;
- continueLabels = new Stack();
- breakLabels = new Stack();
- exceptionHandlers = new Stack();
- }
- public void getNone() throws IOException {
- code.getstatic("org/python/core/Py", "None", $pyObj);
- }
- public void loadFrame() throws Exception {
- code.aload(1);
- }
- public void loadThreadState() throws Exception {
- code.aload(2);
- }
- public void setLastI(int idx) throws Exception {
- loadFrame();
- code.iconst(idx);
- code.putfield("org/python/core/PyFrame", "f_lasti", "I");
- }
-
- private void loadf_back() throws Exception {
- code.getfield("org/python/core/PyFrame", "f_back", $pyFrame);
- }
- public int storeTop() throws Exception {
- int tmp = code.getLocal("org/python/core/PyObject");
- code.astore(tmp);
- return tmp;
- }
- public void setline(int line) throws Exception {
- if (module.linenumbers) {
- code.setline(line);
- loadFrame();
- code.iconst(line);
- code.invokevirtual("org/python/core/PyFrame", "setline", "(I)V");
- }
- }
- public void setline(PythonTree node) throws Exception {
- setline(node.getLine());
- }
- public void set(PythonTree node) throws Exception {
- int tmp = storeTop();
- set(node, tmp);
- code.aconst_null();
- code.astore(tmp);
- code.freeLocal(tmp);
- }
- public void set(PythonTree node, int tmp) throws Exception {
- temporary = tmp;
- visit(node);
- }
- private void saveAugTmps(PythonTree node, int count) throws Exception {
- if (count >= 4) {
- augtmp4 = code.getLocal("Lorg/python/core/PyObject;");
- code.astore(augtmp4);
- }
- if (count >= 3) {
- augtmp3 = code.getLocal("Lorg/python/core/PyObject;");
- code.astore(augtmp3);
- }
- if (count >= 2) {
- augtmp2 = code.getLocal("Lorg/python/core/PyObject;");
- code.astore(augtmp2);
- }
- augtmp1 = code.getLocal("Lorg/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(PythonTree 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(mod 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;
-
- if (scope.max_with_count > 0) {
- // allocate for all the with-exits we will have in the frame;
- // this allows yield and with to happily co-exist
- loadFrame();
- code.iconst(scope.max_with_count);
- code.anewarray("org/python/core/PyObject");
- code.putfield("org/python/core/PyFrame", "f_exits", $pyObjArr);
- }
- Object exit = visit(node);
- if (classBody) {
- loadFrame();
- code.invokevirtual("org/python/core/PyFrame", "getf_locals", "()" + $pyObj);
- code.areturn();
- } else {
- if (exit == null) {
- setLastI(-1);
- getNone();
- code.areturn();
- }
- }
- }
- @Override
- public Object visitInteractive(Interactive node) throws Exception {
- traverse(node);
- return null;
- }
- @Override
- public Object visitModule(org.python.antlr.ast.Module suite)
- throws Exception
- {
- if (suite.getInternalBody().size() > 0 &&
- suite.getInternalBody().get(0) instanceof Expr &&
- ((Expr) suite.getInternalBody().get(0)).getInternalValue() instanceof Str)
- {
- loadFrame();
- code.ldc("__doc__");
- visit(((Expr) suite.getInternalBody().get(0)).getInternalValue());
- code.invokevirtual("org/python/core/PyFrame", "setglobal", "(" +$str + $pyObj + ")V");
- }
- traverse(suite);
- return null;
- }
- @Override
- public Object visitExpression(Expression node) throws Exception {
- if (my_scope.generator && node.getInternalBody() != null) {
- module.error("'return' with argument inside generator",
- true, node);
- }
- return visitReturn(new Return(node,node.getInternalBody()), true);
- }
- public int makeArray(java.util.List<? extends PythonTree> nodes) throws Exception {
- // XXX: This should produce an array on the stack (if possible) instead of a local
- // the caller is responsible for freeing.
- int n;
- if (nodes == null)
- n = 0;
- else
- n = nodes.size();
- int array = code.getLocal("[Lorg/python/core/PyObject;");
- if (n == 0) {
- code.getstatic("org/python/core/Py", "EmptyObjects", $pyObjArr);
- code.astore(array);
- } else {
- code.iconst(n);
- code.anewarray("org/python/core/PyObject");
- code.astore(array);
- for(int i=0; i<n; i++) {
- visit(nodes.get(i));
- code.aload(array);
- code.swap();
- code.iconst(i);
- code.swap();
- code.aastore();
- }
- }
- return array;
- }
- // nulls out an array of references
- public void freeArray(int array) {
- code.aload(array);
- code.aconst_null();
- code.invokestatic("java/util/Arrays", "fill", "(" + $objArr + $obj + ")V");
- code.freeLocal(array);
- }
- public void getDocString(java.util.List<stmt> suite) throws Exception {
- if (suite.size() > 0 && suite.get(0) instanceof Expr &&
- ((Expr) suite.get(0)).getInternalValue() instanceof Str)
- {
- visit(((Expr) suite.get(0)).getInternalValue());
- } else {
- code.aconst_null();
- }
- }
- 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;
- int tmp = code.getLocal("[Lorg/python/core/PyObject;");
- code.iconst(n);
- code.anewarray("org/python/core/PyObject");
- code.astore(tmp);
- Map<String, SymInfo> upTbl = scope.up.tbl;
- for(int i=0; i<n; i++) {
- code.aload(tmp);
- code.iconst(i);
- loadFrame();
- for(int j = 1; j < scope.distance; j++) {
- loadf_back();
- }
- SymInfo symInfo = upTbl.get(scope.freevars.elementAt(i));
- code.iconst(symInfo.env_index);
- code.invokevirtual("org/python/core/PyFrame", "getclosure", "(I)" + $pyObj);
- code.aastore();
- }
- code.aload(tmp);
- code.freeLocal(tmp);
- return true;
- }
- @Override
- public Object visitFunctionDef(FunctionDef node) throws Exception {
- String name = getName(node.getInternalName());
- setline(node);
- ScopeInfo scope = module.getScopeInfo(node);
- // NOTE: this is attached to the constructed PyFunction, so it cannot be nulled out
- // with freeArray, unlike other usages of makeArray here
- int defaults = makeArray(scope.ac.getDefaults());
- code.new_("org/python/core/PyFunction");
- code.dup();
- loadFrame();
- code.getfield("org/python/core/PyFrame", "f_globals", $pyObj);
- code.aload(defaults);
- code.freeLocal(defaults);
- scope.setup_closure();
- scope.dump();
- module.PyCode(new Suite(node,node.getInternalBody()), name, true,
- className, false, false,
- node.getLine(), scope, cflags).get(code);
- getDocString(node.getInternalBody());
- if (!makeClosure(scope)) {
- code.invokespecial("org/python/core/PyFunction", "<init>", "(" + $pyObj + $pyObjArr + $pyCode + $pyObj + ")V");
- } else {
- code.invokespecial( "org/python/core/PyFunction", "<init>", "(" + $pyObj + $pyObjArr + $pyCode + $pyObj + $pyObjArr + ")V");
- }
-
- applyDecorators(node.getInternalDecorator_list());
- set(new Name(node,node.getInternalName(), expr_contextType.Store));
- return null;
- }
- private void applyDecorators(java.util.List<expr> decorators) throws Exception {
- if (decorators != null && !decorators.isEmpty()) {
- int res = storeTop();
- for (expr decorator : decorators) {
- visit(decorator); stackProduce();
- }
- for (int i = decorators.size(); i > 0; i--) {
- stackConsume();
- loadThreadState();
- code.aload(res);
- code.invokevirtual("org/python/core/PyObject", "__call__", "(" + $threadState + $pyObj + ")" + $pyObj);
- code.astore(res);
- }
- code.aload(res);
- code.freeLocal(res);
- }
- }
- @Override
- public Object visitExpr(Expr node) throws Exception {
- setline(node);
- visit(node.getInternalValue());
- if (print_results) {
- code.invokestatic("org/python/core/Py", "printResult", "(" + $pyObj + ")V");
- } else {
- code.pop();
- }
- return null;
- }
- @Override
- public Object visitAssign(Assign node) throws Exception {
- setline(node);
- visit(node.getInternalValue());
- if (node.getInternalTargets().size() == 1) {
- set(node.getInternalTargets().get(0));
- } else {
- int tmp = storeTop();
- for (expr target : node.getInternalTargets()) {
- set(target, tmp);
- }
- code.freeLocal(tmp);
- }
- return null;
- }
- @Override
- public Object visitPrint(Print node) throws Exception {
- setline(node);
- int tmp = -1;
- if (node.getInternalDest() != null) {
- visit(node.getInternalDest());
- tmp = storeTop();
- }
- if (node.getInternalValues() == null || node.getInternalValues().size() == 0) {
- if (node.getInternalDest() != null) {
- code.aload(tmp);
- code.invokestatic("org/python/core/Py", "printlnv", "(" + $pyObj + ")V");
- } else {
- code.invokestatic("org/python/core/Py", "println", "()V");
- }
- } else {
- for (int i = 0; i < node.getInternalValues().size(); i++) {
- if (node.getInternalDest() != null) {
- code.aload(tmp);
- visit(node.getInternalValues().get(i));
- if (node.getInternalNl() && i == node.getInternalValues().size() - 1) {
- code.invokestatic("org/python/core/Py", "println", "(" + $pyObj + $pyObj + ")V");
- } else {
- code.invokestatic("org/python/core/Py", "printComma", "(" + $pyObj + $pyObj + ")V");
- }
- } else {
- visit(node.getInternalValues().get(i));
- if (node.getInternalNl() && i == node.getInternalValues().size() - 1) {
- code.invokestatic("org/python/core/Py", "println", "(" + $pyObj + ")V");
- } else {
- code.invokestatic("org/python/core/Py", "printComma", "(" + $pyObj + ")V");
- }
- }
- }
- }
- if (node.getInternalDest() != null) {
- code.freeLocal(tmp);
- }
- return null;
- }
- @Override
- public Object visitDelete(Delete node) throws Exception {
- setline(node);
- traverse(node);
- return null;
- }
- @Override
- public Object visitPass(Pass node) throws Exception {
- setline(node);
- return null;
- }
- @Override
- 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;
- }
- @Override
- 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;
- }
- @Override
- public Object visitYield(Yield node) throws Exception {
- setline(node);
- if (!fast_locals) {
- throw new ParseException("'yield' outside function", node);
- }
- int stackState = saveStack();
-
- if (node.getInternalValue() != null) {
- visit(node.getInternalValue());
- } else {
- getNone();
- }
-
- setLastI(++yield_count);
-
- saveLocals();
- code.areturn();
- Label restart = new Label();
- yields.addElement(restart);
- code.label(restart);
- restoreLocals();
- restoreStack(stackState);
-
- loadFrame();
- code.invokevirtual("org/python/core/PyFrame", "getGeneratorInput", "()" + $obj);
- code.dup();
- code.instanceof_("org/python/core/PyException");
- Label done2 = new Label();
- code.ifeq(done2);
- code.checkcast("java/lang/Throwable");
- code.athrow();
- code.label(done2);
- code.checkcast("org/python/core/PyObject");
-
- return null;
- }
-
- private void stackProduce() {
- stackProduce("org/python/core/PyObject");
- }
-
- private void stackProduce(String signature) {
- stack.push(signature);
- }
- private void stackConsume() {
- stackConsume(1);
- }
-
- private void stackConsume(int numItems) {
- for (int i = 0; i < numItems; i++) {
- stack.pop();
- }
- }
- private int saveStack() throws Exception {
- if (stack.size() > 0) {
- int array = code.getLocal("[Ljava/lang/Object;");
- code.iconst(stack.size());
- code.anewarray("java/lang/Object");
- code.astore(array);
- for (int i = 0; i < stack.size(); i++) {
- code.aload(array);
- // Stack: |- ... value array
- code.swap();
- code.iconst(i);
- code.swap();
- // Stack: |- ... array index value
- code.aastore();
- // Stack: |- ...
- }
- return array;
- } else {
- return -1;
- }
- }
- private void restoreStack(int array) throws Exception {
- if (stack.size() > 0) {
- int i = stack.size() -1;
- for (String signature : stack) {
- code.aload(array);
- // Stack: |- ... array
- code.iconst(i);
- code.aaload();
- // Stack: |- ... value
- code.checkcast(signature);
- }
- code.freeLocal(array);
- }
- }
- private void restoreLocals() throws Exception {
- endExceptionHandlers();
-
- Vector v = code.getActiveLocals();
- loadFrame();
- code.getfield("org/python/core/PyFrame", "f_savedlocals", "[Ljava/lang/Object;");
- int locals = code.getLocal("[Ljava/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(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 = new Label();
- code.label(end);
- for (int i = 0; i < exceptionHandlers.size(); ++i) {
- ExceptionHandler handler =
- (ExceptionHandler)exceptionHandlers.elementAt(i);
- handler.exceptionEnds.addElement(end);
- }
- }
- private void restartExceptionHandlers()
- {
- Label start = new Label();
- code.label(start);
- 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();
- code.iconst(v.size());
- code.anewarray("java/lang/Object");
- int locals = code.getLocal("[Ljava/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();
- }
- loadFrame();
- code.aload(locals);
- code.putfield("org/python/core/PyFrame", "f_savedlocals", "[Ljava/lang/Object;");
- code.freeLocal(locals);
- }
- @Override
- 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.getInternalValue() != null) {
- if (my_scope.generator)
- throw new ParseException("'return' with argument " +
- "inside generator", node);
- visit(node.getInternalValue());
- tmp = code.getReturnLocal();
- code.astore(tmp);
- }
- doFinallysDownTo(0);
- setLastI(-1);
- if (node.getInternalValue() != null) {
- code.aload(tmp);
- } else {
- getNone();
- }
- code.areturn();
- return Exit;
- }
- @Override
- public Object visitRaise(Raise node) throws Exception {
- setline(node);
- if (node.getInternalType() != null) { visit(node.getInternalType()); stackProduce(); }
- if (node.getInternalInst() != null) { visit(node.getInternalInst()); stackProduce(); }
- if (node.getInternalTback() != null) { visit(node.getInternalTback()); stackProduce(); }
- if (node.getInternalType() == null) {
- code.invokestatic("org/python/core/Py", "makeException", "()" + $pyExc);
- } else if (node.getInternalInst() == null) {
- stackConsume();
- code.invokestatic("org/python/core/Py", "makeException", "(" + $pyObj + ")" + $pyExc);
- } else if (node.getInternalTback() == null) {
- stackConsume(2);
- code.invokestatic("org/python/core/Py", "makeException", "(" + $pyObj + $pyObj + ")" + $pyExc);
- } else {
- stackConsume(3);
- code.invokestatic("org/python/core/Py", "makeException", "(" + $pyObj + $pyObj + $pyObj + ")" + $pyExc);
- }
- code.athrow();
- return Exit;
- }
- @Override
- public Object visitImport(Import node) throws Exception {
- setline(node);
- for (alias a : node.getInternalNames()) {
- String asname = null;
- if (a.getInternalAsname() != null) {
- String name = a.getInternalName();
- asname = a.getInternalAsname();
- code.ldc(name);
- loadFrame();
- code.invokestatic("org/python/core/imp", "importOneAs", "(" + $str + $pyFrame + ")" + $pyObj);
- } else {
- String name = a.getInternalName();
- asname = name;
- if (asname.indexOf('.') > 0)
- asname = asname.substring(0, asname.indexOf('.'));
- code.ldc(name);
- loadFrame();
- code.invokestatic("org/python/core/imp", "importOne", "(" + $str + $pyFrame + ")" + $pyObj);
- }
- set(new Name(a, asname, expr_contextType.Store));
- }
- return null;
- }
- @Override
- public Object visitImportFrom(ImportFrom node) throws Exception {
- Future.checkFromFuture(node); // future stmt support
- setline(node);
- code.ldc(node.getInternalModule());
- java.util.List<alias> names = node.getInternalNames();
- if (names == null || names.size() == 0) {
- throw new ParseException("Internel parser error", node);
- } else if (names.size() == 1 && names.get(0).getInternalName().equals("*")) {
- if (node.getInternalLevel() > 0) {
- throw new ParseException("'import *' not allowed with 'from .'", node);
- }
- if (my_scope.func_level > 0) {
- module.error("import * only allowed at module level", false, node);
- if (my_scope.contains_ns_free_vars) {
- module.error("import * is not allowed in function '" +
- my_scope.scope_name +
- "' because it contains a nested function with free variables",
- true, node);
- }
- }
- if (my_scope.func_level > 1) {
- module.error("import * is not allowed in function '" +
- my_scope.scope_name +
- "' because it is a nested function",
- true, node);
- }
-
- loadFrame();
- code.invokestatic("org/python/core/imp", "importAll", "(" + $str + $pyFrame + ")V");
- } else {
- java.util.List<String> fromNames = new ArrayList<String>();//[names.size()];
- java.util.List<String> asnames = new ArrayList<String>();//[names.size()];
- for (int i = 0; i < names.size(); i++) {
- fromNames.add(names.get(i).getInternalName());
- asnames.add(names.get(i).getInternalAsname());
- if (asnames.get(i) == null)
- asnames.set(i, fromNames.get(i));
- }
- int strArray = makeStrings(code, fromNames);
- code.aload(strArray);
- code.freeLocal(strArray);
- loadFrame();
- if (node.getInternalLevel() == 0) {
- if (module.getFutures().isAbsoluteImportOn()) {
- code.iconst_0();
- } else {
- code.iconst_m1();
- }
- } else {
- code.iconst(node.getInternalLevel());
- }
- code.invokestatic("org/python/core/imp", "importFrom", "(" + $str + $strArr + $pyFrame + "I" + ")" + $pyObjArr);
- int tmp = storeTop();
- for (int i = 0; i < names.size(); i++) {
- code.aload(tmp);
- code.iconst(i);
- code.aaload();
- set(new Name(names.get(i), asnames.get(i), expr_contextType.Store));
- }
- code.freeLocal(tmp);
- }
- return null;
- }
- @Override
- public Object visitGlobal(Global node) throws Exception {
- return null;
- }
- @Override
- public Object visitExec(Exec node) throws Exception {
- setline(node);
- visit(node.getInternalBody());
- stackProduce();
- if (node.getInternalGlobals() != null) {
- visit(node.getInternalGlobals());
- } else {
- code.aconst_null();
- }
- stackProduce();
- if (node.getInternalLocals() != null) {
- visit(node.getInternalLocals());
- } else {
- code.aconst_null();
- }
- stackProduce();
- //do the real work here
- stackConsume(3);
- code.invokestatic("org/python/core/Py", "exec", "(" + $pyObj + $pyObj + $pyObj + ")V");
- return null;
- }
- @Override
- public Object visitAssert(Assert node) throws Exception {
- setline(node);
- Label end_of_assert = new Label();
-
- /* First do an if __debug__: */
- loadFrame();
- emitGetGlobal("__debug__");
- code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z");
- 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.getInternalTest());
- code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z");
- /* If evaluation is false, then branch to end of method */
- code.ifne(end_of_assert);
- /* Visit the message part of the assertion, or pass Py.None */
- if( node.getInternalMsg() != null ) {
- visit(node.getInternalMsg());
- } else {
- getNone();
- }
-
- /* Push exception type onto stack(Py.AssertionError) */
- code.getstatic("org/python/core/Py", "AssertionError", "Lorg/python/core/PyObject;");
-
- code.swap(); // The type is the first argument, but the message could be a yield
-
- code.invokestatic("org/python/core/Py", "makeException", "(" + $pyObj + $pyObj + ")" + $pyExc);
-
- /* Raise assertion error. Only executes this logic if assertion
- failed */
- code.athrow();
-
- /* And finally set the label for the end of it all */
- code.label(end_of_assert);
- return null;
- }
- public Object doTest(Label end_of_if, If node, int index)
- throws Exception
- {
- Label end_of_suite = new Label();
- setline(node.getInternalTest());
- visit(node.getInternalTest());
- code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z");
- code.ifeq(end_of_suite);
- Object exit = suite(node.getInternalBody());
- if (end_of_if != null && exit == null)
- code.goto_(end_of_if);
- code.label(end_of_suite);
- if (node.getInternalOrelse() != null) {
- return suite(node.getInternalOrelse()) != null ? exit : null;
- } else {
- return null;
- }
- }
- @Override
- public Object visitIf(If node) throws Exception {
- Label end_of_if = null;
- if (node.getInternalOrelse() != null)
- end_of_if = new Label();
- Object exit = doTest(end_of_if, node, 0);
- if (end_of_if != null)
- code.label(end_of_if);
- return exit;
- }
- @Override
- public Object visitIfExp(IfExp node) throws Exception {
- setline(node.getInternalTest());
- Label end = new Label();
- Label end_of_else = new Label();
- visit(node.getInternalTest());
- code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z");
- code.ifeq(end_of_else);
- visit(node.getInternalBody());
- code.goto_(end);
- code.label(end_of_else);
- visit(node.getInternalOrelse());
- code.label(end);
- return null;
- }
- public int beginLoop() {
- continueLabels.push(new Label());
- breakLabels.push(new Label());
- int savebcf = bcfLevel;
- bcfLevel = exceptionHandlers.size();
- return savebcf;
- }
- public void finishLoop(int savebcf) {
- continueLabels.pop();
- breakLabels.pop();
- bcfLevel = savebcf;
- }
- @Override
- 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 = new Label();
- code.goto_(continue_loop);
- code.label(start_loop);
- //Do suite
- suite(node.getInternalBody());
- code.label(continue_loop);
- setline(node);
- //Do test
- visit(node.getInternalTest());
- code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z");
- code.ifne(start_loop);
- finishLoop(savebcf);
- if (node.getInternalOrelse() != null) {
- //Do else
- suite(node.getInternalOrelse());
- }
- code.label(break_loop);
- // Probably need to detect "guaranteed exits"
- return null;
- }
- @Override
- 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 = new Label();
- Label next_loop = new Label();
- 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.getInternalIter());
- //set up the loop iterator
- code.invokevirtual("org/python/core/PyObject", "__iter__", "()Lorg/python/core/PyObject;");
- code.astore(iter_tmp);
- //do check at end of loop. Saves one opcode ;-)
- code.goto_(next_loop);
- code.label(start_loop);
- //set iter variable to current entry in list
- set(node.getInternalTarget(), expr_tmp);
- //evaluate for body
- suite(node.getInternalBody());
- code.label(continue_loop);
- code.label(next_loop);
- setline(node);
- //get the next element from the list
- code.aload(iter_tmp);
- code.invokevirtual("org/python/core/PyObject", "__iternext__", "()" + $pyObj);
- code.astore(expr_tmp);
- code.aload(expr_tmp);
- //if no more elements then fall through
- code.ifnonnull(start_loop);
- finishLoop(savebcf);
- if (node.getInternalOrelse() != null) {
- //Do else clause if provided
- suite(node.getInternalOrelse());
- }
- code.label(break_loop);
- code.freeLocal(iter_tmp);
- code.freeLocal(expr_tmp);
- // Probably need to detect "guaranteed exits"
- return null;
- }
- public void exceptionTest(int exc, Label end_of_exceptions,
- TryExcept node, int index)
- throws Exception
- {
- for (int i = 0; i < node.getInternalHandlers().size(); i++) {
- ExceptHandler handler = (ExceptHandler)node.getInternalHandlers().get(i);
- //setline(name);
- Label end_of_self = new Label();
- if (handler.getInternalType() != null) {
- code.aload(exc);
- //get specific exception
- visit(handler.getInternalType());
- code.invokevirtual("org/python/core/PyException", "match", "(" + $pyObj + ")Z");
- code.ifeq(end_of_self);
- } else {
- if (i != node.getInternalHandlers().size()-1) {
- throw new ParseException(
- "default 'except:' must be last", handler);
- }
- }
- if (handler.getInternalName() != null) {
- code.aload(exc);
- code.getfield("org/python/core/PyException", "value", "Lorg/python/core/PyObject;");
- set(handler.getInternalName());
- }
- //do exception body
- suite(handler.getInternalBody());
- code.goto_(end_of_exceptions);
- code.label(end_of_self);
- }
- code.aload(exc);
- code.athrow();
- }
-
- @Override
- public Object visitTryFinally(TryFinally node) throws Exception
- {
- Label start = new Label();
- Label end = new Label();
- Label handlerStart = new Label();
- Label finallyEnd = new Label();
- 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);
- code.label(start);
- inFinally.exceptionStarts.addElement(start);
- ret = suite(node.getInternalBody());
- code.label(end);
- 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
- code.label(handlerStart);
- code.astore(excLocal);
- code.aload(excLocal);
- loadFrame();
- code.invokestatic("org/python/core/Py", "addTraceback", "(" + $throwable + $pyFrame + ")V");
- inlineFinally(inFinally);
- code.aload(excLocal);
- code.checkcast("java/lang/Throwable");
- code.athrow();
- code.label(finallyEnd);
- 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.
- Label end = new Label();
- code.label(end);
- handler.exceptionEnds.addElement(end);
- // also exiting the try: portion of this particular finally
- }
- if (handler.isFinallyHandler()) {
- handler.finalBody(this);
- }
- }
-
- private void reenterProtectedBody(ExceptionHandler handler) throws Exception {
- // restart exception coverage
- Label restart = new Label();
- code.label(restart);
- handler.exceptionStarts.addElement(restart);
- }
-
- /**
- * 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);
- }
- }
-
- @Override
- public Object visitTryExcept(TryExcept node) throws Exception {
- Label start = new Label();
- Label end = new Label();
- Label handler_start = new Label();
- Label handler_end = new Label();
- ExceptionHandler handler = new ExceptionHandler();
- code.label(start);
- handler.exceptionStarts.addElement(start);
- exceptionHandlers.push(handler);
- //Do suite
- Object exit = suite(node.getInternalBody());
- exceptionHandlers.pop();
- code.label(end);
- handler.exceptionEnds.addElement(end);
- if (exit == null)
- code.goto_(handler_end);
- code.label(handler_start);
- loadFrame();
- code.invokestatic("org/python/core/Py", "setException", "(" + $throwable + $pyFrame + ")" + $pyExc);
- int exc = code.getFinallyLocal("java/lang/Throwable");
- code.astore(exc);
- if (node.getInternalOrelse() == null) {
- //No else clause to worry about
- exceptionTest(exc, handler_end, node, 1);
- code.label(handler_end);
- } else {
- //Have else clause
- Label else_end = new Label();
- exceptionTest(exc, else_end, node, 1);
- code.label(handler_end);
- //do else clause
- suite(node.getInternalOrelse());
- code.label(else_end);
- }
- code.freeFinallyLocal(exc);
- handler.addExceptionHandlers(handler_start);
- return null;
- }
- @Override
- public Object visitSuite(Suite node) throws Exception {
- return suite(node.getInternalBody());
- }
- public Object suite(java.util.List<stmt> stmts) throws Exception {
- for(stmt s: stmts) {
- Object exit = visit(s);
- if (exit != null)
- return Exit;
- }
- return null;
- }
- @Override
- public Object visitBoolOp(BoolOp node) throws Exception {
- Label end = new Label();
- visit(node.getInternalValues().get(0));
- for (int i = 1; i < node.getInternalValues().size(); i++) {
- code.dup();
- code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z");
- switch (node.getInternalOp()) {
- case Or :
- code.ifne(end);
- break;
- case And :
- code.ifeq(end);
- break;
- }
- code.pop();
- visit(node.getInternalValues().get(i));
- }
- code.label(end);
- return null;
- }
- @Override
- public Object visitCompare(Compare node) throws Exception {
- int last = code.getLocal("org/python/core/PyObject");
- int result = code.getLocal("org/python/core/PyObject");
- Label end = new Label();
- visit(node.getInternalLeft());
- code.astore(last);
- int n = node.getInternalOps().size();
- for(int i = 0; i < n - 1; i++) {
- visit(node.getInternalComparators().get(i));
- code.aload(last);
- code.swap();
- code.dup();
- code.astore(last);
- visitCmpop(node.getInternalOps().get(i));
- code.dup();
- code.astore(result);
- code.invokevirtual("org/python/core/PyObject", "__nonzero__", "()Z");
- code.ifeq(end);
- }
- visit(node.getInternalComparators().get(n-1));
- code.aload(last);
- code.swap();
- visitCmpop(node.getInternalOps().get(n-1));
- if (n > 1) {
- code.astore(result);
- code.label(end);
- code.aload(result);
- }
- code.aconst_null();
- code.astore(last);
- code.freeLocal(last);
- code.freeLocal(result);
- return null;
- }
- public void visitCmpop(cmpopType op) throws Exception {
- String name = null;
- switch (op) {
- case Eq: name = "_eq"; break;
- case NotEq: name = "_ne"; break;
- case Lt: name = "_lt"; break;
- case LtE: name = "_le"; break;
- case Gt: name = "_gt"; break;
- case GtE: name = "_ge"; break;
- case Is: name = "_is"; break;
- case IsNot: name = "_isnot"; break;
- case In: name = "_in"; break;
- case NotIn: name = "_notin"; break;
- }
- code.invokevirtual("org/python/core/PyObject", name, "(" + $pyObj + ")" + $pyObj);
- }
- @Override
- public Object visitBinOp(BinOp node) throws Exception {
- visit(node.getInternalLeft());
- stackProduce();
- visit(node.getInternalRight());
- stackConsume();
- String name = null;
- switch (node.getInternalOp()) {
- case Add: name = "_add"; break;
- case Sub: name = "_sub"; break;
- case Mult: name = "_mul"; break;
- case Div: name = "_div"; break;
- case Mod: name = "_mod"; break;
- case Pow: name = "_pow"; break;
- case LShift: name = "_lshift"; break;
- case RShift: name = "_rshift"; break;
- case BitOr: name = "_or"; break;
- case BitXor: name = "_xor"; break;
- case BitAnd: name = "_and"; break;
- case FloorDiv: name = "_floordiv"; break;
- }
- if (node.getInternalOp() == operatorType.Div && module.getFutures().areDivisionOn()) {
- name = "_truediv";
- }
- code.invokevirtual("org/python/core/PyObject", name, "(" + $pyObj + ")" + $pyObj);
- return null;
- }
-
- @Override
- public Object visitUnaryOp(UnaryOp node) throws Exception {
- visit(node.getInternalOperand());
- String name = null;
- switch (node.getInternalOp()) {
- case Invert: name = "__invert__"; break;
- case Not: name = "__not__"; break;
- case UAdd: name = "__pos__"; break;
- case USub: name = "__neg__"; break;
- }
- code.invokevirtual("org/python/core/PyObject", name, "()" + $pyObj);
- return null;
- }
- @Override
- public Object visitAugAssign(AugAssign node) throws Exception {
- setline(node);
- augmode = expr_contextType.Load;
- visit(node.getInternalTarget());
- int target = storeTop();
- visit(node.getInternalValue());
- code.aload(target);
- code.swap();
- String name = null;
- switch (node.getInternalOp()) {
- case Add: name = "_iadd"; break;
- case Sub: name = "_isub"; break;
- case Mult: name = "_imul"; break;
- case Div: name = "_idiv"; break;
- case Mod: name = "_imod"; break;
- case Pow: name = "_ipow"; break;
- case LShift: name = "_ilshift"; break;
- case RShift: name = "_irshift"; break;
- case BitOr: name = "_ior"; break;
- case BitXor: name = "_ixor"; break;
- case BitAnd: name = "_iand"; break;
- case FloorDiv: name = "_ifloordiv"; break;
- }
- if (node.getInternalOp() == operatorType.Div && module.getFutures().areDivisionOn()) {
- name = "_itruediv";
- }
- code.invokevirtual("org/python/core/PyObject", name, "(" + $pyObj + ")" + $pyObj);
- code.freeLocal(target);
- temporary = storeTop();
- augmode = expr_contextType.Store;
- visit(node.getInternalTarget());
- code.freeLocal(temporary);
- return null;
- }
- public static int makeStrings(Code c, Collection<String> names)
- throws IOException
- {
- if (names != null) {
- c.iconst(names.size());
- } else {
- c.iconst_0();
- }
- c.anewarray("java/lang/String");
- int strings = c.getLocal("[Ljava/lang/String;");
- c.astore(strings);
- if (names != null) {
- int i = 0;
- for (String name : names) {
- c.aload(strings);
- c.iconst(i);
- c.ldc(name);
- c.aastore();
- i++;
- }
- }
- return strings;
- }
-
- public Object invokeNoKeywords(Attribute node, java.util.List<expr> values)
- throws Exception
- {
- String name = getName(node.getInternalAttr());
- visit(node.getInternalValue()); stackProduce();
- code.ldc(name);
- code.invokevirtual("org/python/core/PyObject", "__getattr__", "(" + $str + ")" + $pyObj);
- loadThreadState(); stackProduce("org/python/core/ThreadState");
- switch (values.size()) {
- case 0:
- stackConsume(2); // target + ts
- code.invokevirtual("org/python/core/PyObject", "__call__", "(" + $threadState + ")" + $pyObj);
- break;
- case 1:
- visit(values.get(0));
- stackConsume(2); // target + ts
- code.invokevirtual("org/python/core/PyObject", "__call__", "(" + $threadState + $pyObj + ")" + $pyObj);
- break;
- case 2:
- visit(values.get(0)); stackProduce();
- visit(values.get(1)…
Large files files are truncated, but you can click here to view the full file