/* * 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.Collections; import java.util.List; import polyglot.ast.Expr; import polyglot.ast.Formal; import polyglot.ast.MethodDecl; import polyglot.ast.New; import polyglot.ast.NodeFactory; import polyglot.ast.Return; import polyglot.ast.Special; import polyglot.ast.Stmt; import polyglot.frontend.Job; import polyglot.types.ClassDef; import polyglot.types.ClassType; import polyglot.types.Context; import polyglot.types.Flags; import polyglot.types.MethodDef; import polyglot.types.Name; import polyglot.types.SemanticException; import polyglot.types.Type; import x10.ast.Closure; import x10.ast.TypeParamNode; import x10.ast.X10MethodDecl; import x10.compiler.ws.WSTransformState; import x10.compiler.ws.util.WSUtil; import x10.types.ClosureDef; import x10.types.ParameterType; import x10.types.X10ClassDef; import x10.types.X10ClassType; import x10.types.X10MethodDef; import x10.util.HierarchyUtils; import x10.util.synthesizer.CodeBlockSynth; import x10.util.synthesizer.ConstructorSynth; import x10.util.synthesizer.FieldSynth; import x10.util.synthesizer.InstanceCallSynth; import x10.util.synthesizer.MethodSynth; import x10.util.synthesizer.NewInstanceSynth; import x10.util.synthesizer.NewLocalVarSynth; import x10.visit.X10PrettyPrinterVisitor; /** * @author Haichuan * * Used to generate a closure fast/slow/back path * A closure frame is a extension to a Regular frame * It need process formals, return values. It need provide fast/slow method * The inner class extends RegularFrame. * And it will return the closure with the wrapper code * */ public class WSClosureFrameClassGen extends WSRegularFrameClassGen { protected final Closure closure; protected List<Formal> formals; //original methods's all formals protected MethodSynth fastWrapperMethodSynth; protected Name returnFieldName; protected Name returnFlagName; //=> boolean returnFlagName; public WSClosureFrameClassGen(Job job, NodeFactory xnf, Context xct, Closure closure, X10ClassDef containerClassDef, WSTransformState wts) { super(job, xnf, xct, wts, WSUtil.getClosureBodyClassName(closure), closure.body(), containerClassDef, Flags.FINAL.Static(), job.extensionInfo().typeSystem().RegularFrame()); this.closure = closure; ClosureDef closureDef = closure.closureDef(); //processing the type parameters List<ParameterType> paramTypes = closureDef.typeParameters(); //TODO: need check the closure's type paramters; //List<TypeParamNode> paramNodes = closure.typeParameters(); for(int i = 0; i < paramTypes.size(); i++){ classSynth.addTypeParameter(paramTypes.get(i), ParameterType.Variance.INVARIANT/*paramNodes.get(i).variance()*/); } //processing the return returnFlagName = wsynth.createReturnFlagField(classSynth); fieldNames.add(returnFlagName); Type returnType = closureDef.returnType().get(); if (returnType != xts.Void()){ returnFieldName = wsynth.createReturnValueField(classSynth, returnType); fieldNames.add(returnFieldName); //add it as one field for query //and also need add "=> type" as one interface classSynth.addInterface(synth.simpleFunctionType(returnType, compilerPos)); } formals = closure.formals(); //record all formals //finally changes fast/slow method's return type genMethodFormalAsFields(); } /** * Generate apply() method for non-void method's inner class * @param returnType * @throws SemanticException */ protected void genApplyMethod(Type returnType) throws SemanticException{ MethodSynth applyMSynth = classSynth.createMethod(classSynth.pos(), "apply"); applyMSynth.setFlag(Flags.PUBLIC); applyMSynth.setReturnType(returnType); CodeBlockSynth applyMBSynth = applyMSynth.getMethodBodySynth(compilerPos); //return result; Return r = xnf.Return(compilerPos, synth.makeFieldAccess(compilerPos, getThisRef(), returnFieldName, xct)); applyMBSynth.addStmt(r); } protected void genMethodFormalAsFields(){ //transform formals as fields for(Formal f:formals){ Name fieldName = f.name().id(); classSynth.createField(compilerPos, fieldName.toString(), f.type().type()).setFlags(f.flags().flags()); fieldNames.add(fieldName); } } public Closure transform() throws SemanticException { Type returnType = closure.returnType().type(); if (returnType != xts.Void()){ genApplyMethod(returnType); } genClass(); return getNewClosure(); } public Closure getNewClosure() throws SemanticException{ NewInstanceSynth rSynth = new NewInstanceSynth(xnf, xct, compilerPos, xts.RootFinish()); InstanceCallSynth riSynth = new InstanceCallSynth(xnf, xct, rSynth.genExpr(), "init"); NewLocalVarSynth nvSynth = new NewLocalVarSynth(xnf, xct, compilerPos, Name.make("rootFinish"), Flags.FINAL, riSynth.genExpr(), xts.RootFinish(), Collections.EMPTY_LIST); //new _main(args) NewInstanceSynth niSynth = new NewInstanceSynth(xnf, xct, compilerPos, this.getClassType()); niSynth.addArgument(xts.Frame(), nvSynth.getLocal()); niSynth.addArgument(xts.FinishFrame(), nvSynth.getLocal()); for(Formal f : formals){ //now add the type Type fType = f.localDef().type().get(); Expr formalRef = xnf.Local(compilerPos, xnf.Id(compilerPos, f.name().id())).localInstance(f.localDef().asInstance()).type(fType); niSynth.addArgument(fType, formalRef); } Expr newMainExpr = niSynth.genExpr(); // new _main(args).run(); InstanceCallSynth icSynth = new InstanceCallSynth(xnf, xct, newMainExpr, "run"); CodeBlockSynth cbSynth = new CodeBlockSynth(xnf, xct, closure.body().position()); cbSynth.addStmt(nvSynth.genStmt()); cbSynth.addStmt(icSynth.genStmt()); return (Closure) closure.body(cbSynth.close()); } protected void genClassConstructor() throws SemanticException{ ConstructorSynth conSynth = wsynth.genClassConstructorType2Base(classSynth); CodeBlockSynth codeBlockSynth = conSynth.createConstructorBody(compilerPos); //all formals as constructor's formal //This ref Expr thisRef = wsynth.genThisRef(classSynth); for(Formal f: formals){ Expr fRef = conSynth.addFormal((Formal) f.copy()); //make a field access Stmt s = xnf.Eval(compilerPos, synth.makeFieldAssign(compilerPos, thisRef, f.name().id(), fRef, xct)); codeBlockSynth.addStmt(s); } } /** * Generate one wrapper method * static def fib_fast(worker:Worker!, up:Frame!, ff:FinishFrame!, pc:Int, n:Int):Int { * @StackAllocate val _tmp = @StackAllocate new _fib(up, ff, pc, n); * return _tmp.fast(worker); * } * @param containerClassDef the method's container class's def * @param methodName the newly method's name * @param targetClassDef the target class's def * @param targetMethodName the target method's name, fast or slow * @return the method synthesizer * @throws SemanticException */ // private MethodSynth genWSMethod(MethodSynth methodSynth) throws SemanticException{ // // String targetMethodName = FAST.toString(); // // //now process the formals // Expr workerRef = methodSynth.addFormal(compilerPos, Flags.FINAL, xts.Worker(), WORKER.toString()); // Expr upRef = methodSynth.addFormal(compilerPos, Flags.FINAL, ts.Frame(), UP.toString()); // Expr ffRef = methodSynth.addFormal(compilerPos, Flags.FINAL, ts.FinishFrame(), FF.toString()); // // //all other formals // List<Expr> orgFormalRefs = new ArrayList<Expr>(); // List<Type> orgFormalTypes = new ArrayList<Type>(); // for(Formal f : methodDecl.formals()){ // orgFormalTypes.add(f.type().type()); // orgFormalRefs.add(methodSynth.addFormal(f)); //all formals are added in // } // //add all type parameters (template) // X10MethodDecl mDecl = (X10MethodDecl)methodDecl; // X10MethodDef mDef = mDecl.methodDef(); // int paramSize = mDef.typeParameters().size(); // for(int i = 0; i < paramSize; i++){ // methodSynth.addTypeParameter(mDef.typeParameters().get(i), // mDecl.typeParameters().get(i).variance()); // } // // //now create the body // CodeBlockSynth mBodySynth = methodSynth.getMethodBodySynth(compilerPos); // NewInstanceSynth niSynth = new NewInstanceSynth(xnf, xct, compilerPos, classSynth.getClassDef().asType()); // niSynth.addArgument(ts.Frame(), upRef); // niSynth.addArgument(ts.FinishFrame(), ffRef); // niSynth.addArguments(orgFormalTypes, orgFormalRefs); // niSynth.addAnnotation(genStackAllocateAnnotation()); // //special process for the new statement // New newE = (New) niSynth.genExpr(); // Special s = (Special) newE.qualifier(); // if(s != null){ // s = s.qualifier(null); //clear the type node // newE = newE.qualifier(s); //this method is outer, no need qualifier typenode // } // // //special process for the new statement end // // NewLocalVarSynth localSynth = mBodySynth.createLocalVar(compilerPos, Flags.FINAL, newE); // localSynth.addAnnotation(genStackAllocateAnnotation()); // Expr localRef = localSynth.getLocal(); //point to this inner class instance // // //_tmp.fast(worker) or _temp.slow(worker) // InstanceCallSynth callSynth = new InstanceCallSynth(xnf, xct, localRef, targetMethodName); // callSynth.addArgument(xts.Worker(), workerRef); // Expr callExpr = callSynth.genExpr(); // //if the method has return type, insert return, others, just call them // if(callExpr.type() != null && callExpr.type() != xts.Void()){ // mBodySynth.addStmt(xnf.Return(compilerPos, callExpr)); // } // else{ // mBodySynth.addStmt(xnf.Eval(callExpr.position(), callExpr)); // } // // return methodSynth; // } public Name getReturnFieldName() { return returnFieldName; } public Name getReturnFlagName() { return returnFlagName; } }