/*
* 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.matcher;
import polyglot.types.Context;
import polyglot.types.FieldInstance;
import polyglot.types.Name;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.TypeSystem_c;
import polyglot.types.Types;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import x10.constraint.XConstraint;
import x10.constraint.XFailure;
import x10.constraint.XVar;
import x10.types.constraints.ConstraintManager;
import x10.constraint.XVar;
import x10.errors.Errors;
import x10.types.ParameterType;
import polyglot.types.Context;
import x10.types.X10FieldInstance;
import polyglot.types.TypeSystem;
import x10.types.constraints.CConstraint;
public class X10FieldMatcher {
public static Type instantiateAccess(Type container, Type t, XVar oldThis,
boolean contextKnowsReceiver) throws SemanticException {
assert container!=null && t!=null;
CConstraint c = Types.xclause(container);
// Let v be the symbolic name for the target. If there is none, we make one up.
// Let t = T{tc}, and ct = U{c}.
// If c does not have a selfVarBinding, then we want to set t to
// t = T{exists vv. (tc,this==vv),ct[vv/self]}
// If c does have a selfVarBinding, v, then we want to set t to
// t = T{exists v. (tc, this=v, ct)}
XVar v = Types.selfVarBinding(container);
XVar vv = null;
if (v == null) {
v = vv =ConstraintManager.getConstraintSystem().makeUQV();
}
if (oldThis != null && v == null && vv==null)
assert false;
/*if (c != null)
c = c.copy().instantiateSelf(v);*/
{ // Update t
CConstraint tconst = Types.realX(t);
if (! contextKnowsReceiver) {
tconst.addIn(v, c);
//CConstraint tc2 = tconst.copy().project(tconst.self());
CConstraint tc2 = tconst.exists();
t = Subst.addIn(t, tc2);
}
t = Types.constrainedType(Types.baseType(t), tconst);
t = Subst.subst(t,
new XVar[] {v},
new XVar[] {oldThis},
new Type[] {}, new ParameterType[] {});
if (vv != null) { // Hide vv, i.e. substitute in an anonymous EQV
t = Subst.subst(t,
new XVar[] {ConstraintManager.getConstraintSystem().makeEQV()},
new XVar[] {vv},
new Type[] {}, new ParameterType[] {});
}
final CConstraint tmpTc = Types.realX(t).copy();
tmpTc.addIn(v,c);
if (! tmpTc.consistent()) {
throw new Errors.InconsistentType(t, t.position());
}
}
return t;
}
public static X10FieldInstance instantiateAccess(X10FieldInstance fi, Name name, Type container, boolean contextKnowsReceiver, Context context) throws SemanticException {
if (! fi.name().equals(name)) {
return null;
}
TypeSystem ts = fi.typeSystem();
Type t = fi.type();
Type rt = fi.rightType();
// Now need to figure out the type of the field, from the declaration of the field
// in the container, and the type of the container.
// The task is to transfer constraints from the target to the field.
Type ct = container != null ? container : fi.container();
CConstraint c = Types.xclause(ct);
// Let v be the symbolic name for the target. If there is none, we make one up.
// Let t = T{tc}, and ct = U{c}.
// If c does not have a selfVarBinding, then we want to set t to
// t = T{exists vv. (tc,this==vv),ct[vv/self]}
// If c does have a selfVarBinding, v, then we want to set t to
// t = T{exists v. (tc, this=v, ct)}
XVar v = Types.selfVarBinding(ct);
XVar vv = null;
if (v == null) {
v = vv =ConstraintManager.getConstraintSystem().makeUQV();
}
XVar oldThis = fi.x10Def().thisVar();
if (oldThis != null && v == null && vv==null)
assert false;
/*if (c != null)
c = c.copy().instantiateSelf(v);*/
t = instantiateAccess(ct,t,oldThis, contextKnowsReceiver);
rt = instantiateAccess(ct,rt,oldThis, contextKnowsReceiver);
//rt = Subst.subst(rt, (new XVar[] { w }), (new XVar[] { oldThis }), new Type[] {}, new ParameterType[] {});
//if (v != null)
// rt = X10TypeMixin.setThisVar(rt, v);
// }
if (!ts.consistent(t, context)) {
throw new Errors.InconsistentType(t, Position.COMPILER_GENERATED);
}
if (!ts.consistent(rt, context)) {
throw new Errors.InconsistentType(rt, Position.COMPILER_GENERATED);
}
return fi.type(t, rt);
}
}