package org.simantics.scl.compiler.types; import java.util.ArrayList; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.internal.codegen.utils.NameMangling; import org.simantics.scl.compiler.internal.types.HashCodeUtils; import org.simantics.scl.compiler.internal.types.TypeHashCodeContext; import org.simantics.scl.compiler.internal.types.ast.TConAst; import org.simantics.scl.compiler.internal.types.ast.TypeAst; import org.simantics.scl.compiler.types.exceptions.KindUnificationException; import org.simantics.scl.compiler.types.kinds.Kind; import org.simantics.scl.compiler.types.util.Polarity; import org.simantics.scl.compiler.types.util.TypeUnparsingContext; import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; /** * This class represents an SCL type constant with a name given in a module. */ public final class TCon extends Type { public final String module; public final String name; TCon(String module, String name) { if(NULL_CHECKS) { if(module == null || name == null) throw new NullPointerException(); } this.module = module; this.name = name; } @Override public TCon replace(TVar var, Type replacement) { // Constants don't include type variables return this; } @Override public TypeAst toTypeAst(TypeUnparsingContext context) { if(module == Types.BUILTIN) { char c = name.charAt(0); if(Character.isLetter(c) || c == '(' || name.equals("[]")) return new TConAst(name); else return new TConAst("(" + name + ")"); } else return new TConAst(name.length() <= 1 ? simplifiedModuleName(module) + "." + name : name); } private static String simplifiedModuleName(String name) { int p = name.lastIndexOf('/'); if(p == -1) return name; else return name.substring(p+1); } @Override public boolean equals(Object obj) { while(obj instanceof TMetaVar) { TMetaVar metaVar = (TMetaVar)obj; if(metaVar.ref == null) return false; else obj = metaVar.ref; } return this == obj; } @Override public void updateHashCode(TypeHashCodeContext context) { context.append(System.identityHashCode(this)); } @Override public void collectFreeVars(ArrayList vars) { } @Override public void collectMetaVars(ArrayList vars) { } @Override public void collectMetaVars(THashSet vars) { } @Override public void collectEffectMetaVars(ArrayList vars) { } @Override public boolean isGround() { return true; } public Kind inferKind(Environment context) throws KindUnificationException { return context.getTypeDescriptor(this).getKind(); } public Kind getKind(Environment context) { return context.getTypeDescriptor(this).getKind(); } @Override public boolean containsMetaVars() { return false; } @Override public void toName(TypeUnparsingContext context, StringBuilder b) { b.append(NameMangling.mangle(name)); } @Override public int getClassId() { return CON_ID; } @Override public boolean contains(TMetaVar other) { return false; } @Override public Type convertMetaVarsToVars() { return this; } @Override public void addPolarity(Polarity polarity) { } @Override public void collectConcreteEffects(ArrayList concreteEffects) { concreteEffects.add(this); } @Override public Type head() { return this; } @Override public Type copySkeleton(THashMap metaVarMap) { return this; } @Override public int hashCode() { return System.identityHashCode(this); } @Override public int hashCode(int hash) { return HashCodeUtils.update(hash, System.identityHashCode(this)); } @Override public int hashCode(int hash, TVar[] boundVars) { return HashCodeUtils.update(hash, System.identityHashCode(this)); } @Override public int skeletonHashCode() { return System.identityHashCode(this); } @Override public int skeletonHashCode(int hash) { return HashCodeUtils.update(hash, System.identityHashCode(this)); } @Override public int skeletonHashCode(int hash, TVar[] boundVars) { return HashCodeUtils.update(hash, System.identityHashCode(this)); } @Override public boolean equalsCanonical(Type other) { return this == other; } @Override public Type[] skeletonCanonicalChildren() { return EMPTY_ARRAY; } }