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 metaVarListeners = new ArrayList(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); } } }