]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/types/TVarAst.java
(refs #7588) Support for existential type variables with syntax ?v
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / parsing / types / TVarAst.java
1 package org.simantics.scl.compiler.internal.parsing.types;
2
3 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
4 import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
5 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
6 import org.simantics.scl.compiler.environment.AmbiguousNameException;
7 import org.simantics.scl.compiler.environment.Environments;
8 import org.simantics.scl.compiler.internal.types.TypeElaborationContext;
9 import org.simantics.scl.compiler.types.TCon;
10 import org.simantics.scl.compiler.types.Type;
11 import org.simantics.scl.compiler.types.Types;
12 import org.simantics.scl.compiler.types.kinds.Kind;
13 import org.simantics.scl.compiler.types.kinds.Kinds;
14
15 import gnu.trove.map.hash.TObjectIntHashMap;
16 import gnu.trove.set.hash.TIntHashSet;
17
18
19 /**
20  * This class represents an abstract syntax tree node for a type variable.
21  * The only property of a type variable is its name.
22  */
23 public class TVarAst extends TypeAst {    
24     public final String name;
25     
26     public TVarAst(String name) {
27         this.name = name;
28     }
29
30     @Override
31     public void toString(StringBuilder b) {
32         b.append(name);
33     }
34
35     @Override
36     public Type toType(TypeTranslationContext context, Kind expectedKind) {
37         char c = name.charAt(0);
38         TCon con;
39         block: {
40             if(c == '(') {
41                 for(int i=1;i<name.length()-1;++i)
42                     if(name.charAt(i) != ',') {
43                         try {
44                             con = Environments.getTypeDescriptorName(context.getEnvironment(), name.substring(1, name.length()-1));
45                         } catch(AmbiguousNameException e) {
46                             context.getErrorLog().log(location, e.getMessage());
47                             return Types.metaVar(Kinds.STAR);
48                         }
49                         if(con == null) {
50                             context.getErrorLog().log(location, "Didn't find type constructor " + name + ".");
51                             return Types.metaVar(Kinds.STAR);
52                         }
53                         break block;
54                     }
55                 con = Types.con(Types.BUILTIN, name);
56             }
57             else if(Character.isLowerCase(c))
58                 return context.resolveTypeVariable(location, name, expectedKind);
59             else if(c == '?')
60                 return context.resolveExistential(location, name, expectedKind);
61             else {
62                 TypeDescriptor tdesc;
63                 try {
64                     tdesc = Environments.getTypeDescriptor(context.getEnvironment(), name);
65                 } catch (AmbiguousNameException e) {
66                     context.getErrorLog().log(location, e.getMessage());
67                     return Types.metaVar(Kinds.STAR);
68                 }
69                 if(tdesc == null) {
70                     context.getErrorLog().log(location, "Didn't find type constructor " + name + ".");
71                     return Types.metaVar(Kinds.STAR);
72                 }
73                 if(tdesc instanceof TypeAlias) {
74                     TypeAlias alias = (TypeAlias)tdesc;
75                     if(alias.getArity() > 0) {
76                         context.getErrorLog().log(location, "The alias expects " +
77                                 alias.getArity() + " parameters, but none are given.");
78                         return Types.metaVar(Kinds.metaVar());
79                     }
80                     return alias.body;
81                 }
82                 con = tdesc.name;
83             }
84         }
85         
86         Kind providedKind = context.getKind(con);
87         context.unify(location, providedKind, expectedKind);
88         return con;
89     }
90     
91     @Override
92     public Type toType(TypeElaborationContext context) {
93         char c = name.charAt(0);
94         Type con;
95         block: {
96             if(c == '(') {
97                 for(int i=1;i<name.length()-1;++i)
98                     if(name.charAt(i) != ',') {
99                         con = context.resolveTypeConstructor(name.substring(1, name.length()-1));
100                         if(con == null) {
101                             System.err.println("Didn't find type constructor " + name + ".");
102                             return Types.metaVar(Kinds.STAR);
103                         }
104                         break block;
105                     }
106                 con = Types.con(Types.BUILTIN, name);
107             }
108             else if(Character.isLowerCase(c))
109                 return context.resolveTypeVariable(name);
110             else if(c == '?')
111                 return context.resolveExistential(name);
112             else {                
113                 con = context.resolveTypeConstructor(name);
114                 if(con == null) {
115                     System.err.println("Didn't find type constructor " + name + ".");
116                     return Types.metaVar(Kinds.STAR);
117                 }
118             }
119         }
120         
121         return con;
122     }
123     
124     /**
125      * Translate this variable reference to an effect Type. Lower initial names are treated as
126      * type meta-variables. Capitalized names are resolved as effect name constants.
127      * 
128      * Error messages about unresolved or ambiguous effect names are logged, with a new meta-variable
129      * as the return value.
130      */
131     @Override
132     public Type toEffect(TypeTranslationContext context) {
133         char c = name.charAt(0);
134         if(Character.isLowerCase(c))
135             return context.resolveTypeVariable(location, name, Kinds.EFFECT);
136         else {
137             TCon con;
138             try {
139                 con = Environments.getEffectConstructorName(context.getEnvironment(), name);
140             } catch (AmbiguousNameException e) {
141                 context.getErrorLog().log(location, e.getMessage());
142                 return Types.metaVar(Kinds.EFFECT);
143             }
144             if(con == null) {
145                 context.getErrorLog().log(location, "Didn't find effect constructor " + name + ".");
146                 return Types.metaVar(Kinds.EFFECT);
147             }
148             return con;
149         }
150     }
151     
152     @Override
153     public Type toEffect(TypeElaborationContext context) {
154         char c = name.charAt(0);
155         if(Character.isLowerCase(c))
156             return context.resolveTypeVariable(name);
157         else if(c == '?')
158             return context.resolveExistential(name);
159         else {
160             Type con = context.resolveTypeConstructor(name);
161             if(con == null) {
162                 System.err.println("Didn't find effect constructor " + name + ".");
163                 return Types.metaVar(Kinds.EFFECT);
164             }
165             return con;
166         }
167     }
168
169     @Override
170     public int getPrecedence() {
171         return 0;
172     }
173
174     @Override
175     public void collectReferences(TObjectIntHashMap<String> typeNameMap,
176             TIntHashSet set) {
177         if(typeNameMap.containsKey(name))
178             set.add(typeNameMap.get(name));
179     }
180 }