]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
(refs #7588) Support for existential type variables with syntax ?v 71/1171/1
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Wed, 1 Nov 2017 07:11:18 +0000 (09:11 +0200)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Wed, 1 Nov 2017 07:11:18 +0000 (09:11 +0200)
Change-Id: I418a9d260c02c7082e7a7359b90659ea2c3a96d4

bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/types/TVarAst.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/types/TypeElaborationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/types/ast/TVarAst.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/Types.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/InitialRepository.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/experimentation/TestExistential.java [new file with mode: 0644]

index 1eea959fd249459273a9139008b86d29ac9a2d0c..d107cb621a2dc9ff5ccceb18b4909643832151cd 100644 (file)
@@ -6,6 +6,7 @@ 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.TMetaVar;
 import org.simantics.scl.compiler.types.TPred;
 import org.simantics.scl.compiler.types.TVar;
 import org.simantics.scl.compiler.types.Type;
@@ -25,6 +26,7 @@ public class TypeTranslationContext {
     ErrorLog errorLog;    
     
     THashMap<String, TVar> typeVariables = new THashMap<String, TVar>();
+    THashMap<String, TMetaVar> existentials;
     
     public TypeTranslationContext(CompilationContext compilationContext) {
         this.compilationContext = compilationContext;
@@ -80,6 +82,19 @@ public class TypeTranslationContext {
         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()));
     }
index e95b3ad9a9a4cdf21aab2abafa835b6457d013ad..84d3e3a01d4f37fd02e6fc331ba979b40bf7aa99 100644 (file)
@@ -56,6 +56,8 @@ public class TVarAst extends TypeAst {
             }
             else if(Character.isLowerCase(c))
                 return context.resolveTypeVariable(location, name, expectedKind);
+            else if(c == '?')
+                return context.resolveExistential(location, name, expectedKind);
             else {
                 TypeDescriptor tdesc;
                 try {
@@ -105,6 +107,8 @@ public class TVarAst extends TypeAst {
             }
             else if(Character.isLowerCase(c))
                 return context.resolveTypeVariable(name);
+            else if(c == '?')
+                return context.resolveExistential(name);
             else {                
                 con = context.resolveTypeConstructor(name);
                 if(con == null) {
@@ -150,6 +154,8 @@ public class TVarAst extends TypeAst {
         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) {
index bfde4677352e4cff7e74661811f8e654a91c8c02..8e638a08984186e97f1c2e0b472e8356348e6d33 100644 (file)
@@ -1,5 +1,6 @@
 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;
@@ -10,7 +11,8 @@ import gnu.trove.map.hash.THashMap;
 
 public class TypeElaborationContext {
 
-    THashMap<String, TVar> vars; 
+    THashMap<String, TVar> vars;
+    THashMap<String, TMetaVar> existentials;
     ITypeEnvironment environment;
         
     public TypeElaborationContext(
@@ -24,17 +26,28 @@ public class 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) {
index 24a6d9aeb4078e29668c9850772f40aca10784bc..b9c8b6b577c17f3d6ed8d814a749a6a9e2fb4152 100644 (file)
@@ -19,7 +19,7 @@ public class TVarAst extends TypeAst {
 
     @Override
     public Type toType(TypeElaborationContext context) {
-        return context.resolveTypeVariable(name);
+        return name.startsWith("?") ? context.resolveExistential(name) : context.resolveTypeVariable(name);
     }
 
     @Override
index 50eec32fe29e9f8c37209f91eba6e2709f88aa59..00e60a6367dc0707a8d002d5c00d84521ad103d4 100644 (file)
@@ -1124,17 +1124,9 @@ public class Types {
         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));
index 5608689f512079c8a01c76fa50e63476d767e888..87ea5274d23aa0947d56c0d7163b67d3afa17368 100644 (file)
@@ -1,5 +1,8 @@
 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;
@@ -14,6 +17,12 @@ public class InitialRepository {
                     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);
@@ -22,4 +31,8 @@ public class InitialRepository {
         else
             return SCLOsgi.MODULE_REPOSITORY;
     }
+    
+    public static Environment getDefaultEnvironment() throws ImportFailureException {
+        return getInitialRepository().createEnvironment(DEFAULT_ENVIRONMENT_SPECIFICATION, null);
+    }
 }
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/experimentation/TestExistential.java b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/experimentation/TestExistential.java
new file mode 100644 (file)
index 0000000..31f9981
--- /dev/null
@@ -0,0 +1,24 @@
+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());
+    }
+}