/* * 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.Collections; import polyglot.ast.Assign; import polyglot.ast.Binary; import polyglot.ast.Block; import polyglot.ast.Catch; import polyglot.ast.Expr; import polyglot.ast.If; import polyglot.ast.Local; import polyglot.ast.Stmt; import polyglot.types.Flags; import polyglot.types.Name; import polyglot.types.SemanticException; import x10.ast.When; import x10.compiler.ws.util.AddIndirectLocalDeclareVisitor; import x10.compiler.ws.util.ClosureDefReinstantiator; import x10.compiler.ws.util.Triple; import x10.compiler.ws.util.WSUtil; import x10.util.Synthesizer; import x10.util.synthesizer.CodeBlockSynth; import x10.util.synthesizer.InstanceCallSynth; import x10.util.synthesizer.MethodSynth; import x10.util.synthesizer.NewLocalVarSynth; import x10.util.synthesizer.SwitchSynth; /** * @author Haichuan * * Generate the when class * Currently, it only supports the first branch of when * */ public class WSWhenFrameClassGen extends WSRegularFrameClassGen { protected final When whenStmt; public WSWhenFrameClassGen(AbstractWSClassGen parent, When whenStmt) { super(parent, whenStmt.stmt(), WSUtil.getWhenClassName(parent.getClassName())); this.whenStmt = whenStmt; } /* This method is different to the regular frame's genTreeMethods, * Besides the fast/resume/back, it needs a condition method * @see x10.compiler.ws.codegen.WSRegularFrameClassGen#genThreeMethods() */ @Override protected void genMethods() throws SemanticException { //firstly translate the bodies Triple<CodeBlockSynth, SwitchSynth, SwitchSynth> bodyCodes = transformMethodBody(); //TODO: we should be using transNormalStmt here (Olivier) CodeBlockSynth fastBodySynth = genPathBody(fastMSynth, bodyCodes.first().close()); CodeBlockSynth resumeBodySynth = genPathBody(resumeMSynth, bodyCodes.first().close()); CodeBlockSynth backBodySynth = backMSynth.getMethodBodySynth(whenStmt.position()); //finally the back backBodySynth.addStmt(bodyCodes.third()); } /** * Synthesize the following codes * var b:Boolean; * atomic if (b = condition()) { * // fast body * } * if (!b) redo(worker); * @param methodSynth * @param bodyStmt * @return * @throws SemanticException */ protected CodeBlockSynth genPathBody(MethodSynth methodSynth, Stmt bodyStmt) throws SemanticException{ CodeBlockSynth bodySynth = methodSynth.getMethodBodySynth(whenStmt.position()); NewLocalVarSynth bVarSynth = new NewLocalVarSynth(xnf, xct, whenStmt.position(), Flags.NONE, xnf.BooleanLit(whenStmt.position(), false).type(xts.Boolean())); Local bVar = bVarSynth.getLocal(); bodySynth.addStmt(bVarSynth); //b = condition(); Expr orgWhenExpr = (Expr) this.replaceLocalVarRefWithFieldAccess(whenStmt.expr()); Expr assign = xnf.LocalAssign(whenStmt.position(), bVar, Assign.ASSIGN, orgWhenExpr).type(orgWhenExpr.type()); If ifStmt = xnf.If(whenStmt.position(), assign, bodyStmt); Stmt enter = xnf.Eval(whenStmt.position(), synth.makeStaticCall(whenStmt.position(), xts.Runtime(), WSSynthesizer.ENTER_ATOMIC, xts.Void(), xct)); Stmt exit = xnf.Eval(whenStmt.position(), synth.makeStaticCall(whenStmt.position(), xts.Runtime(), WSSynthesizer.EXIT_WHEN, Collections.<Expr>singletonList(xnf.Local(whenStmt.position(), bVar.name()).localInstance(bVar.localInstance()).type(xts.Boolean())), xts.Void(), xct)); Block fin = xnf.Block(whenStmt.position(), exit); //finally, put it into atomic Stmt atmCheck = xnf.Try(whenStmt.position(), xnf.Block(whenStmt.position(), enter, ifStmt), Collections.<Catch>emptyList(), fin); bodySynth.addStmt(atmCheck); //!b Expr redoCheck = xnf.Binary(whenStmt.position(), bVar, Binary.EQ, synth.booleanValueExpr(false, whenStmt.position())).type(xts.Boolean()); //continueLater(worker) Stmt redoStmt = wsynth.genContinueLaterStmt(classSynth, methodSynth); Stmt ifRedoStmt = xnf.If(whenStmt.position(), redoCheck, redoStmt); bodySynth.addStmt(ifRedoStmt); return bodySynth; } }