--- /dev/null
+package org.simantics.scl.compiler.types.util;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.types.Skeletons;
+import org.simantics.scl.compiler.types.TApply;
+import org.simantics.scl.compiler.types.TForAll;
+import org.simantics.scl.compiler.types.TFun;
+import org.simantics.scl.compiler.types.TMetaVar;
+import org.simantics.scl.compiler.types.TMetaVar.TMetaVarListener;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.Type;
+
+public abstract class TypeListener {
+ private ArrayList<TMetaVarListener> metaVarListeners = new ArrayList<TMetaVarListener>(2);
+ public abstract void notifyAboutChange();
+
+ private static class SubListener extends TMetaVarListener {
+ private final TypeListener parent;
+ public SubListener(TypeListener parent) {
+ this.parent = parent;
+ } @Override
+ public void notifyAboutChange() {
+ for(TMetaVarListener otherListeners : parent.metaVarListeners)
+ otherListeners.remove();
+ parent.notifyAboutChange();
+ }
+ };
+
+ public void listenSkeleton(Type type) {
+ type = Skeletons.canonicalSkeleton(type);
+ if(type instanceof TMetaVar) {
+ TMetaVar metaVar = (TMetaVar)type;
+ TMetaVarListener latestListener = metaVar.getLatestListener();
+ if(latestListener instanceof SubListener &&
+ ((SubListener)latestListener).parent == this)
+ return;
+
+ SubListener subListener = new SubListener(this);
+ metaVarListeners.add(subListener);
+ metaVar.addListener(subListener);
+ }
+ else if(type instanceof TApply) {
+ TApply apply = (TApply)type;
+ listenSkeleton(apply.function);
+ listenSkeleton(apply.parameter);
+ }
+ else if(type instanceof TFun) {
+ TFun fun = (TFun)type;
+ listenSkeleton(fun.domain);
+ listenSkeleton(fun.range);
+ }
+ else if(type instanceof TForAll) {
+ TForAll forAll = (TForAll)type;
+ listenSkeleton(forAll.type);
+ }
+ else if(type instanceof TPred) {
+ TPred pred = (TPred)type;
+ for(Type parameter : pred.parameters)
+ listenSkeleton(parameter);
+ }
+ }
+}