/* * 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.util.synthesizer; import java.util.ArrayList; import java.util.List; import polyglot.ast.ClassBody; import polyglot.ast.ClassDecl; import polyglot.ast.ClassMember; import polyglot.ast.Expr; import polyglot.ast.FlagsNode; import polyglot.ast.Id; import polyglot.ast.NodeFactory; import polyglot.ast.Receiver; import polyglot.ast.Stmt; import polyglot.ast.TypeNode; import polyglot.types.ClassDef; import polyglot.types.ClassType; import polyglot.types.FieldDef; import polyglot.types.Flags; import polyglot.types.Name; import polyglot.types.Ref; import polyglot.types.SemanticException; import polyglot.types.Type; import polyglot.types.Types; import polyglot.types.ClassDef.Kind; import polyglot.util.Position; import polyglot.frontend.Job; import x10.ast.TypeParamNode; import x10.ast.X10ClassDecl; import x10.ast.X10ConstructorDecl; import x10.types.ParameterType; import x10.types.ParameterType.Variance; import x10.types.X10ClassDef; import polyglot.types.Context; import x10.types.checker.PlaceChecker; import x10.types.constraints.TypeConstraint; /** * Synthesizer to construct a class * */ public class ClassSynth extends AbstractStateSynth implements IClassMemberSynth { X10ClassDef classDef; X10ClassDecl classDecl; List<IClassMemberSynth> membersSynth; public ClassSynth(Job job, NodeFactory xnf, Context xct, ClassDecl classDecl) { super(xnf, xct, classDecl.position()); this.classDecl = (X10ClassDecl) classDecl; this.classDef = (X10ClassDef) classDecl.classDef(); // no need to set others membersSynth = new ArrayList<IClassMemberSynth>(); classDef.setJob(job); } public ClassSynth(Job job, NodeFactory xnf, Context xct, Position pos, Type superType, Name className, List<Type> interfaces, Flags flags, Kind kind) { super(xnf, xct, pos); membersSynth = new ArrayList<IClassMemberSynth>(); classDef = (X10ClassDef) xts.createClassDef(); classDef.setThisDef(xts.thisDef(pos, Types.ref(classDef.asType()))); classDef.superType(Types.ref(superType)); // And the super Type List<Ref<? extends Type>> interfacesRef = new ArrayList<Ref<? extends Type>>(); for (Type t : interfaces) { interfacesRef.add(Types.ref(t)); } classDef.setInterfaces(interfacesRef); classDef.name(className); classDef.setFlags(flags); classDef.kind(kind); // important to set kind classDef.setJob(job); } /** * Create a class def with no interaces, Flags.None and top.level * * @param xnf * @param xct * @param superType * @param className */ public ClassSynth(Job job, NodeFactory xnf, Context xct, Position pos, Type superType, String className) { this(job, xnf, xct, pos, superType, Name.make(className), new ArrayList<Type>(), Flags.NONE, ClassDef.MEMBER); } public X10ClassDef getClassDef() { return classDef; } public X10ClassDef getDef() { return classDef; } public void setSuperType(Type superType) { classDef.superType(Types.ref(superType)); } public void setOuter(X10ClassDef outClassDef){ if(outClassDef != null){ classDef.outer(Types.ref(outClassDef)); } } public X10ClassDef getOuter(){ Ref<? extends X10ClassDef> outRef = classDef.outer(); if(outRef != null){ return outRef.get(); } return null; } public Flags getFlags(){ return classDef.flags(); } public void setFlags(Flags flags) { try { checkClose(); classDef.setFlags(flags); } catch (StateSynthClosedException e) { e.printStackTrace(); } } public void setKind(Kind kind) { try { checkClose(); classDef.kind(kind); } catch (StateSynthClosedException e) { e.printStackTrace(); } } public void addInterface(Type interf) { try { checkClose(); classDef.addInterface(Types.ref(interf)); } catch (StateSynthClosedException e) { e.printStackTrace(); } } public void addTypeParameter(ParameterType p, ParameterType.Variance v){ try { checkClose(); classDef.addTypeParameter(p, v); } catch (StateSynthClosedException e) { e.printStackTrace(); } } public void addTypeParameters(List<ParameterType> params, List<ParameterType.Variance> variances){ assert(params.size() == variances.size()); int size = params.size(); for(int i = 0 ; i < size ; i++){ addTypeParameter(params.get(i), variances.get(i)); } } public FieldSynth createField(Position pos, String name, Type type) { FieldSynth fsynth = new FieldSynth(xnf, xct, pos, classDef, name, type); membersSynth.add(fsynth); return fsynth; } public ConstructorSynth createConstructor(Position pos) { ConstructorSynth conSynth = new ConstructorSynth(xnf, xct, pos, classDef); membersSynth.add(conSynth); return conSynth; } public ClassSynth createInnerClass(Position pos, Type type, String className) { ClassSynth cSynth = new ClassSynth(classDef.job(), xnf, xct, pos, type, className); membersSynth.add(cSynth); return cSynth; } public MethodSynth createMethod(Position pos, String methodName) { MethodSynth mSynth = new MethodSynth(xnf, xct, pos, classDef, methodName); membersSynth.add(mSynth); return mSynth; } public X10ClassDecl close() throws SemanticException { // should trigger all member gen to generate the decl, // add add it into the class decl if (closed) { return classDecl; } closed = true; if (classDecl == null) { // a new class - classdecl FlagsNode fNode = xnf.FlagsNode(pos, classDef.flags()); Id id = xnf.Id(pos, classDef.name()); TypeNode superTN = (TypeNode) xnf.CanonicalTypeNode(pos, classDef.superType()); List<ClassMember> cmembers = new ArrayList<ClassMember>(); // iterate all memberSynths ClassBody body = xnf.ClassBody(pos, cmembers); List<TypeNode> interfaceTN = new ArrayList<TypeNode>(); for (Ref<? extends Type> t : classDef.interfaces()) { interfaceTN.add((TypeNode) xnf.CanonicalTypeNode(pos, t)); } classDecl = (X10ClassDecl) xnf.ClassDecl(pos, fNode, id, superTN, interfaceTN, body); //add type parameters if classDef has type parameters if(classDef.typeParameters().size() > 0){ List<TypeParamNode> typeParamNodes = new ArrayList<TypeParamNode>(); List<Variance> vars = classDef.variances(); List<ParameterType> params = classDef.typeParameters(); for(int i = 0; i < params.size(); i++){ TypeParamNode tn = xnf.TypeParamNode(compilerPos, xnf.Id(compilerPos, params.get(i).name()), vars.get(i)); typeParamNodes.add(tn.type(params.get(i))); } classDecl = classDecl.typeParameters(typeParamNodes); } //After it has type parameters, we need create a type bounds here in all causes //In fact, some times, no need setting. For example, the container class has no parameter type if(classDef.typeBounds() == null){ classDef.setTypeBounds(Types.ref(new TypeConstraint())); } classDecl = (X10ClassDecl) classDecl.classDef(classDef); } // now tries to add all the members ClassBody b = classDecl.body(); for (IClassMemberSynth cms : membersSynth) { if (cms instanceof ConstructorSynth) { //need handle the type parameters for the constructor ArrayList<ParameterType> paramTypes = new ArrayList<ParameterType>(); ArrayList<ParameterType.Variance> variances = new ArrayList<ParameterType.Variance>(); for(TypeParamNode tpn : classDecl.typeParameters()){ paramTypes.add(tpn.type()); variances.add(tpn.variance()); } ((ConstructorSynth) cms).setTypeParameters(paramTypes, variances); } ClassMember cm = cms.close(); b = b.addMember(cm); } classDecl = (X10ClassDecl) classDecl.body(b); return classDecl; } public X10ClassDecl getClassDecl() { if (closed) { return classDecl; } else { System.out.println("[ClassSynth_ERR]Try to get the ClassDecl before the class synthesizer is closed!"); return null; // the class is not generated yet } } }