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.TMetaVar;
import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
ErrorLog errorLog;
THashMap<String, TVar> typeVariables = new THashMap<String, TVar>();
+ THashMap<String, TMetaVar> existentials;
public TypeTranslationContext(CompilationContext compilationContext) {
this.compilationContext = compilationContext;
return var;
}
+ public TMetaVar resolveExistential(long loc, String name, Kind expectedKind) {
+ if(existentials == null)
+ existentials = new THashMap<String, TMetaVar>();
+ TMetaVar var = existentials.get(name);
+ if(var == null) {
+ var = Types.metaVar(expectedKind);
+ existentials.put(name, var);
+ }
+ else
+ unify(loc, var.getKind(), expectedKind);
+ return var;
+ }
+
public TVar pushTypeVar(String name) {
return typeVariables.put(name, Types.var(Kinds.metaVar()));
}
}
else if(Character.isLowerCase(c))
return context.resolveTypeVariable(location, name, expectedKind);
+ else if(c == '?')
+ return context.resolveExistential(location, name, expectedKind);
else {
TypeDescriptor tdesc;
try {
}
else if(Character.isLowerCase(c))
return context.resolveTypeVariable(name);
+ else if(c == '?')
+ return context.resolveExistential(name);
else {
con = context.resolveTypeConstructor(name);
if(con == null) {
char c = name.charAt(0);
if(Character.isLowerCase(c))
return context.resolveTypeVariable(name);
+ else if(c == '?')
+ return context.resolveExistential(name);
else {
Type con = context.resolveTypeConstructor(name);
if(con == null) {
package org.simantics.scl.compiler.internal.types;
+import org.simantics.scl.compiler.types.TMetaVar;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
public class TypeElaborationContext {
- THashMap<String, TVar> vars;
+ THashMap<String, TVar> vars;
+ THashMap<String, TMetaVar> existentials;
ITypeEnvironment environment;
public TypeElaborationContext(
this(new THashMap<String, TVar>(), environment);
}
+ public TMetaVar resolveExistential(String varName) {
+ if(existentials == null)
+ existentials = new THashMap<String, TMetaVar>();
+ TMetaVar var = existentials.get(varName);
+ if(var == null) {
+ var = Types.metaVar(Kinds.metaVar());
+ existentials.put(varName, var);
+ }
+ return var;
+ }
+
public TVar resolveTypeVariable(String varName) {
TVar var = vars.get(varName);
if(var == null) {
- var = Types.var(Kinds.STAR /* FIXME */);
+ var = Types.var(Kinds.metaVar());
vars.put(varName, var);
}
return var;
}
-
+
public TVar push(String varName) {
- return vars.put(varName, Types.var(Kinds.STAR /* FIXME */));
+ return vars.put(varName, Types.var(Kinds.metaVar()));
}
public TVar pop(String varName, TVar oldVar) {
@Override
public Type toType(TypeElaborationContext context) {
- return context.resolveTypeVariable(name);
+ return name.startsWith("?") ? context.resolveExistential(name) : context.resolveTypeVariable(name);
}
@Override
return parseType(new TypeElaborationContext(environment), text);
}
- public static Type parseType(ITypeEnvironment environment, THashMap<String, TVar> localTypeVars, String text) throws SCLTypeParseException {
- return parseType(new TypeElaborationContext(localTypeVars, environment), text);
- }
-
public static Type parseType(String text) throws SCLTypeParseException {
return parseType(new TypeElaborationContext(DUMMY_TYPE_ENVIRONMENT), text);
}
-
- public static Type parseType(THashMap<String, TVar> localTypeVars, String text) throws SCLTypeParseException {
- return parseType(new TypeElaborationContext(localTypeVars, DUMMY_TYPE_ENVIRONMENT), text);
- }
private static Type parseType(TypeElaborationContext context, String text) throws SCLTypeParseException {
SCLParserImpl parser = new SCLParserImpl(new StringReader(text));
package org.simantics.scl.compiler.tests;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
+import org.simantics.scl.compiler.module.repository.ImportFailureException;
import org.simantics.scl.compiler.module.repository.ModuleRepository;
import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
import org.simantics.scl.compiler.source.repository.SourceRepositories;
SourceRepositories.PRELUDE_SOURCE_REPOSITORY
));
+ public static EnvironmentSpecification DEFAULT_ENVIRONMENT_SPECIFICATION = new EnvironmentSpecification();
+ static {
+ DEFAULT_ENVIRONMENT_SPECIFICATION.importModule("Builtin", "");
+ DEFAULT_ENVIRONMENT_SPECIFICATION.importModule("Prelude", "");
+ }
+
public static ModuleRepository getInitialRepository() {
if(NO_PRELUDE)
return new ModuleRepository(SourceRepositories.BUILTIN_SOURCE_REPOSITORY);
else
return SCLOsgi.MODULE_REPOSITORY;
}
+
+ public static Environment getDefaultEnvironment() throws ImportFailureException {
+ return getInitialRepository().createEnvironment(DEFAULT_ENVIRONMENT_SPECIFICATION, null);
+ }
}
--- /dev/null
+package org.simantics.scl.compiler.tests.experimentation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.module.repository.ImportFailureException;
+import org.simantics.scl.compiler.tests.InitialRepository;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.UnificationException;
+
+public class TestExistential {
+ @Test
+ public void testExistentialTypes() throws ImportFailureException, UnificationException {
+ Environment environment = InitialRepository.getDefaultEnvironment();
+ Type type1 = Environments.getType(environment, "?a -> String -> ?a");
+ Type type2 = Environments.getType(environment, "Integer -> ?b -> ?c");
+ Assert.assertEquals("a -> String -> a", type1.toString());
+ Assert.assertEquals("Integer -> a -> b", type2.toString());
+ Types.unify(type1, type2);
+ Assert.assertEquals("Integer -> String -> Integer", type1.toString());
+ }
+}