--- /dev/null
+package org.simantics.scl.compiler.elaboration.contexts;
+
+import gnu.trove.map.hash.THashMap;
+
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
+import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+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;
+
+public class TypeTranslationContext {
+
+ Environment environment;
+
+ ErrorLog errorLog;
+
+ THashMap<String, TVar> typeVariables = new THashMap<String, TVar>();
+
+ public TypeTranslationContext(ErrorLog errorLog, Environment environment) {
+ this.errorLog = errorLog;
+ this.environment = environment;
+ }
+
+ /**
+ * Convert a type AST node to a Type instance, using STAR as the expected kind.
+ * If the conversion fails with a syntax error exception, the returned value
+ * is a new type meta-variable.
+ *
+ * @param typeAst An AST node representing a type
+ * @return A Type instance.
+ */
+ public Type toType(TypeAst typeAst) {
+ return toType(typeAst, Kinds.STAR);
+ }
+
+ /**
+ * Convert a type AST node to a Type instance.
+ * If the conversion fails with a syntax error exception, the returned value
+ * is a new type meta-variable.
+ *
+ * @param typeAst An AST node representing a type
+ * @param kind A kind as which the node should be interpreted as
+ * @return A Type instance.
+ */
+ public Type toType(TypeAst typeAst, Kind kind) {
+ Type type;
+ try {
+ type = typeAst.toType(this, kind);
+ } catch(SCLSyntaxErrorException e) {
+ errorLog.log(e.location, e.getMessage());
+ return Types.metaVar(kind);
+ }
+ /*try {
+ type.checkKind(kindingContext, kind);
+ } catch (KindUnificationException e) {
+ errorLog.log(typeAst, "Invalid type " + type + ".");
+ }*/
+ return type;
+ }
+
+ public TVar resolveTypeVariable(long loc, String name, Kind expectedKind) {
+ TVar var = typeVariables.get(name);
+ if(var == null) {
+ var = Types.var(expectedKind);
+ typeVariables.put(name, var);
+ }
+ else
+ unify(loc, var.getKind(), expectedKind);
+ return var;
+ }
+
+ public TVar pushTypeVar(String name) {
+ return typeVariables.put(name, Types.var(Kinds.metaVar()));
+ }
+
+ public TVar addTypeVar(String name) {
+ TVar var = Types.var(Kinds.metaVar());
+ typeVariables.put(name, var);
+ return var;
+ }
+
+ public TVar popTypeVar(String name, TVar var) {
+ if(var == null)
+ return typeVariables.remove(name);
+ else
+ return typeVariables.put(name, var);
+ }
+
+ public TPred toTFuncApply(TypeAst typeAst) {
+ return typeAst.toTFuncApply(this);
+ }
+
+ public ErrorLog getErrorLog() {
+ return errorLog;
+ }
+
+ public Environment getEnvironment() {
+ return environment;
+ }
+
+ public Kind getKind(TCon con) {
+ return environment.getTypeConstructor(con).kind;
+ }
+
+ /**
+ * Unify the given kinds. An error message is logged, if the unification fails.
+ * @param loc location identifier
+ * @param provided actual kind
+ * @param expectedKind expected kind
+ */
+ public void unify(long loc, Kind provided, Kind expectedKind) {
+ try {
+ Kinds.unify(provided, expectedKind);
+ } catch (KindUnificationException e) {
+ errorLog.log(loc, "Expected a type with kind " + expectedKind + " but got " + provided + ".");
+ }
+ }
+}