package org.simantics.scl.compiler.internal.parsing.types; import java.util.ArrayList; import java.util.Collections; import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext; import org.simantics.scl.compiler.elaboration.modules.TypeClass; import org.simantics.scl.compiler.environment.AmbiguousNameException; import org.simantics.scl.compiler.environment.Environments; import org.simantics.scl.compiler.internal.parsing.Symbol; import org.simantics.scl.compiler.internal.types.TypeElaborationContext; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.TPred; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.KindUnificationException; import org.simantics.scl.compiler.types.kinds.Kind; import org.simantics.scl.compiler.types.kinds.Kinds; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.TIntHashSet; /** * This class is a common base class for type-related nodes in an SCL abstract syntax tree. * sub-nodes of type nodes in the AST are restricted to the subclasses of this abstract base class. */ public abstract class TypeAst extends Symbol { public static final TypeAst[] EMPTY_ARRAY = new TypeAst[0]; @Override public String toString() { StringBuilder b = new StringBuilder(); toString(b); return b.toString(); } /** * Write a text representation of this node to a string builder. * All sub-classes must override this abstract method instead of * directly overriding the {@link #toString()} method. */ public abstract void toString(StringBuilder b); /** * Write a text representation of this node, with parenthesis if demanded by the precedence. * Literals that never need to be parenthesized can override this method directly. */ public void toString(StringBuilder b, int outerPrecedence) { if(getPrecedence() >= outerPrecedence) { b.append('('); toString(b); b.append(')'); } else toString(b); } /** * Translate this node into a Type instance usinga TypeTranslationContext, with expected Kind. */ public abstract Type toType(TypeTranslationContext context, Kind expectedKind); /** * Elaborate this node into a Type using a TypeElaborationContext. */ public abstract Type toType(TypeElaborationContext context); /** * Elaborate an array of type nodes into an array of Type instances. */ public static Type[] toTypes(TypeElaborationContext context, TypeAst[] typeAsts) { Type[] result = new Type[typeAsts.length]; for(int i=0;i parameters = new ArrayList(); ArrayList parameterKinds = new ArrayList(); TypeAst cur = this; loop: while(true) { if(cur instanceof TApplyAst) { TApplyAst apply = (TApplyAst)cur; for(int i=apply.parameters.length-1;i>=0;--i) { TypeAst parameter = apply.parameters[i]; Kind kind = Kinds.metaVar(); parameters.add(parameter.toType(context, kind)); parameterKinds.add(kind); } cur = apply.function; } else if(cur instanceof TVarAst) { TVarAst con = (TVarAst)cur; Collections.reverse(parameters); Collections.reverse(parameterKinds); TCon typeClass; try { typeClass = Environments.getTypeClassName(context.getEnvironment(), con.name); } catch (AmbiguousNameException e1) { context.getErrorLog().log(con.location, e1.getMessage()); break; } if(typeClass == null) { context.getErrorLog().log(con.location, "Unresolved type class " + con.name + "."); break; } TypeClass classDesc = context.getEnvironment().getTypeClass(typeClass); if(classDesc.parameters.length != parameters.size()) { context.getErrorLog().log(location, "Wrong number of parameters. " + classDesc.parameters.length + " parameters were expected."); break; } for(int i=0;i typeNameMap, TIntHashSet set); }