]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/types/TVarAst.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / parsing / types / TVarAst.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/types/TVarAst.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/types/TVarAst.java
new file mode 100644 (file)
index 0000000..9633d86
--- /dev/null
@@ -0,0 +1,177 @@
+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));
+    }
+}