/*
* 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.List;
import java.util.Collections;
import polyglot.ast.Binary;
import polyglot.ast.Call;
import polyglot.ast.Expr;
import polyglot.ast.Field;
import polyglot.ast.Formal;
import polyglot.ast.Lit;
import polyglot.ast.Local;
import polyglot.ast.Node;
import polyglot.ast.Receiver;
import polyglot.ast.Term;
import polyglot.ast.TypeNode;
import polyglot.ast.Typed;
import polyglot.ast.Unary;
import polyglot.ast.Variable;
import polyglot.ast.Binary.Operator;
import polyglot.types.ClassDef;
import polyglot.types.CodeDef;
import polyglot.types.Context;
import polyglot.types.FieldInstance;
import polyglot.types.Flags;
import polyglot.types.LocalDef;
import polyglot.types.LocalInstance;
import polyglot.types.MethodDef;
import polyglot.types.Name;
import polyglot.types.QName;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.Types;
import polyglot.types.TypeSystem;
import polyglot.types.Def;
import polyglot.types.Ref;
import polyglot.types.ClassType;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import polyglot.visit.ContextVisitor;
import x10.ast.Closure_c;
import x10.ast.Here;
import x10.ast.Here_c;
import x10.ast.IsRefTest;
import x10.ast.ParExpr;
import x10.ast.SubtypeTest;
import x10.ast.Tuple;
import x10.ast.X10Cast;
import x10.ast.X10Field_c;
import x10.ast.X10Special;
import x10.ast.HasZeroTest;
import x10.constraint.XEQV;
import x10.constraint.XFailure;
import x10.constraint.XLit;
import x10.constraint.XLocal;
import x10.constraint.XUQV;
import x10.constraint.XVar;
import x10.constraint.XTerm;
import x10.constraint.XField;
import x10.errors.Errors;
import x10.errors.Errors.IllegalConstraint;
import x10.extension.X10Ext;
import x10.types.checker.PlaceChecker;
import x10.types.constants.ClosureValue;
import x10.types.constants.ConstantValue;
import x10.types.constants.StringValue;
import x10.types.constraints.CConstraint;
import x10.types.constraints.CLocal;
import x10.types.constraints.ConstraintManager;
import x10.types.constraints.SubtypeConstraint;
import x10.types.constraints.TypeConstraint;
import x10.types.constraints.XConstrainedTerm;
import x10.types.constraints.CAtom;
import x10.types.constraints.CField;
import x10.types.constraints.CThis;
import x10.types.constraints.CSelf;
import x10.types.matcher.Subst;
import x10.util.Synthesizer;
import x10.types.constraints.XTypeLit;
import x10.types.constraints.xnative.QualifiedVar;
/**
* This is the bridge from Expr or TypeNode to a CConstraint. The CConstraint
* generated may keep a reference to type objects obtained from the Expr or TypeNode.
*
* @author nystrom
* @author vj
*/
public class XTypeTranslator {
public static final boolean THIS_VAR = true;
private final TypeSystem ts;
public XTypeTranslator(TypeSystem xts) {
super();
ts = xts;
}
//public static XTerm translate(CConstraint c, Receiver r, TypeSystem xts, Context xc) {
// return xts.xtypeTranslator().translate(c, r, xc);
//}
/**
* Translate the given AST term to an XTerm using information in the constraint
* to resolve self, and using the context to determine AST type information
* (e.g. for Specials).
* @param c --- a constraint used for context, e.g. self information. If term
* is a this (e.g. this, Foo.this etc), then the constraint's this Var is set
* on return.
* @param term -- the term to be translated
* @param xc -- the context in which the term is to be translated
* @return null if the translation is not possible. Caller must always check.
* FIX: Remove the need for the constraint to be passed into translate.
*
* If toplevel is true, then boolean connectives, && are permitted.
*/
public XTerm translate(CConstraint c, Receiver term, Context xc) throws IllegalConstraint {
return translate(c, term, xc, false);
}
public XTerm translate(CConstraint c, Receiver term, Context xc, boolean tl) throws IllegalConstraint {
if (term == null)
return null;
if (term instanceof Lit)
return translate((Lit) term);
if (term instanceof Here_c)
return trans(c, (Here_c) term, xc, tl);
if (term instanceof Variable)
return trans(c, (Variable) term, xc, tl);
if (term instanceof X10Special)
return trans(c, (X10Special) term, xc, tl);
if (term instanceof Expr && ts.isUnknown(term.type())) {
return null;
}
if (term instanceof Expr) {
Expr e = (Expr) term;
if (e.isConstant()) {
ConstantValue cv = e.constantValue();
if (!(cv instanceof ClosureValue)) {
return ConstraintManager.getConstraintSystem().makeLit(ConstantValue.toJavaObject(e.constantValue()), e.type());
}
}
}
if (term instanceof X10Cast) {
X10Cast cast = ((X10Cast) term);
return translate(c, cast.expr().type(cast.type()), xc, tl);
}
if (term instanceof Call) {
return trans(c, (Call) term, xc, tl);
}
if (term instanceof Tuple) {
return trans(c, (Tuple) term, xc, tl);
}
if (term instanceof Unary) {
Unary u = (Unary) term;
Expr t2 = u.expr();
Unary.Operator op = u.operator();
if (op == Unary.POS)
return translate(c, t2, xc, tl);
return null; // no other unary operator supported
}
if (term instanceof Binary)
return trans(c, (Binary) term, xc, tl);
if (term instanceof TypeNode)
return trans(c, (TypeNode) term);
if (term instanceof ParExpr)
return translate(c, ((ParExpr) term).expr(), xc, tl);
return null;
}
/**
* Return the term var.field, where information about the field is obtained from fi.
* The returned term carries a reference to fi.def(), and field is fi.name().toString().
* @param var
* @param fi
* @return
*/
public XVar translate(XVar var, FieldInstance fi, boolean ignore) {
// Warning -- used to have a string that did not contain container()#.
return ConstraintManager.getConstraintSystem().makeField(var, fi.def());
}
/**
* Return the term target.field, where information about the field is obtained from fi.
* The returned term carriers a reference to fi.def(), and field is fi.name().toString().
* Note that if target is a formula f, then the atom field(f) is returned instead.
* @param target
* @param fi
* @return
*/
public XTerm translate(XTerm target, FieldInstance fi) {
return translate(target, fi, false);
}
XTerm translate(XTerm target, FieldInstance fi, boolean ignore) {
if (fi == null)
return null;
try {
if (fi.flags().isStatic()) {
Type container = Types.get(fi.def().container());
container = Types.baseType(container);
if (container instanceof X10ClassType) {
target = ConstraintManager.getConstraintSystem().makeLit(((X10ClassType) container).fullName());
}
else {
throw new Errors.CannotTranslateStaticField(container, fi.position());
}
}
XTerm v;
if (target instanceof XVar) {
v = ConstraintManager.getConstraintSystem().makeField((XVar) target, fi.def()); // hmm string was fi.name().toString(0 before.
}
else {
// this is odd....?
// TODO: Determine under what conditions is this path taken.
v = ConstraintManager.getConstraintSystem().makeAtom(fi.def(), target);
}
return v;
} catch (SemanticException z) {
return null;
}
}
/**
* Return target.prop, where information about the property is obtained from fi.
* It must be the case that fi corresponds to a property that takes no arguments.
* Note that if target is a formula f, then the atom prop(f) is returned instead.
* TODO: Determine why the name cant be just fi.name().toString().
* @param target
* @param fi
* @return
*/
public XTerm translate(XTerm target, MethodInstance mi) {
assert mi.flags().isProperty() && mi.formalTypes().size() == 0;
XTerm v;
if (target instanceof XVar) {
v = ConstraintManager.getConstraintSystem().makeField((XVar) target, mi.def());
}
else {
// this is odd....?
// TODO: Determine under what conditions is this path taken.
// XName field = ConstraintManager.getConstraintSystem().makeName(mi.def(), Types.get(mi.def().container()) + "#" + mi.name().toString() + "()");
v = ConstraintManager.getConstraintSystem().makeAtom(mi.def(), target);
}
// this creates an unexpanded property method call.
return v;
}
static public XTerm expandSelfPropertyMethod(XTerm term) {
return expandPropertyMethod(term,false,null,null,null);
}
// todo: merge this code with Checker.expandCall and try to get rid of ts.expandMacros
static public XTerm expandPropertyMethod(XTerm term, boolean isThisOrSelf,
// these three formals help us search for a concrete implementation of the property method
// they can be null (then we don't search for an implementation)
TypeSystem ts, ClassType classType, Context context) {
Def aDef = null;
XTerm[] args = null; // the first arg is the this-receiver
if (term instanceof CAtom) {
CAtom cAtom = (CAtom) term;
aDef = cAtom.def();
args = cAtom.arguments();
}
if (term instanceof XField) {
XField cField = (XField) term;
Object o = cField.field();
if (o instanceof Def) {
aDef = (Def) o;
args = new XTerm[1];
args[0] = cField.receiver();
}
}
if (aDef==null || !(aDef instanceof X10MethodDef)) return term;
XTerm receiver = args[0];
if (isThisOrSelf) {
// for methods (checking overriding) we replace "this.p(...)"
if (!(receiver instanceof CThis)) return term;
} else {
// for subtyping tests we replace "self.p(...)"
if (!(receiver instanceof CSelf)) return term;
}
X10MethodDef def = (X10MethodDef) aDef;
if (classType!=null) {
// find the correct def, and return a clone of the XTerm
final MethodInstance method = ts.findImplementingMethod(classType, def.asInstance(), false, context);
if (method==null) // the property is abstract in t1
return term;
def = (X10MethodDef) method.def();
}
final Ref<XTerm> bodyRef = def.body();
if (bodyRef==null)
return term;
XTerm body = bodyRef.get();
if (body==null)
return term;
// currently we only support nullary property methods that are not CAtoms
List<LocalDef> formals = def.formalNames();
if (formals.size()!=args.length-1)
throw new InternalCompilerError("The number of arguments in the property method didn't match the property defintiion.");
int pos=1;
for (LocalDef formal : formals) {
XVar x = ConstraintManager.getConstraintSystem().makeLocal((X10LocalDef)formal);
XTerm y = args[pos++];
body = body.subst(y, x);
}
body = body.subst(receiver, def.thisVar());
return body;
}
public static final Object FAKE_KEY = new Object();
/**
* A fake field is one which exists purely for compilation purposes
* and has no run-time existence. The main example is "home". It used to exist
* for all objects, but is now used merely to track the location of the current
* object statically.
* @param target
* @param name
* @return
*/
public XTerm translateFakeField(XTerm target, String name) {
return ConstraintManager.getConstraintSystem().makeFakeField((XVar) target, Name.make(name));
}
/**
* Return an XLocal which contains a reference to the type object li.def(),
* and whose name is li.name().
* @param li
* @return
*/
public CLocal translate(LocalInstance li) {
return ConstraintManager.getConstraintSystem().makeLocal((X10LocalDef) li.def());
}
/**
* Return an XLit representing the literal t.
* @param t
* @return
*/
public XLit translate(Lit t) {
return ConstraintManager.getConstraintSystem().makeLit(ConstantValue.toJavaObject(t.constantValue()), t.type());
}
/**
* Translate a type t into an XTerm. A type parameter
* is translated into an XLocal. Other types are converted
* into XTypeLit_c.
* @param t
* @return
*/
public XTerm translate(Type t) {
if (t instanceof ParameterType)
return translateTypeParam((ParameterType) t);
// if (t instanceof X10ClassType)
// return transClassType((X10ClassType) t);
// if (t instanceof ConstrainedType)
// return transConstrainedType((ConstrainedType) t);
if (t instanceof MacroType) {
MacroType pt = (MacroType) t;
return translate(pt.definedType());
}
return ConstraintManager.getConstraintSystem().makeTypeLit(t);
// return ConstraintManager.getConstraintSystem().makeLit(t);
}
public XUQV translateTypeParam(ParameterType t) {
return ConstraintManager.getConstraintSystem().makeUQV(t.toString()); //ConstraintManager.getConstraintSystem().makeLocal(ConstraintManager.getConstraintSystem().makeName(t));
}
/**
* Translate into the literal t.
* @param t
* @param ts TODO
* @return
*/
public static XLit translate(int t, TypeSystem ts) {
return ConstraintManager.getConstraintSystem().makeLit(t, ts.Int());
}
/**
* Translate into the literal t.
* @param t
* @param ts TODO
* @return
*/
public static XLit translate(boolean t, TypeSystem ts) {
return ConstraintManager.getConstraintSystem().makeLit(t, ts.Boolean());
}
/**
* Return the XLit representing null.
* @param ts TODO
* @return
*/
public static XLit transNull(TypeSystem ts) {
return ConstraintManager.getConstraintSystem().makeLit(null, ts.Null());
}
/* public CConstraint normalize(CConstraint c, Context xc) {
CConstraint result = ConstraintManager.getConstraintSystem().makeCConstraint();
for (XTerm term : c.extConstraints()) {
try {
if (term instanceof XEquals) {
XEquals xt = (XEquals) term;
XTerm right = xt.right();
if (right instanceof XEquals) {
XEquals xright = (XEquals) right;
XTerm t1 = xright.left();
XTerm t2 = xright.right();
if (c.entails(t1, t2)) {
result.addBinding(xt.left(), ConstraintManager.getConstraintSystem().TRUE);
} else
if (c.disEntails(t1, t2)) {
result.addBinding(xt.left(), ConstraintManager.getConstraintSystem().FALSE);
} else
result.addBinding(xt.left(), xt.right());
}
} else
result.addTerm(term);
} catch (XFailure t) {
}
}
return result;
}
*/
/**
* Translate an expression into a CConstraint, throwing SemanticExceptions
* if this is not possible.
* This must be called after type-checking of Expr.
* @param formals TODO
* @param term
* @param xc TODO
* @param c
* @return
* @throws SemanticException
*/
public CConstraint constraint(List<Formal> ignore, Expr term, Context xc) throws SemanticException {
CConstraint c = ConstraintManager.getConstraintSystem().makeCConstraint();
if (term == null)
return c;
if (! term.type().isBoolean())
throw new SemanticException("Cannot build constraint from expression (1)|"
+ term + "| of type " + term.type() + "; not a boolean.", term.position());
// TODO: handle the formals.
XTerm t= translate(c, term, xc, true);
if (t == null)
throw new SemanticException("Cannot build constraint from expression (2)|" + term + "|.", term.position());
try {
c.addTerm(t);
}
catch (XFailure e) {
c.setInconsistent();
}
return c;
}
public TypeConstraint typeConstraint(List<Formal> ignore, Expr term, Context xc) throws SemanticException {
TypeConstraint c = new TypeConstraint();
if (term == null)
return c;
if (! term.type().isBoolean())
throw new SemanticException("Cannot build constraint from expression (3)|"
+ term + "| of type " + term.type() + "; not a boolean.",
term.position());
// TODO: handle the formals.
transType(c, term, xc);
return c;
}
public static boolean isPureTerm(Term t) {
boolean result = false;
if (t instanceof Variable) {
Variable v = (Variable) t;
result = v.flags().isFinal();
}
return result;
}
public XVar translateThisWithoutTypeConstraint() {
XVar v = ConstraintManager.getConstraintSystem().makeThis(); // ConstraintManager.getConstraintSystem().makeLocal(ConstraintManager.getConstraintSystem().makeName("this"));
return v;
}
/*public XLocal translateThis(Type t) throws SemanticException {
XLocal v = translateThisWithoutTypeConstraint();
return v;
}*/
public CConstraint binaryOp(Binary.Operator op, CConstraint cl, CConstraint cr) {
return null; // none supported
}
public CConstraint unaryOp(Unary.Operator op, CConstraint ca) {
return null; // none supported
}
// *********************************************************************************************
// *********************************** private help routines for translation********************
private XTerm trans(CConstraint c, Here_c h, Context xc, boolean tl) {
XConstrainedTerm placeTerm = xc.currentPlaceTerm();
//XConstrainedTerm placeTerm = h.placeTerm();
if (placeTerm == null) return ConstraintManager.getConstraintSystem().makeEQV();
return placeTerm.term();
//return PlaceChecker.here();
}
private XLocal trans(Local t) {
return translate(t.localInstance());
}
private XTerm trans(CConstraint c, TypeNode t) {
return translate(t.type());
}
private void transType(TypeConstraint c, Binary t, Context xc) throws SemanticException {
Expr left = t.left();
Expr right = t.right();
XTerm v;
if (t.operator() == Binary.COND_AND
|| (t.operator() == Binary.BIT_AND
&& ts.isImplicitCastValid(t.type(), ts.Boolean(), xc))) {
transType(c, left, xc);
transType(c, right, xc);
}
else {
throw new SemanticException("Cannot translate " + t
+ " into a type constraint.", t.position());
}
}
private void transType(TypeConstraint c, Expr t, Context xc) throws SemanticException {
if (t instanceof Binary) {
transType(c, (Binary) t, xc);
}
else if (t instanceof ParExpr) {
transType(c, ((ParExpr) t).expr(), xc);
}
else if (t instanceof SubtypeTest) {
transType(c, (SubtypeTest) t, xc);
} else if (t instanceof HasZeroTest) {
transType(c, (HasZeroTest) t, xc);
} else if (t instanceof IsRefTest) {
transType(c, (IsRefTest) t, xc);
}
else {
throw new SemanticException("Cannot translate " + t
+ " into a type constraint.", t.position());
}
}
private void transType(TypeConstraint c, HasZeroTest t, Context xc) throws SemanticException {
TypeNode left = t.parameter();
c.addTerm(new SubtypeConstraint(left.type(), null, SubtypeConstraint.Kind.HASZERO));
}
private void transType(TypeConstraint c, IsRefTest t, Context xc) throws SemanticException {
TypeNode left = t.parameter();
c.addTerm(new SubtypeConstraint(left.type(), null, SubtypeConstraint.Kind.ISREF));
}
private void transType(TypeConstraint c, SubtypeTest t, Context xc) throws SemanticException {
TypeNode left = t.subtype();
TypeNode right = t.supertype();
c.addTerm(new SubtypeConstraint(left.type(), right.type(), t.equals()));
}
private XTerm simplify(Binary rb, XTerm v) {
XTerm result = v;
Expr r1 = rb.left();
Expr r2 = rb.right();
// Determine if their types force them to be equal or disequal.
CConstraint c1 = Types.xclause(r1.type()).copy();
XVar x = ConstraintManager.getConstraintSystem().makeUQV();
c1.addSelfBinding(x);
CConstraint c2 = Types.xclause(x, r2.type()).copy();
if (rb.operator()== Binary.EQ) {
c1.addIn(c2);
if (! c1.consistent())
result = ConstraintManager.getConstraintSystem().xfalse();
if (c1.entails(c2) && c2.entails(c1)) {
result = ConstraintManager.getConstraintSystem().xtrue();
}
}
return result;
}
private XTerm trans(CConstraint c, Binary t, Context xc, boolean tl) throws IllegalConstraint {
Expr left = t.left();
Expr right = t.right();
XTerm v = null;
Operator op = t.operator();
XTerm lt = translate(c, left, xc, op==Binary.COND_AND); // Not top-level, unless op==&&
XTerm rt = translate(c, right, xc,op==Binary.COND_AND); // Not top-level, unless op==&&
if (lt == null || rt == null)
return null;
if (op == Binary.EQ || op == Binary.NE) {
if (right instanceof ParExpr) {
right = ((ParExpr)right).expr();
}
if (right instanceof Binary && ((Binary) right).operator() == Binary.EQ) {
rt = simplify((Binary) right, rt);
}
if (left instanceof Binary && ((Binary) right).operator() == Binary.EQ) {
lt = simplify((Binary) left, lt);
}
if (! tl)
throw new IllegalConstraint(t);
v = op == Binary.EQ ? ConstraintManager.getConstraintSystem().makeEquals(lt, rt): ConstraintManager.getConstraintSystem().makeDisEquals(lt, rt);
}
else if (op == Binary.COND_AND
|| (op == Binary.BIT_AND && ts.isImplicitCastValid(t.type(), ts.Boolean(), xc))) {
if (! tl)
throw new IllegalConstraint(t);
v = ConstraintManager.getConstraintSystem().makeAnd(lt, rt);
}
else {
v = ConstraintManager.getConstraintSystem().makeAtom(t.operator(), lt, rt);
throw new IllegalConstraint(t);
// return null;
}
return v;
}
private XTerm trans(CConstraint c, Tuple t, Context xc, boolean tl) throws IllegalConstraint {
List<XTerm> terms = new ArrayList<XTerm>();
for (Expr e : t.arguments()) {
XTerm v = translate(c, e, xc, tl);
if (v == null)
return null;
terms.add(v);
}
return ConstraintManager.getConstraintSystem().makeAtom("tuple", terms.toArray(new XTerm[0]));
}
private Type getType(TypeSystem ts, String name) throws SemanticException {
return ts.systemResolver().findOne(QName.make(name));
}
private String nodeHasOpaqueAnnotation(TypeSystem ts, MethodDef d) {
List<Type> anns;
try {
anns = d.annotationsMatching(getType(ts, "x10.compiler.Opaque"));
} catch (SemanticException e) {
// in case Opaque.x10 does not exist
return null;
}
if (anns.size() == 0) return null;
Type the_ann = anns.get(0);
X10ClassType the_ann2 = the_ann.toClass();
Expr e = the_ann2.propertyInitializer(0);
if (e.isConstant()) {
return (String) ConstantValue.toJavaObject(e.constantValue());
}
return null;
}
/**
* This used to be a key routine that contained special code for handling at constraints.
* It translates a call t into what the body of the called method would translate to,
* assuming that the method represents a property.
* @param c
* @param t
* @param xc
* @return
*/
private XTerm trans(CConstraint c, Call t, Context xc, boolean tl) throws IllegalConstraint {
MethodInstance xmi = (MethodInstance) t.methodInstance();
Flags f = xmi.flags();
if (f.isProperty()) {
XTerm r = translate(c, t.target(), xc, tl);
if (r == null)
return null;
// FIXME: should just return the atom, and add atom==body to the real clause of the class
// FIXME: fold in class's real clause constraints on parameters into real clause of type parameters
XTerm body = xmi.body();
if (body != null) {
if (xmi.x10Def().thisVar() != null && t.target() instanceof Expr) {
//XName This = ConstraintManager.getConstraintSystem().makeName(new Object(), Types.get(xmi.def().container()) + "#this");
//body = body.subst(r, ConstraintManager.getConstraintSystem().makeLocal(This));
body = body.subst(r, xmi.x10Def().thisVar());
}
if ((! tl) && ! (body.okAsNestedTerm()))
throw new IllegalConstraint(t, body, t.position());
for (int i = 0; i < t.arguments().size(); i++) {
//XVar x = (XVar) X10TypeMixin.selfVarBinding(xmi.formalTypes().get(i));
//XVar x = (XVar) xmi.formalTypes().get(i);
XVar x = ConstraintManager.getConstraintSystem().makeLocal((X10LocalDef) xmi.def().formalNames().get(i)); // we get the def first because the formalNames were renamed in Matcher.instantiate, see XTENLANG-2582
XTerm y = translate(c, t.arguments().get(i), xc, tl);
if (y == null)
assert y != null : "XTypeTranslator: translation of arg " + i + " of " + t + " yields null (pos="
+ t.position() + ")";
body = body.subst(y, x);
}
return body;
} else {
String n = nodeHasOpaqueAnnotation(xc.typeSystem(), xmi.def());
if (n != null) {
System.out.println("making atom \""+n+"\" for "+t);
// translating arguments
List<XTerm> args = new ArrayList<XTerm>();
for (Expr arg : t.arguments()) {
XTerm x = translate(c, arg, xc, tl);
args.add(x);
}
return ConstraintManager.getConstraintSystem().makeOpaque(xmi.def(), r, args);
}
}
if (t.arguments().size() == 0) {
XTerm v;
if (r instanceof XVar) {
v = ConstraintManager.getConstraintSystem().makeField((XVar) r, xmi.def());
}
else {
if ((! tl))
throw new IllegalConstraint(t);
v = ConstraintManager.getConstraintSystem().makeAtom(xmi.def(), r);
}
return v;
}
if ((! tl))
throw new IllegalConstraint(t);
List<XTerm> terms = new ArrayList<XTerm>();
terms.add(r);
for (Expr e : t.arguments()) {
XTerm v = translate(c, e, xc, tl);
if (v == null)
return null;
terms.add(v);
}
XTerm v = ConstraintManager.getConstraintSystem().makeAtom(xmi.def(), terms);
return v;
}
Type type = t.type();
return Types.selfVarBinding(type); // maybe null.
}
private XTerm trans(CConstraint c, Variable term, Context xc, boolean tl) throws IllegalConstraint {
if (term instanceof Field)
return trans(c, (Field) term, xc, tl);
if (term instanceof X10Special)
return trans(c, (X10Special) term, xc, tl);
if (term instanceof Local)
return trans((Local) term);
return null;
}
private XTerm trans(CConstraint c, X10Special term, Context xc, boolean tl) {
return trans(c, term, xc);
}
public XTerm trans(CConstraint c, X10Special t, Context xc0) {
if (true || xc0.specialAsQualifiedVar()) {
return translateSpecialAsQualified(c,t,xc0);
}
Context xc = xc0;
if (t.kind() == X10Special.SELF) {
if (c == null) {
//throw new SemanticException("Cannot refer to self outside a dependent clause.");
return null;
}
XVar v = (XVar) c.self().clone();
// Need to deal with qualified guy as well.
TypeNode tn = t.qualifier();
if (tn != null) {
Type q = Types.baseType(tn.type());
v = ConstraintManager.getConstraintSystem().makeQualifiedVar(q, v);
}
return v;
}
else {
TypeNode tn = t.qualifier();
if (tn != null) {
Type q = Types.baseType(tn.type());
if (q instanceof X10ClassType) {
X10ClassType ct = (X10ClassType) q;
while (xc != null) {
if (xc.inSuperTypeDeclaration()) {
if (xc.supertypeDeclarationType() == ct.def())
break;
}
else if (xc.currentClassDef() == ct.def()) {
break;
}
xc = (Context) xc.pop();
}
}
}
XVar thisVar = null;
for (Context outer = xc; outer != null && thisVar == null; outer = outer.pop()) {
thisVar = outer.thisVar();
}
if (thisVar == null) {
SemanticException e = new SemanticException("Cannot refer to |this| from the context " + xc);
return null;
}
if (c != null)
c.setThisVar(thisVar);
return thisVar;
}
}
public XTerm translateSpecialAsQualified(CConstraint c, X10Special t, Context xc0) {
Context xc = xc0;
if (t.kind() == X10Special.SELF) {
if (c == null) {
//throw new SemanticException("Cannot refer to self outside a dependent clause.");
return null;
}
XVar v = (XVar) c.self().clone();
// Need to deal with qualified guy as well.
TypeNode tn = t.qualifier();
if (tn != null) {
Type q = Types.baseType(tn.type());
v = ConstraintManager.getConstraintSystem().makeQualifiedVar(q, v);
}
return v;
}
// this. why are we doing nothing about super..?
XVar baseThisVar = null;
for (Context outer = xc; outer != null && baseThisVar == null; outer = outer.pop()) {
baseThisVar = outer.thisVar();
}
if (baseThisVar == null) {
SemanticException e = new SemanticException("Cannot refer to |this| from the context " + xc);
return null;
}
if (baseThisVar instanceof QualifiedVar) {
QualifiedVar qVar = (QualifiedVar) baseThisVar;
if (qVar.type() == ((Typed) qVar.receiver()).type())
baseThisVar = qVar.receiver();
}
assert (baseThisVar instanceof CThis);
XVar thisVar = baseThisVar;
try {
TypeNode tn = t.qualifier();
if (tn == null) {
return thisVar;
}
Type q = Types.baseType(tn.type());
// So we need to translate A.this in a deptype.
// The result should not be the this-associated-with-
// the-outer-A in the context.
// Rather it needs to be a QualifiedVar capturing
// A as a qualifier.
// Return the qualified version of the base this.
thisVar = (((CThis)baseThisVar).type()==q)
? baseThisVar : ConstraintManager.getConstraintSystem().makeQualifiedVar(q, baseThisVar);
return thisVar;
} finally {
if (c != null)
c.setThisVar(baseThisVar);
}
}
private XTerm trans(CConstraint c, Field t, Context xc, boolean tl) throws IllegalConstraint {
XTerm receiver = translate(c, t.target(), xc, tl);
if (receiver == null)
return null;
return translate(receiver, t.fieldInstance(), tl);
}
}