/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10.compiler.ws.codegen;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import polyglot.ast.Block;
import polyglot.ast.Catch;
import polyglot.ast.Expr;
import polyglot.ast.Formal;
import polyglot.ast.Stmt;
import polyglot.ast.Try;
import polyglot.ast.TypeNode;
import polyglot.types.ClassDef;
import polyglot.types.Flags;
import polyglot.types.Name;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.util.Position;
import x10.ast.Finish;
import x10.compiler.ws.util.AddIndirectLocalDeclareVisitor;
import x10.compiler.ws.util.ClosureDefReinstantiator;
import x10.compiler.ws.util.TransCodes;
import x10.compiler.ws.util.WSUtil;
import x10.types.X10ClassType;
import x10.util.synthesizer.ClassSynth;
import x10.util.synthesizer.CodeBlockSynth;
import x10.util.synthesizer.ConstructorSynth;
import x10.util.synthesizer.InstanceCallSynth;
import x10.util.synthesizer.SuperCallSynth;
import x10.util.synthesizer.SwitchSynth;
/**
* @author Haichuan
*
* Transform a try stmt to a inner class
*
*/
public class WSTryStmtClassGen extends AbstractWSClassGen {
protected Try tryStmt;
public WSTryStmtClassGen(AbstractWSClassGen parent, Try tryStmt) {
super(parent, parent,
WSUtil.getExceptionFrameClassName(parent.getClassName()),
parent.xts.TryFrame(), tryStmt.tryBlock());
this.tryStmt = tryStmt;
//Never need PC value in fact
// if(WSOptimizeConfig.OPT_PC_FIELD == 0){
// addPCField();
// }
}
/*
* The constructor is the same as a regular frame's constructor
* (non-Javadoc)
* @see x10.compiler.ws.codegen.AbstractWSClassGen#genClassConstructor()
*/
protected void genClassConstructor() throws SemanticException {
ConstructorSynth conSynth = wsynth.genClassConstructorType2Base(classSynth);
}
@Override
protected void genMethods() throws SemanticException {
CodeBlockSynth fastBodySynth = fastMSynth.getMethodBodySynth(compilerPos);
CodeBlockSynth resumeBodySynth = resumeMSynth.getMethodBodySynth(compilerPos);
CodeBlockSynth backBodySynth = backMSynth.getMethodBodySynth(compilerPos);
AbstractWSClassGen childFrameGen = genChildFrame(xts.RegularFrame(), codeBlock, WSUtil.getBlockFrameClassName(getClassName()));
List<Stmt> stmts = wsynth.genInvocateFrameStmts(1, classSynth, fastMSynth, childFrameGen);
//now add codes to three path;
//FIXME: just a simple try. Not correct
//Some style
//try { child frame call }
//catch { original code but replace the local var access with field access}
//finally {still replace the local var access with field access}
//
//fast path & resume path
Block tryBlockFast = xnf.Block(tryStmt.tryBlock().position(), stmts);
Block tryBlockResume = xnf.Block(tryStmt.tryBlock().position(), wsynth.genRethrowStmt(resumeMSynth));
Try tryFast = tryStmt.tryBlock(tryBlockFast);
Try tryResume = tryStmt.tryBlock(tryBlockResume);
List<Catch> catchBlocksFast = new ArrayList<Catch>();
List<Catch> catchBlocksResume = new ArrayList<Catch>();
Name formalName = xct.getNewVarName();
Formal fa = synth.createFormal(compilerPos, xts.Abort(), formalName, Flags.NONE);
Stmt ea = xnf.Throw(compilerPos, xnf.Local(compilerPos, xnf.Id(compilerPos, formalName)).localInstance(fa.localDef().asInstance()).type(xts.Abort()));
Catch ca = xnf.Catch(compilerPos, fa, xnf.Block(compilerPos, ea));
catchBlocksFast.add(ca);
catchBlocksResume.add(ca);
for(Catch c: tryStmt.catchBlocks()){
//note there is only one local var, the exception
int pc = 1; //No need the pc;
TransCodes catchBody = transNormalStmt(c.body(), pc, Collections.singleton(c.formal().name().id()));
catchBlocksFast.add(c.body(WSUtil.stmtToBlock(xnf, catchBody.getFastStmts().get(0))));
catchBlocksResume.add(c.body(WSUtil.stmtToBlock(xnf, catchBody.getResumeStmts().get(0))));
}
tryFast = tryFast.catchBlocks(catchBlocksFast);
tryResume = tryResume.catchBlocks(catchBlocksResume);
if (tryStmt.finallyBlock() != null) {
int pc = 1;
TransCodes finalBody = transNormalStmt(tryStmt.finallyBlock(), pc, Collections.EMPTY_SET);
tryFast.finallyBlock(WSUtil.stmtToBlock(xnf, finalBody.getFastStmts().get(0)));
tryResume.finallyBlock(WSUtil.stmtToBlock(xnf, finalBody.getResumeStmts().get(0)));
}
fastBodySynth.addStmt(tryFast);
resumeBodySynth.addStmt(tryResume);
}
}