/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package abs.frontend.typechecker.locationtypes.infer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import abs.frontend.ast.ASTNode;
import abs.frontend.ast.ClassDecl;
import abs.frontend.ast.FieldDecl;
import abs.frontend.ast.MethodSig;
import abs.frontend.ast.ParamDecl;
import abs.frontend.ast.VarDecl;
import abs.frontend.typechecker.locationtypes.LocationType;
public class LocationTypeVariable {
public static final Object VAR_KEY = new Object();
public static int counter = 0;
boolean updated = false;
boolean declared = false;
public static final LocationTypeVariable ALWAYS_NEAR = new LocationTypeVariable();
public static final LocationTypeVariable ALWAYS_FAR = new LocationTypeVariable();
public static final LocationTypeVariable ALWAYS_BOTTOM = new LocationTypeVariable();
public static final LocationTypeVariable ALWAYS_SOMEWHERE = new LocationTypeVariable();
private LocationType annotatedType;
private List<LocationType> parametricFarTypes = new ArrayList<LocationType>();
List<LocationType> farTypes = new ArrayList<LocationType>();
List<LocationType> allCTypes = new ArrayList<LocationType>(Arrays.asList(LocationType.ALLCONCRETEUSERTYPES)); // all but bottom
private int id = ++counter;
private ASTNode<?> node;
private List<LocationType> allTypes = Arrays.asList(LocationType.ALLVISTYPES);
public static LocationTypeVariable newVar(Set<Constraint> constraints, ASTNode<?> n, boolean declared, List<LocationType> farTypes, LocationType annotatedType) {
LocationTypeVariable result = new LocationTypeVariable();
result.node = n;
result.farTypes = farTypes;
result.declared = declared;
result.annotatedType = annotatedType;
constraints.add(Constraint.declConstraint(result));
if (declared) {
//constraints.add(Constraint.constConstraint(result, result.allCTypes, Constraint.MUST_HAVE));
MultiListIterable<LocationType> tt = new MultiListIterable<LocationType>(farTypes, Arrays.asList(LocationType.ALLCONCRETEUSERTYPES));
constraints.add(Constraint.constConstraint(result, tt, Constraint.MUST_HAVE));
}
return result;
}
private void update() {
if (updated) return;
allTypes = new ArrayList<LocationType>();
allTypes.addAll(Arrays.asList(LocationType.ALLVISTYPES));
allTypes.addAll(farTypes);
if (declared) {
allCTypes.addAll(farTypes);
}
updated = true;
}
public List<LocationType> parametricFarTypes() {
update();
return farTypes;
}
public List<LocationType> allTypes() {
update();
return allTypes;
}
@Override
public String toString() {
String pos = "";
if (node != null) {
pos = " at " + node.getPositionString();
}
return "v" + id + getASTNodeString();
}
public ASTNode<?> getTypeNode() {
if (node instanceof MethodSig) {
MethodSig ms = (MethodSig) node;
return ms.getReturnType();
}
if (node instanceof FieldDecl) {
FieldDecl fd = (FieldDecl) node;
return fd.getAccess();
}
if (node instanceof ParamDecl) {
ParamDecl pd = (ParamDecl) node;
return pd.getAccess();
}
if (node instanceof VarDecl) {
VarDecl vd = (VarDecl) node;
return vd.getAccess();
}
return node;
}
private String getASTNodeString() {
if (node == null)
return "";
if (node instanceof MethodSig) {
MethodSig ms = (MethodSig) node;
return " Method "+ms.getName();
}
if (node instanceof FieldDecl) {
FieldDecl fd = (FieldDecl) node;
return " Field "+((ClassDecl)fd.getParent().getParent()).getName()+"."+fd.getName();
}
if (node instanceof VarDecl) {
VarDecl vd = (VarDecl) node;
return " Var "+vd.getName();
}
return node.getClass().getName();
}
public ASTNode<?> getNode() {
return node;
}
public static LocationTypeVariable getFromLocationType(LocationType lt) {
if (lt.isBottom()) return ALWAYS_BOTTOM;
if (lt.isFar()) return ALWAYS_FAR;
if (lt.isNear()) return ALWAYS_NEAR;
if (lt.isSomewhere()) return ALWAYS_SOMEWHERE;
throw new IllegalArgumentException("Location type " + lt + " not allowed");
}
public LocationType getAnnotatedType() {
return annotatedType;
}
}