package org.simantics.scl.compiler.elaboration.contexts; import org.simantics.scl.compiler.compilation.CompilationContext; 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; import gnu.trove.map.hash.THashMap; public class TypeTranslationContext { CompilationContext compilationContext; Environment environment; ErrorLog errorLog; THashMap typeVariables = new THashMap(); public TypeTranslationContext(CompilationContext compilationContext) { this.compilationContext = compilationContext; this.errorLog = compilationContext.errorLog; this.environment = compilationContext.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.getTypeDescriptor(con).getKind(); } /** * 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 + "."); } } public CompilationContext getCompilationContext() { return compilationContext; } }