/*
* 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.types;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import polyglot.types.ClassType;
import polyglot.types.CodeInstance;
import polyglot.types.Def_c;
import polyglot.types.LocalDef;
import polyglot.types.QName;
import polyglot.types.Ref;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.TypeSystem;
import polyglot.types.Types;
import polyglot.types.VarDef;
import polyglot.types.VarInstance;
import polyglot.util.CollectionUtil;
import x10.util.ClosureSynthesizer;
import x10.util.CollectionFactory;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import polyglot.util.TypedList;
import x10.types.constraints.ConstraintManager;
import x10.constraint.XVar;
import x10.constraint.XTerm;
import x10.types.constraints.CConstraint;
import x10.types.constraints.TypeConstraint;
import x10.types.constraints.XConstrainedTerm;
public class ClosureDef_c extends Def_c implements ClosureDef {
private static final long serialVersionUID = -9082180217851254169L;
protected Ref<? extends CodeInstance<?>> methodContainer;
protected Ref<? extends ClassType> typeContainer;
protected Ref<? extends Type> returnType;
protected List<Ref<? extends Type>> formalTypes;
protected List<LocalDef> formalNames;
protected Ref<CConstraint> guard;
//protected Ref<TypeConstraint> typeGuard;
protected CodeInstance<?> asInstance;
protected Ref<? extends Type> offerType;
protected List<VarInstance<? extends VarDef>> capturedEnvironment;
public ClosureDef_c(TypeSystem ts, Position pos,
Ref<? extends ClassType> typeContainer,
Ref<? extends CodeInstance<?>> methodContainer,
Ref<? extends Type> returnType,
List<Ref<? extends Type>> formalTypes,
ThisDef thisDef,
List<LocalDef> formalNames,
Ref<CConstraint> guard,
//Ref<TypeConstraint> typeGuard,
//List<Ref<? extends Type>> throwTypes,
Ref<? extends Type> offerType) {
super(ts, pos, pos);
this.typeContainer = typeContainer;
this.methodContainer = methodContainer;
this.returnType = returnType;
this.formalTypes = TypedList.copyAndCheck(formalTypes, Ref.class, true);
this.formalNames = TypedList.copyAndCheck(formalNames, LocalDef.class, true);
this.guard = guard;
//this.typeGuard = typeGuard;
this.thisDef = thisDef;
this.offerType = offerType;
this.capturedEnvironment = new ArrayList<VarInstance<? extends VarDef>>();
this.isStatic = Types.get(methodContainer).def().staticContext();
}
public Ref<? extends Type> offerType() {
return offerType;
}
public ClosureDef position(Position pos) {
ClosureDef_c n = (ClosureDef_c) copy();
n.position = pos;
return n;
}
public X10ClassDef classDef() {
return asType().x10Def();
}
protected ClosureType asType;
public ClosureType asType() {
if (asType == null) {
asType = ts.closureType(this);
}
return asType;
}
@Override
public ClosureDef_c copy() {
ClosureDef_c res = (ClosureDef_c) super.copy();
res.asInstance = null;
res.asType = null;
res.capturedEnvironment = TypedList.<VarInstance<? extends VarDef>>copy(capturedEnvironment, VarInstance.class, false);
return res;
}
protected boolean inferReturnType;
public boolean inferReturnType() { return inferReturnType; }
public void inferReturnType(boolean r) { this.inferReturnType = r; }
// BEGIN ANNOTATION MIXIN
List<Ref<? extends Type>> annotations;
public List<Ref<? extends Type>> defAnnotations() {
if (annotations == null)
return Collections.<Ref<? extends Type>>emptyList();
return Collections.unmodifiableList(annotations);
}
public void setDefAnnotations(List<Ref<? extends Type>> annotations) {
this.annotations = TypedList.<Ref<? extends Type>>copyAndCheck(annotations, Ref.class, true);
this.asInstance = null;
}
public List<Type> annotations() {
return X10TypeObjectMixin.annotations(this);
}
public List<Type> annotationsMatching(Type t) {
return X10TypeObjectMixin.annotationsMatching(this, t);
}
public List<Type> annotationsNamed(QName fullName) {
return X10TypeObjectMixin.annotationsNamed(this, fullName);
}
// END ANNOTATION MIXIN
public ClosureInstance asInstance() {
if (asInstance == null) {
asInstance = ((TypeSystem) ts).createClosureInstance(position(), errorPosition(), Types.ref(this));
}
return (ClosureInstance) asInstance;
}
public Ref<? extends ClassType> typeContainer() {
return typeContainer;
}
public List<ParameterType> typeParameters() {
return Collections.<ParameterType>emptyList();
}
public void setTypeParameters(List<ParameterType> typeParameters) {
throw new InternalCompilerError("Attempt to set type parameters on a closure def: "+this, position());
}
public XVar thisVar() {
if (this.thisDef != null)
return this.thisDef.thisVar();
return ConstraintManager.getConstraintSystem().makeThis();
}
ThisDef thisDef;
public ThisDef thisDef() {
return this.thisDef;
}
public void setThisDef(ThisDef thisDef) {
this.thisDef = thisDef;
}
protected XConstrainedTerm placeTerm;
public XConstrainedTerm placeTerm() { return placeTerm; }
public void setPlaceTerm(XConstrainedTerm pt) {
if (placeTerm != null && pt != null)
assert (placeTerm == null || pt == null);
placeTerm = pt;
}
public List<LocalDef> formalNames() {
return Collections.unmodifiableList(formalNames);
}
public void setFormalNames(List<LocalDef> formalNames) {
this.formalNames = TypedList.copyAndCheck(formalNames, LocalDef.class, true);
this.asInstance = null;
this.asType = null;
}
public Ref<CConstraint> guard() {
return guard;
}
public void setGuard(Ref<CConstraint> s) {
this.guard = s;
this.asInstance = null;
this.asType = null;
}
public Ref<TypeConstraint> typeGuard() {
return null; // typeGuard;
}
public void setTypeGuard(Ref<TypeConstraint> s) {
// this.typeGuard = s;
assert false;
}
/**
* @param container The container to set.
*/
public void setTypeContainer(Ref<? extends ClassType> container) {
this.typeContainer = container;
this.asInstance = null;
this.asType = null;
}
public Ref<? extends CodeInstance<?>> methodContainer() {
return methodContainer;
}
public void setMethodContainer(Ref<? extends CodeInstance<?>> container) {
methodContainer = container;
this.asInstance = null;
this.asType = null;
}
public Ref<? extends Type> returnType() {
return returnType;
}
public void setReturnType(Ref<? extends Type> returnType) {
assert returnType != null;
this.returnType = returnType;
this.asInstance = null;
this.asType = null;
}
public List<Ref<? extends Type>> formalTypes() {
return Collections.unmodifiableList(formalTypes);
}
/**
* @param formalTypes The formalTypes to set.
*/
public void setFormalTypes(List<Ref<? extends Type>> formalTypes) {
this.formalTypes = TypedList.copyAndCheck(formalTypes, Ref.class, true);
this.asInstance = null;
this.asType = null;
}
public List<VarInstance<? extends VarDef>> capturedEnvironment() {
return Collections.unmodifiableList(capturedEnvironment);
}
public void setCapturedEnvironment(List<VarInstance<? extends VarDef>> env) {
capturedEnvironment = TypedList.<VarInstance<? extends VarDef>>copy(env, VarInstance.class, false);
}
private static boolean containsDef(List<VarInstance<? extends VarDef>> l, VarInstance<? extends VarDef> v) {
for (VarInstance<? extends VarDef> e : l) {
if (e == v)
return true;
if (e.def() == v.def())
return true;
}
return false;
}
public static void addCapturedVariable(List<VarInstance<? extends VarDef>> capturedEnvironment, VarInstance<? extends VarDef> vi) {
if (!containsDef(capturedEnvironment, vi)) {
capturedEnvironment.add(vi);
//if (vi instanceof ThisInstance)
// System.err.println("Closure at "+position()+" captures this");
}
}
public void addCapturedVariable(VarInstance<? extends VarDef> vi) {
addCapturedVariable(this.capturedEnvironment, vi);
}
private boolean isStatic;
public boolean staticContext() {
return isStatic;
}
public void setStaticContext(boolean v) {
isStatic = v;
this.asInstance = null;
this.asType = null;
}
public String signature() {
StringBuilder sb = new StringBuilder("(");
List<LocalDef> names = formalNames();
List<Ref<? extends Type>> types = formalTypes();
assert types != null;
int size = types.size();
for (int i=0; i < size; i++) {
if (names != null && i < names.size())
sb.append(names.get(i).toString());
else {
sb.append(Types.get(types.get(i)).toString());
}
if (i < size-1)
sb.append(",");
}
sb.append(")");
if (guard != null)
sb.append(Types.get(guard).toString());
return sb.toString();
}
public String designator() {
return "closure";
}
public String toString() {
return designator() + " " + signature() + " => " + returnType();
}
@Override
public List<Ref<? extends Type>> throwTypes() {
return Collections.<Ref<? extends Type>>emptyList();
}
@Override
public void setThrowTypes(List<Ref<? extends Type>> l) {
throw new Error("Internal compiler error: X10 closures do not throw java checked exceptions.");
}
}