Commits

Shashank Bharadwaj committed 8fcedc5

Importing the upgrading the ASM to v4 patch

  • Participants
  • Parent commits 4b061dc

Comments (0)

Files changed (34)

 	<classpathentry kind="lib" path="extlibs/mysql-connector-java-5.1.6.jar"/>
 	<classpathentry kind="lib" path="extlibs/postgresql-8.3-603.jdbc4.jar"/>
 	<classpathentry kind="lib" path="extlibs/servlet-api-2.5.jar"/>
-	<classpathentry kind="lib" path="extlibs/asm-4.0.jar"/>
+	<classpathentry kind="lib" path="extlibs/asm-4.0.jar" sourcepath="/home/shashank/bin/asm-4.0/src.zip"/>
 	<classpathentry kind="lib" path="extlibs/asm-commons-4.0.jar"/>
-	<classpathentry kind="lib" path="extlibs/asm-util-4.0.jar"/>
+	<classpathentry kind="lib" path="extlibs/asm-util-4.0.jar" sourcepath="/home/shashank/bin/asm-4.0/src.zip"/>
 	<classpathentry kind="var" path="ANT_HOME/lib/ant.jar"/>
 	<classpathentry kind="lib" path="extlibs/antlr-runtime-3.1.3.jar"/>
 	<classpathentry kind="lib" path="extlibs/constantine.jar"/>
 .idea/misc.xml
 .idea/workspace.xml
 
+.lint4jprefs
+
 .AppleDouble
 .DS_Store
 .classpath
 				</dictionary>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>com.jutils.lint4j.core.Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>org.python.pydev.pythonNature</nature>
+		<nature>com.jutils.lint4j.core.Nature</nature>
 	</natures>
 </projectDescription>
             <pathelement path="${extlibs.dir}/asm-4.0.jar" />
             <pathelement path="${extlibs.dir}/asm-commons-4.0.jar" />
             <pathelement path="${extlibs.dir}/asm-util-4.0.jar" />
+        	<pathelement path="${extlibs.dir}/asm-all-4.0.jar" />
             <pathelement path="${extlibs.dir}/constantine.jar" />
             <pathelement path="${extlibs.dir}/guava-11.0.2.jar" />
             <pathelement path="${extlibs.dir}/jaffl.jar"/>

File extlibs/asm-all-4.0.jar

Binary file added.

File src/org/python/antlr/ast/ExceptionRangeStart.java

