/* * 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.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.TypeParamNode; import x10.ast.X10MethodDecl; import x10.compiler.ws.WSTransformState; import x10.compiler.ws.util.WSUtil; 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 normal method's fast/slow/back path * A method 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 * */ public class WSMethodFrameClassGen extends WSRegularFrameClassGen { protected final MethodDecl methodDecl; protected List<Formal> formals; //original methods's all formals protected Name returnFieldName; protected Name returnFlagName; //=> boolean returnFlagName; protected final boolean isMain; public WSMethodFrameClassGen(Job job, NodeFactory xnf, Context xct, X10MethodDef methodDef, MethodDecl methodDecl, WSTransformState wts, boolean isMain) { super(job, xnf, xct, wts, WSUtil.getMethodBodyClassName(methodDef), methodDecl.body(), ((ClassType) methodDef.container().get()).def(), methodDef.flags().isStatic() ? Flags.FINAL.Static() : Flags.FINAL, isMain ? job.extensionInfo().typeSystem().MainFrame() : job.extensionInfo().typeSystem().RegularFrame()); //And if the method is instance method, need process the method body's all special //this/super need set the qualifier this.isMain = isMain; this.methodDecl = methodDecl; //processing the type parameters List<ParameterType> paramTypes = ((X10MethodDef)methodDef).typeParameters(); List<TypeParamNode> paramNodes = ((X10MethodDecl)methodDecl).typeParameters(); for(int i = 0; i < paramTypes.size(); i++){ classSynth.addTypeParameter(paramTypes.get(i), paramNodes.get(i).variance()); } //processing the return returnFlagName = wsynth.createReturnFlagField(classSynth); fieldNames.add(returnFlagName); Type returnType = methodDef.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 = methodDecl.formals(); //record all formals //finally changes fast/slow method's return type fastMSynth.setReturnType(returnType); genMethodFormalAsFields(); } /** * Generate operator() method for non-void method's inner class * @param returnType * @throws SemanticException */ protected void genOperatorMethod(Type returnType) throws SemanticException{ MethodSynth operatorMSynth = classSynth.createMethod(classSynth.pos(), WSSynthesizer.OPERATOR.toString()); operatorMSynth.setFlag(Flags.PUBLIC); operatorMSynth.setReturnType(returnType); CodeBlockSynth operatorMBSynth = operatorMSynth.getMethodBodySynth(compilerPos); //return result; Return r = xnf.Return(compilerPos, synth.makeFieldAccess(compilerPos, getThisRef(), returnFieldName, xct)); operatorMBSynth.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 MethodDecl transform() throws SemanticException { Type returnType = methodDecl.methodDef().returnType().get(); if (returnType != xts.Void()){ genOperatorMethod(returnType); } genClass(); //Generate the wrapper method if (isMain) { return wsynth.genNewMainMethod(classSynth, methodDecl); } else { return null; } } 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); } } public Name getReturnFieldName() { return returnFieldName; } public Name getReturnFlagName() { return returnFlagName; } public X10MethodDecl getWraperMethod() throws SemanticException{ return wsynth.genWSMethod(classSynth, (X10MethodDecl) methodDecl); } }