--- /dev/null
+package org.simantics.scl.compiler.internal.parsing.types;
+
+import java.util.Arrays;
+
+import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
+import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
+import org.simantics.scl.compiler.environment.AmbiguousNameException;
+import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.internal.types.TypeElaborationContext;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+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;
+
+
+public class TApplyAst extends TypeAst {
+ public final TypeAst function;
+ public final TypeAst[] parameters;
+
+ public TApplyAst(TypeAst function, TypeAst[] parameters) {
+ this.function = function;
+ this.parameters = parameters;
+ }
+
+ @Override
+ public void toString(StringBuilder b) {
+ function.toString(b, 2);
+ for(TypeAst parameter : parameters) {
+ b.append(' ');
+ parameter.toString(b, 1);
+ }
+ }
+
+ @Override
+ public Type toType(TypeTranslationContext context, Kind expectedKind) {
+ if(function instanceof TVarAst) {
+ String name = ((TVarAst)function).name;
+ TypeAlias alias;
+ try {
+ alias = Environments.getTypeAlias(context.getEnvironment(), name);
+ } catch (AmbiguousNameException e) {
+ context.getErrorLog().log(location, e.getMessage());
+ return Types.metaVar(Kinds.STAR);
+ }
+ if(alias != null) {
+ if(parameters.length != alias.getArity()) {
+ context.getErrorLog().log(location, "Wrong number of parameters are given to the type alias. Expected " +
+ alias.getArity() + " parameters, got " + parameters.length + " parameters.");
+ return Types.metaVar(Kinds.metaVar());
+ }
+ Type[] parameterTypes = new Type[parameters.length];
+ for(int i=0;i<parameters.length;++i)
+ parameterTypes[i] = parameters[i].toType(context, Kinds.metaVar());
+ return alias.body.replace(alias.parameters, parameterTypes);
+ }
+ }
+
+ Kind[] parameterKinds = new Kind[parameters.length];
+ Kind functionKind = expectedKind;
+ for(int i=parameters.length-1;i>=0;--i) {
+ Kind kind = Kinds.metaVar();
+ parameterKinds[i] = kind;
+ functionKind = Kinds.arrow(kind, functionKind);
+ }
+ Type functionType = function.toType(context, functionKind);
+ Type[] parameterTypes = new Type[parameters.length];
+ for(int i=0;i<parameters.length;++i) {
+ parameterTypes[i] = parameters[i].toType(context, parameterKinds[i]);
+ }
+ return Types.apply(functionType, parameterTypes);
+ }
+
+ @Override
+ public Type toType(TypeElaborationContext context) {
+ Type functionType = function.toType(context);
+ Type[] parameterTypes = new Type[parameters.length];
+ for(int i=0;i<parameters.length;++i)
+ parameterTypes[i] = parameters[i].toType(context);
+ return Types.apply(functionType, parameterTypes);
+ }
+
+ @Override
+ public int getPrecedence() {
+ return 1;
+ }
+
+ public static TApplyAst apply(TypeAst f, TypeAst p) {
+ if(f instanceof TApplyAst) {
+ TApplyAst fApply = (TApplyAst)f;
+ TypeAst[] parameters = Arrays.copyOf(fApply.parameters,
+ fApply.parameters.length+1);
+ parameters[fApply.parameters.length] = p;
+ return new TApplyAst(fApply.function, parameters);
+ }
+ else
+ return new TApplyAst(f, new TypeAst[] {p});
+ }
+
+ @Override
+ public void collectReferences(TObjectIntHashMap<String> typeNameMap,
+ TIntHashSet set) {
+ function.collectReferences(typeNameMap, set);
+ for(TypeAst parameter : parameters)
+ parameter.collectReferences(typeNameMap, set);
+ }
+
+}