--- /dev/null
+package org.simantics.scl.compiler.internal.parsing.types;
+
+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.TCon;
+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;
+
+
+/**
+ * This class represents an abstract syntax tree node for a type variable.
+ * The only property of a type variable is its name.
+ */
+public class TVarAst extends TypeAst {
+ public final String name;
+
+ public TVarAst(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void toString(StringBuilder b) {
+ b.append(name);
+ }
+
+ @Override
+ public Type toType(TypeTranslationContext context, Kind expectedKind) {
+ char c = name.charAt(0);
+ TCon con;
+ block: {
+ if(c == '(') {
+ for(int i=1;i<name.length()-1;++i)
+ if(name.charAt(i) != ',') {
+ try {
+ con = Environments.getTypeConstructorName(context.getEnvironment(), name.substring(1, name.length()-1));
+ } catch(AmbiguousNameException e) {
+ context.getErrorLog().log(location, e.getMessage());
+ return Types.metaVar(Kinds.STAR);
+ }
+ if(con == null) {
+ context.getErrorLog().log(location, "Didn't find type constructor " + name + ".");
+ return Types.metaVar(Kinds.STAR);
+ }
+ break block;
+ }
+ con = Types.con(Types.BUILTIN, name);
+ }
+ else if(Character.isLowerCase(c))
+ return context.resolveTypeVariable(location, name, expectedKind);
+ else {
+ TypeAlias alias;
+ try {
+ alias = Environments.getTypeAlias(context.getEnvironment(), name);
+ } catch (AmbiguousNameException e1) {
+ context.getErrorLog().log(location, e1.getMessage());
+ return Types.metaVar(Kinds.STAR);
+ }
+ if(alias != null) {
+ if(alias.getArity() > 0) {
+ context.getErrorLog().log(location, "The alias expects " +
+ alias.getArity() + " parameters, but none are given.");
+ return Types.metaVar(Kinds.metaVar());
+ }
+ return alias.body;
+ }
+ try {
+ con = Environments.getTypeConstructorName(context.getEnvironment(), name);
+ } catch(AmbiguousNameException e) {
+ context.getErrorLog().log(location, e.getMessage());
+ return Types.metaVar(Kinds.STAR);
+ }
+ if(con == null) {
+ context.getErrorLog().log(location, "Didn't find type constructor " + name + ".");
+ return Types.metaVar(Kinds.STAR);
+ }
+ }
+ }
+
+ Kind providedKind = context.getKind(con);
+ context.unify(location, providedKind, expectedKind);
+ return con;
+ }
+
+ @Override
+ public Type toType(TypeElaborationContext context) {
+ char c = name.charAt(0);
+ Type con;
+ block: {
+ if(c == '(') {
+ for(int i=1;i<name.length()-1;++i)
+ if(name.charAt(i) != ',') {
+ con = context.resolveTypeConstructor(name.substring(1, name.length()-1));
+ if(con == null) {
+ System.err.println("Didn't find type constructor " + name + ".");
+ return Types.metaVar(Kinds.STAR);
+ }
+ break block;
+ }
+ con = Types.con(Types.BUILTIN, name);
+ }
+ else if(Character.isLowerCase(c))
+ return context.resolveTypeVariable(name);
+ else {
+ con = context.resolveTypeConstructor(name);
+ if(con == null) {
+ System.err.println("Didn't find type constructor " + name + ".");
+ return Types.metaVar(Kinds.STAR);
+ }
+ }
+ }
+
+ return con;
+ }
+
+ /**
+ * Translate this variable reference to an effect Type. Lower initial names are treated as
+ * type meta-variables. Capitalized names are resolved as effect name constants.
+ *
+ * Error messages about unresolved or ambiguous effect names are logged, with a new meta-variable
+ * as the return value.
+ */
+ @Override
+ public Type toEffect(TypeTranslationContext context) {
+ char c = name.charAt(0);
+ if(Character.isLowerCase(c))
+ return context.resolveTypeVariable(location, name, Kinds.EFFECT);
+ else {
+ TCon con;
+ try {
+ con = Environments.getEffectConstructorName(context.getEnvironment(), name);
+ } catch (AmbiguousNameException e) {
+ context.getErrorLog().log(location, e.getMessage());
+ return Types.metaVar(Kinds.EFFECT);
+ }
+ if(con == null) {
+ context.getErrorLog().log(location, "Didn't find effect constructor " + name + ".");
+ return Types.metaVar(Kinds.EFFECT);
+ }
+ return con;
+ }
+ }
+
+ @Override
+ public Type toEffect(TypeElaborationContext context) {
+ char c = name.charAt(0);
+ if(Character.isLowerCase(c))
+ return context.resolveTypeVariable(name);
+ else {
+ Type con = context.resolveTypeConstructor(name);
+ if(con == null) {
+ System.err.println("Didn't find effect constructor " + name + ".");
+ return Types.metaVar(Kinds.EFFECT);
+ }
+ return con;
+ }
+ }
+
+ @Override
+ public int getPrecedence() {
+ return 0;
+ }
+
+ @Override
+ public void collectReferences(TObjectIntHashMap<String> typeNameMap,
+ TIntHashSet set) {
+ if(typeNameMap.containsKey(name))
+ set.add(typeNameMap.get(name));
+ }
+}