/*
* 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.Collections;
import java.util.List;
import polyglot.ast.Expr;
import polyglot.ast.New;
import polyglot.ast.NodeFactory;
import polyglot.ast.Stmt;
import polyglot.types.ClassDef;
import polyglot.types.ClassType;
import polyglot.types.ConstructorDef;
import polyglot.types.ConstructorInstance;
import polyglot.types.Ref;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.Types;
import polyglot.util.Position;
import x10.ast.AnnotationNode;
import x10.extension.X10Del;
import polyglot.types.Context;
import polyglot.types.TypeSystem;
import x10.types.X10ClassType;
import x10.types.checker.PlaceChecker;
/**
* An simple synthesizer to create a new instance: new classType
*
*/
public class NewInstanceSynth extends AbstractStateSynth implements IStmtSynth, IExprSynth {
ClassType classType; //The new instance's type
//Default value for other needed information;
List<AnnotationNode> annotations; // annotations of the new instance
List<Type> argTypes; //arguments' type --> If we could reason the args' type from args, the list could be eliminated
List<Expr> args; //arguments
public NewInstanceSynth(NodeFactory xnf, Context xct, Position pos, ClassType classType){
super(xnf, xct, pos);
this.classType = classType;
annotations = new ArrayList<AnnotationNode>();
argTypes = new ArrayList<Type>();
args = new ArrayList<Expr>();
}
public void addAnnotation(AnnotationNode annotation){
annotations.add(annotation);
}
public void addArgument(Type argType, Expr arg){
argTypes.add(argType);
args.add(arg.type(argType));
}
public void addArguments(List<Type> argTypes, List<Expr> args){
assert(argTypes.size() == args.size());
for(int i = 0; i < argTypes.size(); i++){
addArgument(argTypes.get(i), args.get(i));
}
}
public Expr genExpr() throws SemanticException {
TypeSystem xts = (TypeSystem) xct.typeSystem();
List<Type> typeArgs = ((X10ClassType)classType).typeArguments();
if (typeArgs == null) {
typeArgs = Collections.<Type>emptyList();
}
ConstructorInstance constructorIns = xts.findConstructor(classType, // receiver's
// type
xts.ConstructorMatcher(classType, typeArgs, argTypes, xct));
// ConstructorDef constructorDef = constructorIns.def();
// //need set formals to the constructorIns
// List<Type> formalTypes = new ArrayList<Type>();
// for(Ref<? extends Type> r : constructorDef.formalTypes()){
// formalTypes.add(r.get());
// }
// constructorIns = constructorIns.formalTypes(formalTypes);
// constructorIns.typeParameters(typeArgs);
New aNew = xnf.New(pos, xnf.CanonicalTypeNode(pos, Types.ref(classType)), args);
// aNew.qualifier(qualifier);
Ref<? extends ClassDef> outerRef = classType.def().outer();
if(outerRef != null && classType.def().isInnerClass()){
ClassDef outerDef = outerRef.get();
Expr q = xnf.This(Position.COMPILER_GENERATED,
xnf.CanonicalTypeNode(Position.COMPILER_GENERATED, outerDef.asType())).type(outerDef.asType());
aNew = aNew.qualifier(q);
}
// Add annotations to New
if (annotations.size() > 0) {
aNew = (New) ((X10Del) aNew.del()).annotations(annotations);
}
Expr construct = aNew.constructorInstance(constructorIns).type(classType); // PlaceChecker.AddIsHereClause(classType, xct));
return construct;
}
public Stmt genStmt() throws SemanticException {
return xnf.Eval(pos, genExpr());
}
}