+
+ public void setSkeletonRef(Type type) throws UnificationException {
+ if(DEBUG)
+ System.out.println("setSkeletonRef " + System.identityHashCode(this) + " -> " + type);
+ if(ref != null || skeletonRef != null)
+ throw new InternalCompilerError("Method setRef should be called only for unbound meta variables.");
+ if(type.contains(this))
+ throw new UnificationException(this, type);
+ this.skeletonRef = type;
+ fireNotifyAboutChange();
+ }
+
+ @Override
+ public int hashCode() {
+ if(ref == null)
+ return System.identityHashCode(this);
+ else
+ return ref.hashCode();
+ }
+
+ @Override
+ public int hashCode(int hash) {
+ if(ref == null)
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ else
+ return ref.hashCode(hash);
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ if(ref == null)
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ else
+ return ref.hashCode(hash, boundVars);
+ }
+
+ @Override
+ public int skeletonHashCode() {
+ if(ref != null)
+ return ref.skeletonHashCode();
+ else if(skeletonRef != null)
+ return skeletonRef.skeletonHashCode();
+ else
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public int skeletonHashCode(int hash) {
+ if(ref != null)
+ return ref.skeletonHashCode(hash);
+ else if(skeletonRef != null)
+ return skeletonRef.skeletonHashCode(hash);
+ else
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ if(ref != null)
+ return ref.skeletonHashCode(hash, boundVars);
+ else if(skeletonRef != null)
+ return skeletonRef.skeletonHashCode(hash, boundVars);
+ else
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ return this == other;
+ }
+
+ @Override
+ public Type canonical() {
+ if(ref == null)
+ return this;
+ else
+ return ref = ref.canonical();
+ }
+
+ public void addListener(TMetaVarListener newListener) {
+ if(DEBUG)
+ System.out.println("addListener " + System.identityHashCode(this));
+ newListener.next = listener;
+ newListener.prev = this;
+ if(listener != null)
+ listener.prev = newListener;
+ listener = newListener;
+ }
+
+ private void fireNotifyAboutChange() {
+ if(DEBUG)
+ System.out.println("fireNotifyAboutChange " + System.identityHashCode(this) + " " + ref);
+ TMetaVarListener cur = listener;
+ listener = null;
+ while(cur != null) {
+ if(DEBUG)
+ System.out.println(" call listener");
+ cur.prev = null; // This prevents TMetaVarListener.remove from doing anything
+ cur.notifyAboutChange();
+ TMetaVarListener next = cur.next;
+ cur.next = null;
+ cur = next;
+ }
+ }
+
+ public TMetaVarListener getLatestListener() {
+ return listener;
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return kind;
+ }
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ // Assumes that this is already canonical skeleton
+ return EMPTY_ARRAY;
+ }