/** * 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; import abs.frontend.typechecker.ext.AdaptDirection; public class LocationType { public static final String LOCATION_KEY = "LOCATION_KEY"; public static final LocationType FAR = new LocationType("Far"); public static final LocationType NEAR = new LocationType("Near"); public static final LocationType SOMEWHERE = new LocationType("Somewhere"); public static final LocationType BOTTOM = new LocationType("Bottom"); public static final LocationType INFER = new LocationType("Infer"); public static final LocationType[] ALLTYPES = {FAR, NEAR, SOMEWHERE, BOTTOM, INFER}; public static final LocationType[] ALLVISTYPES = {FAR, NEAR, SOMEWHERE, BOTTOM}; public static final LocationType[] ALLCONCRETEUSERTYPES = {FAR, NEAR, SOMEWHERE}; public static final LocationType[] ALLUSERTYPES = {FAR, NEAR, SOMEWHERE, INFER}; private String name; private LocationType(String name) { this.name = name; } @Override public String toString() { return name; } public static LocationType createFromName(String name) { for (LocationType t : ALLTYPES) { if (t.name.equals(name)) return t; } throw new IllegalArgumentException(name+" is not a location type"); } public static LocationType createParametricFar(String s) { return new ParameterizedFarType(s); } private static class ParameterizedFarType extends LocationType { private ParameterizedFarType(String s) { super("Far(" + s + ")"); } @Override public String toAnnoString() { return "[Far] "; } @Override public boolean equals(Object o) { if (o == null || !(o instanceof ParameterizedFarType)) { return false; } else { if (this == o) { return true; } else { ParameterizedFarType lt = (ParameterizedFarType) o; return toString().equals(lt.toString()); } } } } public boolean isParametricFar() { return this instanceof ParameterizedFarType; } public boolean isFar() { return this == FAR; } public boolean isInfer() { return this == INFER; } public boolean isNear() { return this == NEAR; } public boolean isSomewhere() { return this == SOMEWHERE; } public boolean isBottom() { return this == BOTTOM; } public boolean isSubtypeOf(LocationType t) { return this == t || this.isBottom() || t.isSomewhere() || this.isParametricFar() && t.isFar(); } public boolean isSubtypeOfFarAdapted(LocationType t) { if (this.isBottom()) { return true; } if (this.isNear() || this.isFar() || this.isParametricFar() || this.isSomewhere()) { return t.isFar() || t.isSomewhere() || (t.isParametricFar() && t == this); } throw new IllegalArgumentException("Cannot use location type "+this+" to check subtypeOfFar"); } public LocationType adaptTo(LocationType to, AdaptDirection dir) { if (isBottom()) return this; if (to.isFar()) { return this.isNear() ? FAR : SOMEWHERE; } if (to.isParametricFar()) { if (this.isNear()) return dir.isFrom() ? to : FAR; if (this.isParametricFar() && this != to) { return dir.isFrom() ? SOMEWHERE : this; } return SOMEWHERE; } if (to.isNear()) { return this; } if (to.isSomewhere()) { return SOMEWHERE; } if (to.isBottom()) { return SOMEWHERE; } throw new IllegalArgumentException("Cannot use location type "+to+" to adapt to"); } public String toAnnoString() { return "["+toString()+"] "; } }