X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Ftypes%2FTMetaVar.java;h=1596467bc2931541350fdfd0fd27a424e084e882;hp=d78d745eb670c0ccb99719c2690e314e6a610488;hb=5bed099be36a76e204265abb2f471d84050c0d66;hpb=4bf8562ab7cbb3747f9c5844a07469291d43e905 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TMetaVar.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TMetaVar.java index d78d745eb..1596467bc 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TMetaVar.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TMetaVar.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.types; import java.util.ArrayList; +import org.simantics.databoard.util.IdentityHashSet; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.internal.types.HashCodeUtils; @@ -91,10 +92,12 @@ public class TMetaVar extends Type { @Override public TypeAst toTypeAst(TypeUnparsingContext context) { - if(ref == null) - return new TVarAst(/*polarity.getSymbol() +*/ context.getName(this)); - else + if(ref != null) return ref.toTypeAst(context); + else if(context.showSkeletons && skeletonRef != null) + return skeletonRef.toTypeAst(context); + else + return new TVarAst(/*polarity.getSymbol() +*/ context.getName(this)); } @Override @@ -134,27 +137,116 @@ public class TMetaVar extends Type { } public void setRef(Type type) throws UnificationException { - if(type instanceof TMetaVar && ((TMetaVar)type).ref != null) - throw new InternalCompilerError("Not canonical!"); + //System.out.println("----"); + //System.out.println("this = " + refStructure(this)); + //System.out.println("type = " + refStructure(type)); if(type == this) throw new InternalCompilerError("Illegal setRef"); if(DEBUG) System.out.println("setRef " + System.identityHashCode(this) + " -> " + type); if(ref != null) throw new InternalCompilerError("Method setRef should be called only for unbound meta variables."); - if(type.contains(this)) + Type thisSkeleton = Skeletons.canonicalSkeleton(this); + + if(type instanceof TMetaVar) { + TMetaVar other = (TMetaVar)type; + if(other.ref != null) + throw new InternalCompilerError("Not canonical!"); + + Type typeSkeleton = Skeletons.canonicalSkeleton(type); + if(thisSkeleton == typeSkeleton) { + if(skeletonRef != null) + setRefBase(type); + else + other.setRefBase(this); + return; + } + else if(thisSkeleton instanceof TMetaVar && type.contains((TMetaVar)thisSkeleton)) + throw new UnificationException(this, type); + } + else if(thisSkeleton instanceof TMetaVar && type.contains((TMetaVar)thisSkeleton)) throw new UnificationException(this, type); + + // Common case + if(skeletonRef != null) { + Skeletons.unifySkeletons(thisSkeleton, type); + if(ref != null) { + Types.unify(this, type); + return; + } + } + setRefBase(type); + } + + private void setRefBase(Type type) throws UnificationException { + skeletonRef = null; ref = type; if(polarity != Polarity.NO_POLARITY) type.addPolarity(polarity); - if(skeletonRef != null) { - Type skeleton = skeletonRef; - skeletonRef = null; - Skeletons.unifySkeletons(skeleton, type); - } + //System.out.println("result = " + refStructure(this)); + //checkRefLoop(this); fireNotifyAboutChange(); } + private static String refStructure(Type t) { + StringBuilder b = new StringBuilder(); + IdentityHashSet seenVars = new IdentityHashSet(); + refType(b, t, seenVars); + return b.toString(); + } + + private void refStructure(StringBuilder b, IdentityHashSet seenVars) { + b.append(System.identityHashCode(this)); + if(!seenVars.add(this)) + b.append(" (loop)"); + else if(ref != null) { + b.append(" => "); + refType(b, ref, seenVars); + } + else if(skeletonRef != null) { + b.append(" -> "); + refType(b, skeletonRef, seenVars); + } + else + b.append(" (canonical)"); + } + + private static void refType(StringBuilder b, Type t, IdentityHashSet seenVars) { + if(t instanceof TMetaVar) + ((TMetaVar)t).refStructure(b, seenVars); + else { + b.append('['); + t.toString(new TypeUnparsingContext(), b); + b.append(']'); + } + } + + private void checkRefLoop(TMetaVar var) { + IdentityHashSet seenVars = new IdentityHashSet(); + StringBuilder b = new StringBuilder(); + while(true) { + b.append(var); + if(!seenVars.add(var)) + throw new InternalCompilerError("Cyclic meta var references: " + b); + if(var.ref != null) { + b.append(" => "); + if(var.ref instanceof TMetaVar) + var = (TMetaVar)var.ref; + else + return; + } + else if(var.skeletonRef != null) { + b.append(" -> "); + if(var.skeletonRef instanceof TMetaVar) + var = (TMetaVar)var.skeletonRef; + else + return; + } + else + return; + } + } + public Type getRef() { return ref; } @@ -273,6 +365,7 @@ public class TMetaVar extends Type { if(type.contains(this)) throw new UnificationException(this, type); this.skeletonRef = type; + //checkRefLoop(this); fireNotifyAboutChange(); }