]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TMetaVar.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / types / TMetaVar.java
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
new file mode 100644 (file)
index 0000000..8d2307b
--- /dev/null
@@ -0,0 +1,234 @@
+package org.simantics.scl.compiler.types;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
+import org.simantics.scl.compiler.internal.types.ast.TVarAst;
+import org.simantics.scl.compiler.internal.types.ast.TypeAst;
+import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
+import org.simantics.scl.compiler.types.exceptions.UnificationException;
+import org.simantics.scl.compiler.types.kinds.KMetaVar;
+import org.simantics.scl.compiler.types.kinds.Kind;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.simantics.scl.compiler.types.util.Polarity;
+import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+
+
+
+/**
+ * A meta-variable, a type that is currently unknown. This class
+ * should occur only during type inference. Method removeMetaVars
+ * can be used to remove all instances of TMetaVar from the type.
+ * 
+ * @author Hannu Niemistö
+ */
+public class TMetaVar extends Type {
+    public static final TMetaVar[] EMPTY_ARRAY = new TMetaVar[0];
+    
+    Type ref = null;
+    Polarity polarity = Polarity.NO_POLARITY;
+    private Kind kind;
+    
+    TMetaVar(Kind kind) {
+        this.kind = kind;
+    }
+    
+    TMetaVar(Kind kind, Polarity polarity) {
+        this.kind = kind;
+        this.polarity = polarity;
+    }
+    
+    public Kind getKind() {
+        if(kind instanceof KMetaVar)
+            kind = Kinds.canonical(kind);
+        return kind;        
+    }
+    
+    @Override
+    public Type replace(TVar var, Type replacement) {
+        if(ref == null)
+            return this;
+        else {
+            Type newRef = ref.replace(var, replacement);
+            if(newRef != ref)
+                return newRef;
+            else
+                // We could also return newRef here, but in this way
+                // we don't have to copy so many parent types.
+                return this;
+        }
+    }
+
+    @Override
+    public TypeAst toTypeAst(TypeUnparsingContext context) {
+        if(ref == null)
+            return new TVarAst(/*polarity.getSymbol() +*/ context.getName(this));
+        else
+            return ref.toTypeAst(context);
+    }
+    
+    @Override
+    public int hashCode() {
+        if(ref == null)
+            return System.identityHashCode(this);
+        else
+            return ref.hashCode();
+    }
+    
+    @Override
+    public void updateHashCode(TypeHashCodeContext context) {
+        if(ref == null)
+            context.append(System.identityHashCode(this));
+        else
+            ref.updateHashCode(context);
+    }
+
+    @Override
+    public void collectFreeVars(ArrayList<TVar> vars) {
+        if(ref != null)
+            ref.collectFreeVars(vars);
+    }
+    
+    @Override
+    public void collectMetaVars(ArrayList<TMetaVar> vars) {
+        if(ref == null)
+            vars.add(this);
+        else
+            ref.collectMetaVars(vars);
+    }
+    
+    @Override
+    public void collectMetaVars(THashSet<TMetaVar> vars) {
+        if(ref == null)
+            vars.add(this);
+        else
+            ref.collectMetaVars(vars);
+    }
+    
+    @Override
+    public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
+        if(ref != null)
+            ref.collectEffectMetaVars(vars);
+    }
+
+    public void setRef(Type a) throws UnificationException {
+        a = Types.weakCanonical(a);
+        if(a.contains(this))
+            throw new UnificationException(this, a);
+        ref = a;
+        if(polarity != Polarity.NO_POLARITY)
+            a.addPolarity(polarity);
+    }
+    
+    public Type getRef() {
+        return ref;
+    }
+    
+    @Override
+    public boolean contains(TMetaVar other) {
+        if(ref == null)
+            return this == other;
+        else
+            return ref.contains(other);
+    }
+    
+    @Override
+    public Type convertMetaVarsToVars() {
+        if(ref == null) {
+            if(kind == Kinds.EFFECT && !polarity.isNegative())
+                ref = Types.NO_EFFECTS;
+            else
+                ref = Types.var(getKind());
+            return ref;
+        }
+        else
+            return ref.convertMetaVarsToVars();
+    }
+
+    @Override
+    public boolean isGround() {
+        if(ref == null)
+            return false;
+        else
+            return ref.isGround();
+    }
+
+       public Kind inferKind(Environment context) throws KindUnificationException {
+           return Kinds.metaVar();
+    }
+
+    @Override
+    public boolean containsMetaVars() {
+        if(ref == null)
+            return true;
+        else
+            return ref.containsMetaVars();
+    }
+
+    @Override
+    public void toName(TypeUnparsingContext context, StringBuilder b) {
+        if(ref != null)
+            ref.toName(context, b);
+        else
+            b.append(context.getName(this));
+    }
+    
+    @Override
+    public int getClassId() {
+        return METAVAR_ID;
+    }
+    @Override
+    public boolean isMaximal() {
+        return ref != null && ref.isMaximal(); 
+    }
+    
+    @Override
+    public boolean isMinimal() {
+        return ref != null && ref.isMinimal();
+    }
+
+    @Override
+    public void addPolarity(Polarity polarity) {        
+        if(ref != null)
+            ref.addPolarity(polarity);
+        else
+            this.polarity = this.polarity.add(polarity);
+    }
+
+    public Polarity getPolarity() {
+        return polarity;
+    }
+    
+    @Override
+    public void collectConcreteEffects(ArrayList<TCon> concreteEffects) {
+        if(ref != null)
+            ref.collectConcreteEffects(concreteEffects);
+    }
+
+    @Override
+    public Type head() {
+        if(ref != null)
+            return ref.head();
+        else
+            return this;
+    }
+
+    @Override
+    public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
+        if(ref != null)
+            return ref.copySkeleton(metaVarMap);
+        else {
+            TMetaVar result = metaVarMap.get(this);
+            if(result == null) {
+                result = new TMetaVar(kind, polarity);
+                metaVarMap.put(this, result);
+            }
+            return result;
+        }
+    }
+}