1 package org.simantics.scl.compiler.internal.parsing.types;
3 import java.util.ArrayList;
4 import java.util.Collections;
6 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
7 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
8 import org.simantics.scl.compiler.environment.AmbiguousNameException;
9 import org.simantics.scl.compiler.environment.Environments;
10 import org.simantics.scl.compiler.internal.parsing.Symbol;
11 import org.simantics.scl.compiler.internal.types.TypeElaborationContext;
12 import org.simantics.scl.compiler.types.TCon;
13 import org.simantics.scl.compiler.types.TPred;
14 import org.simantics.scl.compiler.types.Type;
15 import org.simantics.scl.compiler.types.Types;
16 import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
17 import org.simantics.scl.compiler.types.kinds.Kind;
18 import org.simantics.scl.compiler.types.kinds.Kinds;
20 import gnu.trove.map.hash.TObjectIntHashMap;
21 import gnu.trove.set.hash.TIntHashSet;
25 * This class is a common base class for type-related nodes in an SCL abstract syntax tree.
26 * sub-nodes of type nodes in the AST are restricted to the subclasses of this abstract base class.
28 public abstract class TypeAst extends Symbol {
29 public static final TypeAst[] EMPTY_ARRAY = new TypeAst[0];
32 public String toString() {
33 StringBuilder b = new StringBuilder();
39 * Write a text representation of this node to a string builder.
40 * All sub-classes must override this abstract method instead of
41 * directly overriding the {@link #toString()} method.
43 public abstract void toString(StringBuilder b);
46 * Write a text representation of this node, with parenthesis if demanded by the precedence.
47 * Literals that never need to be parenthesized can override this method directly.
49 public void toString(StringBuilder b, int outerPrecedence) {
50 if(getPrecedence() >= outerPrecedence) {
60 * Translate this node into a Type instance usinga TypeTranslationContext, with expected Kind.
62 public abstract Type toType(TypeTranslationContext context, Kind expectedKind);
65 * Elaborate this node into a Type using a TypeElaborationContext.
67 public abstract Type toType(TypeElaborationContext context);
70 * Elaborate an array of type nodes into an array of Type instances.
72 public static Type[] toTypes(TypeElaborationContext context, TypeAst[] typeAsts) {
73 Type[] result = new Type[typeAsts.length];
74 for(int i=0;i<typeAsts.length;++i)
75 result[i] = typeAsts[i].toType(context);
80 * Translate an array of type nodes into an array of Type instances, using Kinds.STAR is the expected kind.
82 public static Type[] toTypes(TypeTranslationContext context, TypeAst[] typeAsts) {
83 Type[] result = new Type[typeAsts.length];
84 for(int i=0;i<typeAsts.length;++i)
85 result[i] = typeAsts[i].toType(context, Kinds.STAR);
90 * Get a TPred instance from this node as a type function application (a type class restriction).
92 public TPred toTFuncApply(TypeTranslationContext context) {
93 ArrayList<Type> parameters = new ArrayList<Type>();
94 ArrayList<Kind> parameterKinds = new ArrayList<Kind>();
97 if(cur instanceof TApplyAst) {
98 TApplyAst apply = (TApplyAst)cur;
99 for(int i=apply.parameters.length-1;i>=0;--i) {
100 TypeAst parameter = apply.parameters[i];
101 Kind kind = Kinds.metaVar();
102 parameters.add(parameter.toType(context, kind));
103 parameterKinds.add(kind);
105 cur = apply.function;
107 else if(cur instanceof TVarAst) {
108 TVarAst con = (TVarAst)cur;
109 Collections.reverse(parameters);
110 Collections.reverse(parameterKinds);
113 typeClass = Environments.getTypeClassName(context.getEnvironment(), con.name);
114 } catch (AmbiguousNameException e1) {
115 context.getErrorLog().log(con.location, e1.getMessage());
118 if(typeClass == null) {
119 context.getErrorLog().log(con.location, "Unresolved type class " + con.name + ".");
122 TypeClass classDesc = context.getEnvironment().getTypeClass(typeClass);
123 if(classDesc.parameters.length != parameters.size()) {
124 context.getErrorLog().log(location, "Wrong number of parameters. " + classDesc.parameters.length + " parameters were expected.");
127 for(int i=0;i<parameterKinds.size();++i)
129 Kinds.unify(parameterKinds.get(i), classDesc.parameters[i].getKind());
130 } catch(KindUnificationException e) {
131 context.getErrorLog().log(location, "Parameter kinds do not match. The kind of the parameter " +
132 (i+1) + " should be " + classDesc.parameters[i].getKind() + ".");
137 parameters.toArray(new Type[parameters.size()]));
140 context.getErrorLog().log(location, "Invalid constraint.");
144 // Returns something dummy
145 return Types.pred(Types.ORD, Types.metaVar(Kinds.STAR));
149 * Elaborate this node to a type function application. Not supported for all type definition nodes.
150 * @throw UnsupportedOperationException The node does not support elaboration.
152 public TPred toTFuncApply(TypeElaborationContext context) {
153 throw new UnsupportedOperationException();
157 * Get node precedence. TVarAst, TEffectAst, TListAst and TTupleAst nodes have precedence 0, TApplyAst has 1,
158 * and TPredAst, TForAllAst and TFunctionAst 2.
160 * The precedence value is used for generating parentheses in deparsed expressions.
162 public abstract int getPrecedence();
165 * Translate this node to an effect Type. Not all type definition constructs are allowed for effects.
166 * @throw UnsupportedOperationException An illegal type definition constuct for effects has been used.
168 public Type toEffect(TypeTranslationContext context) {
169 throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support toEffect.");
173 * Elaborate this node to an effect Type. Not all type definition constructs are allowed for effects.
174 * @throw UnsupportedOperationException An illegal type definition constuct for effects has been used.
176 public Type toEffect(TypeElaborationContext context) {
177 throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support toEffect.");
180 public abstract void collectReferences(TObjectIntHashMap<String> typeNameMap, TIntHashSet set);