/* * 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.constraint.xnative; import java.util.List; import java.util.Map; import x10.constraint.XField; import x10.constraint.XTerm; import x10.constraint.XVar; /** * A representation of a Field.T is a FieldDef or a MethodDef. * @author vj * */ public class XNativeField<T> extends XNativeVar implements XField<T> { private static final long serialVersionUID = -6911344390866611523L; public XNativeVar receiver; public T field; public boolean hasEQV; // used by XPromise_c to determine if this field should occur in the output // representation of a constraint or not. hidden true for fake fields. private boolean hidden; @Override public XNativeTerm accept(TermVisitor visitor) { XNativeTerm res = (XNativeTerm)visitor.visit(this); if (res!=null) return res; XNativeVar newReceiver = (XNativeVar)receiver.accept(visitor); if (newReceiver==receiver) return this; XNativeField<T> newThis = (XNativeField<T>) this.clone(); newThis.receiver = newReceiver; newThis.hasEQV= newReceiver.hasEQV(); return newThis; } public XNativeField(XVar receiver, T field) { this(receiver, field, false);} public XNativeField(XVar receiver, T field, boolean hidden) { super(); this.receiver = (XNativeVar)receiver; this.field = field; this.hidden = hidden; this.hasEQV = this.receiver.hasEQV(); } public boolean isHidden() { return hidden; } @Override public boolean hasEQV(){ return hasEQV;} @Override public XTermKind kind() { return XTermKind.FIELD_ACCESS; } @Override public XNativeTerm subst(XTerm y, XVar x) { return subst((XNativeTerm)y, x, true); } @Override public XNativeTerm subst(XTerm y, XVar x, boolean propagate) { XNativeTerm r = super.subst(y, x, propagate); if (! equals(r)) return r; XNativeVar newReceiver = (XNativeVar) receiver.subst(y, x); if (newReceiver == receiver) return this; XNativeField<T> result = clone(); result.receiver = newReceiver; result.hasEQV = newReceiver.hasEQV(); return result; } @Override public boolean okAsNestedTerm() { return true; } @Override public List<XNativeEQV> eqvs() { return receiver.eqvs();} @Override public T field() { return field;} /** * if this is r.f, then return newReceiver.f. * @param newReceiver * @return */ @Override public XNativeField<T> copyReceiver(XVar newReceiver) { if (newReceiver == receiver) return this; return new XNativeField<T>(newReceiver, field, hidden); } /** If this is r.f1.f2..fn, then return newRoot.f1.f2...fn. * * @param newRoot * @return public XField<T> copyRoot(XVar newRoot) { if (receiver instanceof XField) { XVar newReceiver = ((XField<?>) receiver).copyRoot(newRoot); return copyReceiver(newReceiver); } // replace the root. return copyReceiver(newRoot); } */ public String name() { return field.toString();} @Override public boolean hasVar(XVar v) { return equals(v) || receiver.hasVar(v);} @Override public XNativeVar receiver() { return receiver; } @Override public int hashCode() { return receiver.hashCode() + field.hashCode(); } @SuppressWarnings("unchecked") @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof XNativeField) { XNativeField<T> other = (XNativeField<T>) o; return receiver.equals(other.receiver) && field.equals(other.field); } return false; } @Override public String toString() { return (receiver == null ? "" : receiver.toString() + ".") + field; } @SuppressWarnings("unchecked") @Override public XNativeField<T> clone() { XNativeField<T> n = (XNativeField<T>) super.clone(); n.vars = null; return n; } // memoize rootVar and path. protected XNativeVar[] vars; @Override public XNativeVar[] vars() { if (vars == null) initVars(); return vars; } @Override public XNativeVar rootVar() { if (vars == null) initVars(); return vars[0]; } @SuppressWarnings("unchecked") protected void initVars() { int count = 0; for (XNativeVar source = this; source instanceof XNativeField; source = ((XNativeField<T>) source).receiver) count++; vars = new XNativeVar[count + 1]; XNativeVar f = this; for (int i = count; i >= 0; i--) { vars[i] = f; if (i > 0) f = ((XNativeField<T>) f).receiver; } } @Override public XPromise nfp(XNativeConstraint c) { assert c != null; XPromise root = receiver.nfp(c); root.ensureFields(); Map<Object, XPromise> map = root.fields(); assert map != null; XPromise entry = map.get(field); if (entry == null) { entry = new XPromise(this); map.put(field, entry); return entry; } entry = entry.lookup(); return entry; } }