+package org.python.antlr.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Label;
+import org.python.antlr.base.stmt;
+import org.python.compiler.cfg.Edge;
+
+/**
+ * Node indicating the start of an try-block
+ */
+public class ExceptionRangeStart extends stmt {
+
+    public List<stmt> stmts;
+    public List<Edge> outEdges;
+
+    public Label start;
+
+    public ExceptionRangeStart() {
+        this.stmts = new ArrayList<stmt>();
+        this.outEdges = new ArrayList<Edge>();
+        this.start = new Label();
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitExceptionRangeStart(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        // visitor.visitSuite(new Suite(getToken(), stmts));
+    }
+
+    @Override
+    public String toString() {
+        if (outEdges.size() == 1) {
+            return "Start (" + outEdges.get(0).getDestination().start + ") " + start;
+        }
+        return "ExceptionRangeStart";
+    }
+
+    @Override
+    public String toStringTree() {
+        return "Start (" + outEdges.get(0).getDestination().start + ") " + start;
+    }
+
+    public void addOutgoing(Edge edge) {
+        this.outEdges.add(edge);
+    }
+
+}

File src/org/python/antlr/ast/ExceptionRangeStop.java

+package org.python.antlr.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Label;
+import org.python.antlr.base.stmt;
+import org.python.compiler.cfg.Edge;
+
+/**
+ * Node indicating the end of an try-block
+ */
+public class ExceptionRangeStop extends stmt {
+
+    public List<stmt> stmts;
+    public List<Edge> outEdges;
+
+    public Label end;
+
+    public ExceptionRangeStop() {
+        this.stmts = new ArrayList<stmt>();
+        this.outEdges = new ArrayList<Edge>();
+        this.end = new Label();
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitExceptionRangeStop(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        // visitor.visitSuite(new Suite(getToken(), stmts));
+    }
+
+    @Override
+    public String toString() {
+        if (outEdges.size() == 1) {
+            return "Stop (" + outEdges.get(0).getDestination().start + ") " + end;
+        }
+        return "ExceptionRangeStop";
+    }
+
+    @Override
+    public String toStringTree() {
+        return "Stop (" + outEdges.get(0).getDestination().start + ") " + end;
+    }
+
+    public void addOutgoing(Edge edge) {
+        this.outEdges.add(edge);
+    }
+
+}

File src/org/python/antlr/ast/FinallyGoto.java

+package org.python.antlr.ast;
+
+import org.objectweb.asm.Label;
+import org.python.antlr.base.stmt;
+import org.python.core.PyType;
+
+public class FinallyGoto extends stmt {
+	public static final PyType TYPE = PyType.fromClass(FinallyGoto.class);
+	
+	public Label goto_label;
+	
+	public FinallyGoto(Label goto_label) {
+		this.goto_label = goto_label;
+	}
+	
+    public String toString() {
+        return "FinallyGoto";
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitFinallyGoto(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        return;
+    }
+
+
+}

File src/org/python/antlr/ast/FinallyStart.java

+package org.python.antlr.ast;
+
+import java.util.List;
+
+import org.objectweb.asm.Label;
+import org.python.antlr.base.stmt;
+
+/**
+ * Node indicating the start of the finally region in a try-catch-finally block.
+ */
+public class FinallyStart extends HandlerStart {
+
+    public List<stmt> finalBody;
+    public Label finally_body_start;
+
+    public FinallyStart(List<stmt> fbody) {
+        super();
+        this.finalBody = fbody;
+        finally_body_start = new Label();
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitFinallyHandlerStart(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        // visitor.visitSuite(new Suite(getToken(), stmts));
+    }
+
+    @Override
+    public String toString() {
+        return "FinallyHandler " + start + " (" + startEdges.size() + ", " + stopEdges.size() + ")";
+    }
+
+}

File src/org/python/antlr/ast/HandlerStart.java

+package org.python.antlr.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Label;
+import org.python.compiler.cfg.Edge;
+
+/**
+ * Node indicating the start of a catch handler block.
+ */
+public class HandlerStart extends ExceptHandler {
+
+    public List<Edge> startEdges;
+    public List<Edge> stopEdges;
+
+    public Label start;
+    public Label end;
+
+    public HandlerStart() {
+        this.startEdges = new ArrayList<Edge>();
+        this.stopEdges = new ArrayList<Edge>();
+        start = new Label();
+        end = new Label();
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitHandlerStart(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        // visitor.visitSuite(new Suite(getToken(), stmts));
+    }
+
+    @Override
+    public String toString() {
+        return "Handler " + start + " (" + startEdges.size() + ", " + stopEdges.size() + ")";
+    }
+
+    @Override
+    public String toStringTree() {
+        return toString();
+    }
+
+    public void addIncomingStart(Edge edge) {
+        this.startEdges.add(edge);
+    }
+
+    public void addIncomingStop(Edge edge) {
+        this.stopEdges.add(edge);
+    }
+
+}

File src/org/python/antlr/ast/TryCatchBlock.java

+package org.python.antlr.ast;
+
+import org.objectweb.asm.Label;
+import org.python.antlr.base.stmt;
+
+/**
+ * A node containing the labels for a try-catch block.
+ */
+public class TryCatchBlock extends stmt {
+
+    public Label handler;
+    public Label start;
+    public Label end;
+    public String type;
+
+    public TryCatchBlock(Label start, Label end, Label handler_start, String type) {
+        this.start = start;
+        this.end = end;
+        this.handler = handler_start;
+        this.type = type;
+    }
+
+    @Override
+    public String toString() {
+        return "TryCatchBlock(" + start + ", " + end + ", " + handler + ")";
+    }
+
+    @Override
+    public String toStringTree() {
+        return this.toString();
+    }
+
+    @Override
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitTryCatchBlock(this);
+    }
+
+    @Override
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        // nothing to do
+    }
+
+}

File src/org/python/antlr/ast/VisitorBase.java

         return ret;
     }
 
+    public R visitExceptionRangeStart(ExceptionRangeStart node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+    
+    public R visitExceptionRangeStop(ExceptionRangeStop node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitHandlerStart(HandlerStart node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitFinallyHandlerStart(FinallyStart node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitTryCatchBlock(TryCatchBlock node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitWithSpecialLoad(WithSpecialLoad node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitWithExit(WithExit node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitYieldReturn(YieldReturn node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+    public R visitYieldRestoreLocals(YieldRestoreLocals node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitYieldInput(YieldInput node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
+    public R visitFinallyGoto(FinallyGoto node) throws Exception {
+        R ret = unhandled_node(node);
+        traverse(node);
+        return ret;
+    }
+
     abstract protected R unhandled_node(PythonTree node) throws Exception;
     abstract public void traverse(PythonTree node) throws Exception;
 }

File src/org/python/antlr/ast/VisitorIF.java

     public R visitExtSlice(ExtSlice node) throws Exception;
     public R visitIndex(Index node) throws Exception;
     public R visitExceptHandler(ExceptHandler node) throws Exception;
+    public R visitExceptionRangeStart(ExceptionRangeStart node) throws Exception;
+    public R visitExceptionRangeStop(ExceptionRangeStop node) throws Exception;
+    public R visitHandlerStart(HandlerStart node) throws Exception;
+    public R visitFinallyHandlerStart(FinallyStart node) throws Exception;
+    public R visitTryCatchBlock(TryCatchBlock node) throws Exception;
+    public R visitWithSpecialLoad(WithSpecialLoad node) throws Exception;
+    public R visitWithExit(WithExit node) throws Exception;
+    public R visitYieldReturn(YieldReturn node) throws Exception;
+    public R visitYieldRestoreLocals(YieldRestoreLocals node) throws Exception;
+    public R visitYieldInput(YieldInput node) throws Exception;
+	public R visitFinallyGoto(FinallyGoto node) throws Exception;
 }

File src/org/python/antlr/ast/WithExit.java

+package org.python.antlr.ast;
+
+import org.python.antlr.base.expr;
+import org.python.antlr.base.stmt;
+import org.python.core.PyType;
+
+/**
+ * A node indicating the __exit__ block of a <code>with</code> statement.
+ */
+public class WithExit extends stmt {
+    public static final PyType TYPE = PyType.fromClass(WithExit.class);
+
+    public static final int EXIT_IN_EXCEPT = 1;
+    public static final int EXIT_IN_FINALLY = 2;
+
+    public int typeOfAssign;
+    public expr manager;
+    public expr exception;
+
+    /**
+     * @param typeOfAssign
+     *            should be one of EXIT, ENTER or MGR.
+     * @param manager
+     * @param exception
+     */
+    public WithExit(int typeOfAssign, expr manager, Name exception) {
+        this.typeOfAssign = typeOfAssign;
+        this.manager = manager;
+        this.exception = exception;
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitWithExit(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        if (manager != null)
+            manager.accept(visitor);
+    }
+
+    @Override
+    public String toString() {
+        return "SpecialAssign(" + typeOfAssign + ")";
+    }
+
+}

File src/org/python/antlr/ast/WithSpecialLoad.java

+package org.python.antlr.ast;
+
+import org.python.antlr.base.expr;
+import org.python.core.PyType;
+
+/**
+ * Node for the special loads for the <code>with</code> statement.
+ */
+public class WithSpecialLoad extends expr {
+    public static final PyType TYPE = PyType.fromClass(WithSpecialLoad.class);
+
+    public static final int EXIT_IN_EXCEPT = 1;
+    public static final int ENTER = 2;
+    public static final int MGR = 3;
+
+    public int typeOfAssign;
+    public expr extraExpr;
+
+    /**
+     * @param typeOfAssign
+     *            should be one of EXIT, ENTER or MGR.
+     * @param optionalExpr
+     */
+    public WithSpecialLoad(int typeOfAssign, expr optionalExpr) {
+        this.typeOfAssign = typeOfAssign;
+        this.extraExpr = optionalExpr;
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitWithSpecialLoad(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        if (extraExpr != null)
+            extraExpr.accept(visitor);
+    }
+
+    @Override
+    public String toString() {
+        return "SpecialAssign(" + typeOfAssign + ")";
+    }
+
+}

File src/org/python/antlr/ast/YieldInput.java

+package org.python.antlr.ast;
+
+import org.python.antlr.base.expr;
+import org.python.core.PyType;
+
+/**
+ * A node to represent the work of loading of the input value of a
+ * <code>yield</code> expression (sent via <code>send</code>).
+ */
+public class YieldInput extends expr {
+    public static final PyType TYPE = PyType.fromClass(YieldInput.class);
+
+    public String toString() {
+        return "YieldInput";
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitYieldInput(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        return;
+    }
+
+}

File src/org/python/antlr/ast/YieldRestoreLocals.java

+package org.python.antlr.ast;
+
+import org.python.antlr.base.stmt;
+import org.python.core.PyType;
+
+/**
+ * A node representing the work of restoring the local variables when the
+ * generator resumes.
+ */
+public class YieldRestoreLocals extends stmt {
+    public static final PyType TYPE = PyType.fromClass(YieldRestoreLocals.class);
+
+    public String toString() {
+        return "YieldRestoreLocals";
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitYieldRestoreLocals(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        return;
+    }
+
+}

File src/org/python/antlr/ast/YieldReturn.java

+package org.python.antlr.ast;
+
+import org.python.antlr.base.expr;
+import org.python.antlr.base.stmt;
+import org.python.core.PyType;
+
+/**
+ * A node representing the work in a generator of returning a yielded value.
+ */
+public class YieldReturn extends stmt {
+    public static final PyType TYPE = PyType.fromClass(YieldReturn.class);
+
+    public expr value;
+
+    public YieldReturn(Yield yield) {
+        this.value = yield.getInternalValue();
+    }
+
+    public YieldReturn(expr value) {
+        this.value = value;
+    }
+
+    public String toString() {
+        return "YieldReturn";
+    }
+
+    public String toStringTree() {
+        StringBuffer sb = new StringBuffer("YieldReturn(");
+        sb.append("value=");
+        sb.append(dumpThis(value));
+        sb.append(",");
+        sb.append(")");
+        return sb.toString();
+    }
+
+    public <R> R accept(VisitorIF<R> visitor) throws Exception {
+        return visitor.visitYieldReturn(this);
+    }
+
+    public void traverse(VisitorIF<?> visitor) throws Exception {
+        if (value != null)
+            value.accept(visitor);
+    }
+
+}

File src/org/python/compiler/Code.java

     }
 
     public void visitLabel(Label arg0) {
+        if(arg0 == null)
+            return;
         mv.visitLabel(arg0);
     }
 
     }
     
     public void setline(int line) {
-        mv.visitLineNumber(line, new Label());
+        Label start = new Label();
+        this.visitLabel(start);
+        mv.visitLineNumber(line, start);
     }
 
     @Override

File src/org/python/compiler/CodeCompiler.java

 import org.python.antlr.ast.Assign;
 import org.python.antlr.ast.Attribute;
 import org.python.antlr.ast.AugAssign;
+import org.python.antlr.ast.ExceptionRangeStart;
 import org.python.antlr.ast.BinOp;
 import org.python.antlr.ast.BoolOp;
 import org.python.antlr.ast.Break;
 import org.python.antlr.ast.Dict;
 import org.python.antlr.ast.DictComp;
 import org.python.antlr.ast.Ellipsis;
+import org.python.antlr.ast.ExceptionRangeStop;
+import org.python.antlr.ast.FinallyGoto;
+import org.python.antlr.ast.FinallyStart;
+import org.python.antlr.ast.HandlerStart;
 import org.python.antlr.ast.ExceptHandler;
 import org.python.antlr.ast.Exec;
 import org.python.antlr.ast.Expr;
 import org.python.antlr.ast.Str;
 import org.python.antlr.ast.Subscript;
 import org.python.antlr.ast.Suite;
+import org.python.antlr.ast.TryCatchBlock;
 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.WithExit;
+import org.python.antlr.ast.WithSpecialLoad;
 import org.python.antlr.ast.Yield;
+import org.python.antlr.ast.YieldInput;
+import org.python.antlr.ast.YieldRestoreLocals;
+import org.python.antlr.ast.YieldReturn;
 import org.python.antlr.ast.alias;
 import org.python.antlr.ast.cmpopType;
 import org.python.antlr.ast.comprehension;
 import org.python.antlr.base.expr;
 import org.python.antlr.base.mod;
 import org.python.antlr.base.stmt;
+import org.python.compiler.cfg.IRBuilder;
 import org.python.core.CompilerFlags;
 import org.python.core.ContextGuard;
 import org.python.core.ContextManager;
     private boolean optimizeGlobals = true;
     private String className;
     private Stack<Label> continueLabels, breakLabels;
-    private Stack<ExceptionHandler> exceptionHandlers;
     private Vector<Label> yields = new Vector<Label>();
 
     /*
      * PyCode, in other words: each 'function'.  When returning through
      * finally's all the exceptionHandlers are executed.
      */
-    private int bcfLevel = 0;
     private int yield_count = 0;
     private Stack<String> stack = new Stack<String>();
 
 
         continueLabels = new Stack<Label>();
         breakLabels = new Stack<Label>();
-        exceptionHandlers = new Stack<ExceptionHandler>();
     }
 
     public void getNone() throws IOException {
             throw new ParseException("'break' outside loop", node);
         }
 
-        doFinallysDownTo(bcfLevel);
-
         code.goto_(breakLabels.peek());
         return null;
     }
             throw new ParseException("'continue' not properly in loop", node);
         }
 
-        doFinallysDownTo(bcfLevel);
-
         code.goto_(continueLabels.peek());
         return Exit;
     }
 
+    int stackState;
+
     @Override
-    public Object visitYield(Yield node) throws Exception {
+    public Object visitYieldReturn(YieldReturn node) throws Exception {
         setline(node);
         if (!fast_locals) {
             throw new ParseException("'yield' outside function", node);
         }
 
-        int stackState = saveStack();
+        stackState = saveStack();
 
-        if (node.getInternalValue() != null) {
-            visit(node.getInternalValue());
+        if (node.value != null) {
+            visit(node.value);
         } else {
             getNone();
         }
 
         saveLocals();
         code.areturn();
+        return null;
+    }
 
+    @Override
+    public Object visitYieldRestoreLocals(YieldRestoreLocals node) throws Exception {
         Label restart = new Label();
         yields.addElement(restart);
         code.label(restart);
         restoreLocals();
+        return null;
+    }
+
+    @Override
+    public Object visitYieldInput(YieldInput node) throws Exception {
         restoreStack(stackState);
 
         loadFrame();
     }
 
     private void restoreLocals() throws Exception {
-        endExceptionHandlers();
-
         Vector<String> v = code.getActiveLocals();
 
         loadFrame();
             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 = 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 = exceptionHandlers.elementAt(i);
-            handler.exceptionStarts.addElement(start);
-        }
     }
 
     private void saveLocals() throws Exception {
             tmp = code.getReturnLocal();
             code.astore(tmp);
         }
-        doFinallysDownTo(0);
 
         setLastI(-1);
 
     }
 
     /**
-     * Push the import level <code>0</code> or <code>-1</code>. 
+     * Push the import level <code>0</code> or <code>-1</code>.
      */
     private void defaultImportLevel() {
     	// already prepared for a future change of DEFAULT_LEVEL
             code.iconst_0();
         } else {
             code.iconst_m1();
-        }    	
+        }
     }
-    
+
     @Override
     public Object visitImport(Import node) throws Exception {
         setline(node);
     public int beginLoop() {
         continueLabels.push(new Label());
         breakLabels.push(new Label());
-        int savebcf = bcfLevel;
-        bcfLevel = exceptionHandlers.size();
-        return savebcf;
+        return 0;
     }
 
     public void finishLoop(int savebcf) {
         continueLabels.pop();
         breakLabels.pop();
-        bcfLevel = savebcf;
     }
 
     @Override
         code.ifnonnull(start_loop);
 
         finishLoop(savebcf);
+        code.freeLocal(iter_tmp);
+        code.freeLocal(expr_tmp);
 
         if (node.getInternalOrelse() != null) {
             //Do else clause if provided
 
         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++) {
+        int beg = 0;
+        if(node.getInternalHandlers().get(0) instanceof HandlerStart){
+          ++beg;
+        }
+        for (int i = beg; i < node.getInternalHandlers().size(); i++) {
             ExceptHandler handler = (ExceptHandler) node.getInternalHandlers().get(i);
 
             //setline(name);
                 code.aload(exc);
                 code.getfield(p(PyException.class), "value", ci(PyObject.class));
                 set(handler.getInternalName());
+                // support with statement
+                if (handler.getInternalName() instanceof Name
+                        && ((Name) handler.getInternalName()).getInternalId().startsWith("with$")) {
+                    code.aload(exc);
+                }
             }
 
             //do exception body
     }
 
     @Override
+    public Object visitTryCatchBlock(TryCatchBlock node) throws Exception {
+    	code.visitTryCatchBlock(node.start, node.end, node.handler, node.type);
+    	return null;
+    }
+
+    @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);
+        TryExcept finallyExpr = (TryExcept) node.getInternalFinalbody().remove(0);
+        FinallyStart handlerBlock = (FinallyStart) finallyExpr.getInternalHandlers().get(0);
+        Label handler_start = handlerBlock.start;
+        Label handler_end = handlerBlock.end;
 
         // Do protected suite
-        exceptionHandlers.push(inFinally);
-
         int excLocal = code.getLocal(p(Throwable.class));
         code.aconst_null();
         code.astore(excLocal);
 
-        code.label(start);
-        inFinally.exceptionStarts.addElement(start);
+        suite(node.getInternalBody());
 
-        ret = suite(node.getInternalBody());
-
-        code.label(end);
-        inFinally.exceptionEnds.addElement(end);
-        inFinally.bodyDone = true;
-
-        exceptionHandlers.pop();
-
-        if (ret == NoExit) {
-            inlineFinally(inFinally);
-            code.goto_(finallyEnd);
-        }
+        code.goto_(handlerBlock.finally_body_start);
 
         // Handle any exceptions that get thrown in suite
-        code.label(handlerStart);
+        code.label(handler_start);
         code.astore(excLocal);
 
         code.aload(excLocal);
         code.invokestatic(p(Py.class), "addTraceback",
                 sig(Void.TYPE, Throwable.class, PyFrame.class));
 
-        inlineFinally(inFinally);
+        code.label(handlerBlock.finally_body_start);
+        suite(node.getInternalFinalbody());
+
+        code.aload(excLocal);
+        code.ifnull(handler_end);
         code.aload(excLocal);
         code.checkcast(p(Throwable.class));
         code.athrow();
 
-        code.label(finallyEnd);
-
+        code.label(handler_end);
         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);
-        }
+    @Override
+    public Object visitFinallyGoto(FinallyGoto node) throws Exception {
+    	code.goto_(node.goto_label);
+    	return null;
+    }
+    
+    @Override
+    public Object visitExceptionRangeStart(ExceptionRangeStart node) throws Exception {
+        code.label(node.start);
+        return null;
     }
 
-    private void reenterProtectedBody(ExceptionHandler handler) throws Exception {
-        // restart exception coverage
-        Label restart = new Label();
-        code.label(restart);
-        handler.exceptionStarts.addElement(restart);
+    @Override
+    public Object visitExceptionRangeStop(ExceptionRangeStop node) throws Exception {
+        code.label(node.end);
+        return null;
     }
 
-    /**
-     *  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<ExceptionHandler> poppedHandlers = new Stack<ExceptionHandler>();
-        while (exceptionHandlers.size() > level) {
-            ExceptionHandler handler = exceptionHandlers.pop();
-            inlineFinally(handler);
-            poppedHandlers.push(handler);
-        }
-        while (poppedHandlers.size() > 0) {
-            ExceptionHandler handler = poppedHandlers.pop();
-            reenterProtectedBody(handler);
-            exceptionHandlers.push(handler);
-        }
+    @Override
+    public Object visitHandlerStart(HandlerStart node) throws Exception {
+        // XXX:: visit the nodes' label or is there nothing to do?
+        return null;
+    }
+
+    @Override
+    public Object visitFinallyHandlerStart(FinallyStart node) throws Exception {
+        return super.visitHandlerStart(node);
     }
 
     @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();
+        HandlerStart handlerBlock = (HandlerStart) node.getInternalHandlers().get(0);
+        Label handler_start = handlerBlock.start;
+        Label handler_end = handlerBlock.end;
 
-        code.label(start);
-        handler.exceptionStarts.addElement(start);
-        exceptionHandlers.push(handler);
-        //Do suite
+        // Do suite
         Object exit = suite(node.getInternalBody());
-        exceptionHandlers.pop();
-        code.label(end);
-        handler.exceptionEnds.addElement(end);
 
-        if (exit == null) {
+        if (exit == NoExit) {
             code.goto_(handler_end);
         }
 
         code.label(handler_start);
-
         loadFrame();
 
-        code.invokestatic(p(Py.class), "setException", sig(PyException.class, Throwable.class,
-                PyFrame.class));
+        code.invokestatic(p(Py.class), "setException",
+                sig(PyException.class, Throwable.class, PyFrame.class));
 
         int exc = code.getFinallyLocal(p(Throwable.class));
         code.astore(exc);
 
         if (node.getInternalOrelse() == null) {
-            //No else clause to worry about
+            // No else clause to worry about
             exceptionTest(exc, handler_end, node, 1);
             code.label(handler_end);
         } else {
-            //Have else clause
+            // Have else clause
             Label else_end = new Label();
             exceptionTest(exc, else_end, node, 1);
             code.label(handler_end);
 
-            //do else clause
+            // do else clause
             suite(node.getInternalOrelse());
             code.label(else_end);
         }
 
         code.freeFinallyLocal(exc);
-        handler.addExceptionHandlers(handler_start);
         return null;
     }
 
     }
 
     public Object suite(java.util.List<stmt> stmts) throws Exception {
+    	Object ret = null;
         for (stmt s : stmts) {
             Object exit = visit(s);
             if (exit != null) {
-                return Exit;
+                ret = exit;
             }
         }
-        return null;
+        return ret;
     }
 
     @Override
             super(tree, value);
         }
     }
-    
+
     @Override
     public Object visitLambda(Lambda node) throws Exception {
         String name = "<lambda>";
         scope.setup_closure();
         scope.dump();
 
-        stmt n = new Expr(node, new Yield(node, node.getInternalElt()));
+        // TODO(shashank): Move such transformations into IRBuilder
+        stmt n = null;
+        java.util.List<stmt> yield = new ArrayList<stmt>();
+        yield.add(new YieldReturn(node.getInternalElt()));
+        yield.add(new YieldRestoreLocals());
+        yield.add(new Expr(node.getToken(), new YieldInput()));
 
         expr iter = null;
         for (int i = node.getInternalGenerators().size() - 1; i >= 0; i--) {
             comprehension comp = node.getInternalGenerators().get(i);
             for (int j = comp.getInternalIfs().size() - 1; j >= 0; j--) {
                 java.util.List<stmt> bod = new ArrayList<stmt>();
-                bod.add(n);
+                if (n == null)
+                    bod.addAll(yield);
+                else
+                    bod.add(n);
                 n = new If(comp.getInternalIfs().get(j), comp.getInternalIfs().get(j), bod,
                         new ArrayList<stmt>());
             }
             java.util.List<stmt> bod = new ArrayList<stmt>();
-            bod.add(n);
+            if (n == null)
+                bod.addAll(yield);
+            else
+                bod.add(n);
+
             if (i != 0) {
                 n = new For(comp, comp.getInternalTarget(), comp.getInternalIter(), bod,
                         new ArrayList<stmt>());
         }
 
         java.util.List<stmt> bod = new ArrayList<stmt>();
-        bod.add(n);
+
+        if (n == null)
+            bod.addAll(yield);
+        else
+            bod.add(n);
+
         module.codeConstant(new Suite(node, bod), "<genexpr>", true,
                 className, false, false,
                 node.getLine(), scope, cflags).get(code);
     }
 
     @Override
-    public Object visitWith(With node) throws Exception {
-        if (!module.getFutures().withStatementSupported()) {
-            throw new ParseException("'with' will become a reserved keyword in Python 2.6", node);
+    public Object visitWithExit(WithExit node) throws Exception {
+        final Method __exit__ = Method.getMethod(
+                "boolean __exit__ (org.python.core.ThreadState,org.python.core.PyException)");
+
+        Label label_end = new Label();
+        switch (node.typeOfAssign) {
+        case WithExit.EXIT_IN_EXCEPT:
+            visit(node.manager);
+            code.swap();
+            loadThreadState();
+            code.swap();
+            code.invokeinterface(Type.getType(ContextManager.class).getInternalName(),
+                    __exit__.getName(), __exit__.getDescriptor());
+            // # The exceptional case is handled here
+            // exc = False # implicit
+            // if not exit(*sys.exc_info()):
+            code.ifne(label_end);
+            //    raise
+            // # The exception is swallowed if exit() returns true
+            code.invokestatic(p(Py.class), "makeException", sig(PyException.class));
+            code.checkcast(p(Throwable.class));
+            code.athrow();
+            code.label(label_end);
+            break;
+        case WithExit.EXIT_IN_FINALLY:
+            visit(node.manager);
+            loadThreadState();
+            code.aconst_null();
+            code.invokeinterface(Type.getType(ContextManager.class).getInternalName(),
+                    __exit__.getName(), __exit__.getDescriptor());
+            code.pop();
+            break;
         }
+        return null;
+    }
 
-        final Label label_body_start = new Label();
-        final Label label_body_end = new Label();
-        final Label label_catch = new Label();
-        final Label label_end = new Label();
-
+    @Override
+    public Object visitWithSpecialLoad(WithSpecialLoad node) throws Exception {
         final Method contextGuard_getManager = Method.getMethod(
                 "org.python.core.ContextManager getManager (org.python.core.PyObject)");
         final Method __enter__ = Method.getMethod(
                 "org.python.core.PyObject __enter__ (org.python.core.ThreadState)");
-        final Method __exit__ = Method.getMethod(
-                "boolean __exit__ (org.python.core.ThreadState,org.python.core.PyException)");
 
-        // mgr = (EXPR)
-        visit(node.getInternalContext_expr());
-
-        // wrap the manager with the ContextGuard (or get it directly if it
-        // supports the ContextManager interface)
-        code.invokestatic(Type.getType(ContextGuard.class).getInternalName(),
-                contextGuard_getManager.getName(), contextGuard_getManager.getDescriptor());
-        code.dup();
-
-
-        final int mgr_tmp = code.getLocal(Type.getType(ContextManager.class).getInternalName());
-        code.astore(mgr_tmp);
-
-        // value = mgr.__enter__()
-        loadThreadState();
-        code.invokeinterface(Type.getType(ContextManager.class).getInternalName(),
-                __enter__.getName(), __enter__.getDescriptor());
-        int value_tmp = code.getLocal(p(PyObject.class));
-        code.astore(value_tmp);
-
-        // exc = True # not necessary, since we don't exec finally if exception
-
-        // FINALLY (preparation)
-        // ordinarily with a finally, we need to duplicate the code. that's not the case
-        // here
-        // # The normal and non-local-goto cases are handled here
-        // if exc: # implicit
-        //     exit(None, None, None)
-        ExceptionHandler normalExit = new ExceptionHandler() {
-
-            @Override
-            public boolean isFinallyHandler() {
-                return true;
-            }
-
-            @Override
-            public void finalBody(CodeCompiler compiler) throws Exception {
-                compiler.code.aload(mgr_tmp);
-                loadThreadState();
-                compiler.code.aconst_null();
-                compiler.code.invokeinterface(Type.getType(ContextManager.class).getInternalName(),
-                        __exit__.getName(), __exit__.getDescriptor());
-                compiler.code.pop();
-            }
-        };
-        exceptionHandlers.push(normalExit);
-
-        // try-catch block here
-        ExceptionHandler handler = new ExceptionHandler();
-        exceptionHandlers.push(handler);
-        handler.exceptionStarts.addElement(label_body_start);
-
-        // VAR = value  # Only if "as VAR" is present
-        code.label(label_body_start);
-        if (node.getInternalOptional_vars() != null) {
-            set(node.getInternalOptional_vars(), value_tmp);
+        switch (node.typeOfAssign) {
+        case WithSpecialLoad.ENTER:
+            visit(node.extraExpr);
+            loadThreadState();
+            code.invokeinterface(Type.getType(ContextManager.class).getInternalName(),
+                    __enter__.getName(), __enter__.getDescriptor());
+            break;
+        case WithSpecialLoad.MGR:
+            visit(node.extraExpr);
+            code.invokestatic(Type.getType(ContextGuard.class).getInternalName(),
+                    contextGuard_getManager.getName(), contextGuard_getManager.getDescriptor());
+            code.checkcast(p(PyObject.class));
+            break;
         }
-        code.freeLocal(value_tmp);
-
-        // BLOCK + FINALLY if non-local-goto
-        Object blockResult = suite(node.getInternalBody());
-        normalExit.bodyDone = true;
-        exceptionHandlers.pop();
-        exceptionHandlers.pop();
-        code.label(label_body_end);
-        handler.exceptionEnds.addElement(label_body_end);
-
-        // FINALLY if *not* non-local-goto
-        if (blockResult == NoExit) {
-            // BLOCK would have generated FINALLY for us if it exited (due to a break,
-            // continue or return)
-            inlineFinally(normalExit);
-            code.goto_(label_end);
-        }
-
-        // CATCH
-        code.label(label_catch);
-
-        loadFrame();
-        code.invokestatic(p(Py.class), "setException", sig(PyException.class, Throwable.class,
-                PyFrame.class));
-        code.aload(mgr_tmp);
-        code.swap();
-        loadThreadState();
-        code.swap();
-        code.invokeinterface(Type.getType(ContextManager.class).getInternalName(),
-                __exit__.getName(), __exit__.getDescriptor());
-
-        // # The exceptional case is handled here
-        // exc = False # implicit
-        // if not exit(*sys.exc_info()):
-        code.ifne(label_end);
-        //    raise
-        // # The exception is swallowed if exit() returns true
-        code.invokestatic(p(Py.class), "makeException", sig(PyException.class));
-        code.checkcast(p(Throwable.class));
-        code.athrow();
-
-        code.label(label_end);
-        code.freeLocal(mgr_tmp);
-
-        handler.addExceptionHandlers(label_catch);
         return null;
     }
 
         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 fin ally 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<Label> exceptionStarts = new Vector<Label>();
-        public Vector<Label> exceptionEnds = new Vector<Label>();
-        public boolean bodyDone = false;
-        public PythonTree node = null;
-
-        public ExceptionHandler() {
-        }
-
-        public ExceptionHandler(PythonTree n) {
-            node = n;
-        }
-
-        public boolean isFinallyHandler() {
-            return node != null;
-        }
-
-        public void addExceptionHandlers(Label handlerStart) throws Exception {
-            for (int i = 0; i < exceptionStarts.size(); ++i) {
-                Label start = exceptionStarts.elementAt(i);
-                Label end = exceptionEnds.elementAt(i);
-                //FIXME: not at all sure that getOffset() test is correct or necessary.
-                if (start.getOffset() != end.getOffset()) {
-                    code.trycatch(
-                            exceptionStarts.elementAt(i),
-                            exceptionEnds.elementAt(i),
-                            handlerStart,
-                            p(Throwable.class));
-                }
-            }
-        }
-
-        public void finalBody(CodeCompiler compiler) throws Exception {
-            if (node instanceof TryFinally) {
-                suite(((TryFinally) node).getInternalFinalbody());
-            }
-        }
-    }
 }

File src/org/python/compiler/Future.java

 import org.python.antlr.ast.Interactive;
 import org.python.antlr.ast.Module;
 import org.python.antlr.ast.Str;
+import org.python.antlr.ast.TryCatchBlock;
 import org.python.antlr.ast.alias;
 import org.python.antlr.base.mod;
 import org.python.antlr.base.stmt;
         int beg = 0;
         List<stmt> suite = null;
         if (node instanceof Module) {
-            suite = ((Module) node).getInternalBody();
-            if (suite.size() > 0 && suite.get(0) instanceof Expr
-                    && ((Expr) suite.get(0)).getInternalValue() instanceof Str) {
-                beg++;
-            }
+          suite = ((Module) node).getInternalBody();
+          // Skip the Try-catch blocks added by different passes
+          while (suite.size() > beg && suite.get(beg) instanceof TryCatchBlock){
+            beg++;
+          }
+          // Skip the doc string
+          if (suite.size() > beg && suite.get(beg) instanceof Expr
+                  && ((Expr) suite.get(beg)).getInternalValue() instanceof Str) {
+              beg++;
+          }
         } else if (node instanceof Interactive) {
             suite = ((Interactive) node).getInternalBody();
         } else {

File src/org/python/compiler/JDK7Compiler.java

+package org.python.compiler;
+
+import org.python.antlr.ast.TryCatchBlock;
+import org.python.antlr.base.mod;
+import org.python.compiler.cfg.IRBuilder;
+import org.python.compiler.cfg.IRPrinter;
+import org.python.compiler.cfg.StampTryCatch;
+import org.python.core.CompilerFlags;
+import org.python.core.Py;
+import org.python.core.PythonCodeBundle;
+
+/**
+ * A compiler to generate JDK7 complaint bytecode.
+ *
+ * The DefaultCompiler first builds an intermediate representation (IR) (See
+ * {@link IRBuilder}). The IR is a very basic control flow graph (CFG) with
+ * edges between the start and end of a try-catch block. The IR is then passed
+ * to {@link StampTryCatch}, which will convert the edges to nodes and
+ * {@link TryCatchBlock} nodes into the IR. Then the {@link
+ * LegacyCompiler#compile(...)} is called to do the actual byte-code generation.
+ *
+ */
+public class JDK7Compiler extends LegacyCompiler {
+
+    private static final String TAG = "DefaultCompiler";
+
+    @Override
+    public PythonCodeBundle compile(mod node, String name, String filename, boolean linenumbers,
+            boolean printResults, CompilerFlags cflags) throws Exception {
+//        Py.writeDebug(TAG, "Initial tree\n" + IRPrinter.print(node));
+        mod new_node = (mod) new IRBuilder().visit(node);
+//        Py.writeDebug(TAG, "Successfully built the IR\n" + IRPrinter.print(new_node));
+        new_node = (mod) new StampTryCatch().visit(new_node);
+//        Py.writeDebug(TAG, "Tree after fully built\n" + IRPrinter.print(new_node));
+        return super.compile(new_node, name, filename, linenumbers, printResults, cflags);
+    }
+
+}

File src/org/python/compiler/LegacyCompiler.java

 public class LegacyCompiler implements PythonCompiler {
 
     public PythonCodeBundle compile(mod node, String name, String filename,
-            boolean linenumbers, boolean printResults, CompilerFlags cflags) {
+            boolean linenumbers, boolean printResults, CompilerFlags cflags) throws Exception {
         return new LazyLegacyBundle(node, name, filename, linenumbers,
                 printResults, cflags);
     }

File src/org/python/compiler/ScopesCompiler.java

 
 package org.python.compiler;
 
+import org.python.antlr.PythonTree;
 import org.python.antlr.Visitor;
-import org.python.antlr.PythonTree;
 import org.python.antlr.ast.ClassDef;
 import org.python.antlr.ast.DictComp;
 import org.python.antlr.ast.Exec;
 import org.python.antlr.ast.SetComp;
 import org.python.antlr.ast.With;
 import org.python.antlr.ast.Yield;
+import org.python.antlr.ast.YieldReturn;
 import org.python.antlr.ast.arguments;
 import org.python.antlr.ast.expr_contextType;
 import org.python.antlr.base.expr;
 
 import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Stack;
-import java.util.List;
 
 public class ScopesCompiler extends Visitor implements ScopeConstants {
 
         traverse(node);
         return null;
     }
+    
+    
+    @Override
+    public Object visitYieldReturn(YieldReturn node) throws Exception {
+        cur.defineAsGenerator(node.value);
+        cur.yield_count++;
+        traverse(node);
+        return null;
+    }
+
 
     @Override
     public Object visitYield(Yield node) throws Exception {
         return null;
     }
 
+
 }

File src/org/python/compiler/cfg/Edge.java

+package org.python.compiler.cfg;
+
+import org.objectweb.asm.Label;
+import org.python.antlr.ast.ExceptionRangeStart;
+import org.python.antlr.ast.ExceptionRangeStop;
+import org.python.antlr.ast.HandlerStart;
+import org.python.antlr.base.stmt;
+
+/**
+ * A class which represents an edge between two basic blocks
+ */
+public class Edge {
+    private stmt source;
+    private HandlerStart destination;
+
+    /**
+     * Create a new edge from source to destination. This constructor also takes
+     * care of updating those nodes to maintain links to this edge
+     * 
+     * @param source
+     * @param destination
+     */
+    public Edge(ExceptionRangeStart source, HandlerStart destination) {
+        this.destination = destination;
+        source.addOutgoing(this);
+        this.source = source;
+        destination.addIncomingStart(this);
+    }
+
+    public Edge(ExceptionRangeStop source, HandlerStart destination) {
+        this.destination = destination;
+        source.addOutgoing(this);
+        this.source = source;
+        destination.addIncomingStop(this);
+    }
+
+    public HandlerStart getDestination() {
+        return destination;
+    }
+
+    public stmt getSource() {
+        return source;
+    }
+
+    public Label getHandlerStart() {
+        return destination.start;
+    }
+
+    public Label getHandlerEnd() {
+        return (Label) destination.end;
+    }
+
+    @Override
+    public String toString() {
+        return "<" + source + " --> " + destination + "> ";
+    }
+
+}

File src/org/python/compiler/cfg/IRBuilder.java

+package org.python.compiler.cfg;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Stack;
+
+import org.antlr.runtime.Token;
+import org.objectweb.asm.Label;
+import org.python.antlr.ast.Assign;
+import org.python.antlr.ast.Break;
+import org.python.antlr.ast.Call;
+import org.python.antlr.ast.Continue;
+import org.python.antlr.ast.ExceptHandler;
+import org.python.antlr.ast.ExceptionRangeStart;
+import org.python.antlr.ast.ExceptionRangeStop;
+import org.python.antlr.ast.Expr;
+import org.python.antlr.ast.FinallyGoto;
+import org.python.antlr.ast.FinallyStart;
+import org.python.antlr.ast.For;
+import org.python.antlr.ast.FunctionDef;
+import org.python.antlr.ast.GeneratorExp;
+import org.python.antlr.ast.HandlerStart;
+import org.python.antlr.ast.If;
+import org.python.antlr.ast.Name;
+import org.python.antlr.ast.Pass;
+import org.python.antlr.ast.Return;
+import org.python.antlr.ast.Suite;
+import org.python.antlr.ast.TryExcept;
+import org.python.antlr.ast.TryFinally;
+import org.python.antlr.ast.While;
+import org.python.antlr.ast.With;
+import org.python.antlr.ast.WithExit;
+import org.python.antlr.ast.WithSpecialLoad;
+import org.python.antlr.ast.Yield;
+import org.python.antlr.ast.YieldInput;
+import org.python.antlr.ast.YieldRestoreLocals;
+import org.python.antlr.ast.YieldReturn;
+import org.python.antlr.ast.arguments;
+import org.python.antlr.ast.comprehension;
+import org.python.antlr.ast.expr_contextType;
+import org.python.antlr.ast.keyword;
+import org.python.antlr.base.excepthandler;
+import org.python.antlr.base.expr;
+import org.python.antlr.base.stmt;
+
+/**
+ * Builds an internal representation (IR) of the AST with simple try-catch
+ * blocks.
+ *
+ * This visitor runs through the AST to build a IR. The IR is very similar to
+ * the AST for most nodes, except for {@link TryExcept} and {@link TryFinally}.
+ */
+public class IRBuilder extends ScopedVisitor {
+
+    public static class CFGBuilderData {
+        public List<stmt> stmts;
+        public HandlerStart handler;
+
+        public CFGBuilderData() {
+            stmts = new ArrayList<stmt>();
+        }
+    }
+
+    Stack<CFGBuilderData> stack = new Stack<CFGBuilderData>();
+
+    CFGBuilderData data;
+
+    List<HandlerStart> endedHandlers = new ArrayList<HandlerStart>();
+
+    private int bcfLevel;
+
+    private int uniqueWith = 0;
+
+    private void beginBlock(HandlerStart handler) {
+        data = new CFGBuilderData();
+        if (handler != null) {
+            data.handler = handler;
+        }
+    }
+
+    private void endBlock() {
+        if (data == null) {
+            return;
+        }
+        stack.push(data);
+        data = null;
+    }
+
+    private void startNewExceptionRange() {
+        if (data.handler == null)
+            assert false: data;
+        ExceptionRangeStart start = new ExceptionRangeStart();
+        new Edge(start, data.handler);
+        data.stmts.add(start);
+    }
+
+    private void endCurrExceptionRange() {
+        if (data.handler == null)
+            assert false: data;
+        ExceptionRangeStop end = new ExceptionRangeStop();
+        new Edge(end, data.handler);
+        data.stmts.add(end);
+    }
+
+    private void endAllExceptions(boolean endThis, boolean endFinally) {
+        if (endThis) {
+            endCurrExceptionRange();
+        }
+        for (CFGBuilderData d : stack) {
+            if (d.handler != null && !(endedHandlers.contains(d.handler)) &&
+            		(endFinally || !(d.handler instanceof FinallyStart))) {
+                ExceptionRangeStop stop = new ExceptionRangeStop();
+                new Edge(stop, d.handler);
+                // add it to the current range
+                data.stmts.add(stop);
+                endedHandlers.add(d.handler);
+            }
+        }
+    }
+
+    private void restartAllExceptions(boolean includeThis, boolean restartFinally) {
+        if (includeThis) {
+            startNewExceptionRange();
+        }
+        for (CFGBuilderData d : stack) {
+            if (d.handler != null && endedHandlers.contains(d.handler) && 
+            		(restartFinally || !(d.handler instanceof FinallyStart))) {
+                ExceptionRangeStart start = new ExceptionRangeStart();
+                new Edge(start, d.handler);
+                // again add it to the curr range
+                data.stmts.add(start);
+                endedHandlers.remove(d.handler);
+            }
+        }
+    }
+
+    private void pauseBlock() {
+        if (data != null) {
+            endBlock();
+        } else {
+        }
+    }
+
+    private void restartBlock() {
+        if (!stack.isEmpty()) {
+            data = stack.pop();
+            // if(data.handler != null){
+            // ExceptionRangeStart start = new ExceptionRangeStart();
+            // new Edge(start, data.handler);
+            // }
+        } else {
+        }
+    }
+
+    /**
+     * 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 {
+        // do the current level first
+        inlineFinally(data.handler);
+
+        // then every-body else
+        int now = stack.size();
+        while (now > level) {
+            CFGBuilderData nowData = stack.get(--now);
+            inlineFinally(nowData.handler);
+        }
+    }
+
+    @Override
+    public List<stmt> suite(List<stmt> stmts) throws Exception {
+        return suite(stmts, null);
+    }
+
+    public List<stmt> suite(List<stmt> stmts, HandlerStart handler) throws Exception {
+        boolean shouldRestart = false;
+        boolean shouldEndStartExcs = handler != null;
+        if (data != null) {
+            pauseBlock();
+            shouldRestart = true;
+        }
+
+        beginBlock(handler);
+        if (shouldEndStartExcs) {
+            endAllExceptions(false, false);
+            startNewExceptionRange();
+        }
+        doSuite(stmts);
+        if (shouldEndStartExcs) {
+            endCurrExceptionRange();
+            restartAllExceptions(false, false);
+        }
+        endBlock();
+        List<stmt> ret = stack.pop().stmts;
+        if (shouldRestart) {
+            restartBlock();
+        }
+        return ret;
+    }
+
+    private void doSuite(List<stmt> stmts) throws Exception {
+        for (stmt s : stmts) {
+            stmt newS = (stmt) visit(s);
+            data.stmts.add(newS);
+        }
+    }
+
+    @Override
+    public Object visitTryExcept(TryExcept node) throws Exception {
+
+        HandlerStart handler = new HandlerStart();
+        if (node.getInternalBody().get(0) instanceof TryExcept) {
+            node.getInternalBody().add(0, new Pass());
+        }
+        List<stmt> body = suite(node.getInternalBody(), handler);
+
+        List<stmt> orelse = suite(node.getInternalOrelse());
+
+        List<excepthandler> handlers = new ArrayList<excepthandler>();
+        handlers.add(handler);
+        for (excepthandler target : node.getInternalHandlers()) {
+            handlers.add((excepthandler) visit(target));
+        }
+        TryExcept new_node = new TryExcept(node.getToken(), body, handlers, orelse);
+
+        return new_node;
+    }
+
+    @Override
+    public Object visitTryFinally(TryFinally node) throws Exception {
+        List<stmt> finally_body = node.getInternalFinalbody();
+        FinallyStart finally_handler = new FinallyStart(finally_body);
+
+        List<stmt> body = suite(node.getInternalBody(), finally_handler);
+//        body.addAll(suite(finally_body));
+        // and now there is a empty try-catch block error?
+        List<stmt> suited_finally = suite(finally_body);
+
+        suited_finally.add(0, new TryExcept(node, null, Collections.singletonList(
+        		(excepthandler) finally_handler), null));
+
+        TryFinally new_node = new TryFinally(node.getToken(), body, suited_finally);
+        return new_node;
+    }
+
+    private void inlineFinally(HandlerStart handler) throws Exception {
+        if (handler instanceof FinallyStart) {
+            FinallyStart fHandler = (FinallyStart) handler;
+            data.stmts.addAll(suite(fHandler.finalBody));
+//            data.stmts.add(new FinallyGoto(fHandler.finally_body_start));
+        }
+    }
+
+    private int beginLoop() {
+        int savebcf = bcfLevel;
+        // record the next stack size since all loops are in-side suites
+        // and suites do all the work in a new stack.
+        bcfLevel = stack.size() + 1;
+        return savebcf;
+    }
+
+    private void finishLoop(int savebcf) {
+        bcfLevel = savebcf;
+    }
+
+    @Override
+    public Object visitFor(For node) throws Exception {
+        expr iter = (expr) visitNotNull(node.getInternalIter());
+        expr target = (expr) visitNotNull(node.getInternalTarget());
+
+        int savebcf = beginLoop();
+        List<stmt> body = suite(node.getInternalBody());
+        finishLoop(savebcf);
+
+        List<stmt> orelse = suite(node.getInternalOrelse());
+        return new For(node.getToken(), target, iter, body, orelse);
+    }
+
+    @Override
+    public Object visitWhile(While node) throws Exception {
+        int savebcf = beginLoop();
+        node = (While) super.visitWhile(node);
+        // FIXME!! handler or-else here :(
+        finishLoop(savebcf);
+        return node;
+    }
+
+    @Override