]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/types/TVarAst.java
Merge "Ensure GetElementClassRequest is not constructed without elementFactory"
[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 {
60                 TypeDescriptor tdesc;
61                 try {
62                     tdesc = Environments.getTypeDescriptor(context.getEnvironment(), name);
63                 } catch (AmbiguousNameException e) {
64                     context.getErrorLog().log(location, e.getMessage());
65                     return Types.metaVar(Kinds.STAR);
66                 }
67                 if(tdesc == null) {
68                     context.getErrorLog().log(location, "Didn't find type constructor " + name + ".");
69                     return Types.metaVar(Kinds.STAR);
70                 }
71                 if(tdesc instanceof TypeAlias) {
72                     TypeAlias alias = (TypeAlias)tdesc;
73                     if(alias.getArity() > 0) {
74                         context.getErrorLog().log(location, "The alias expects " +
75                                 alias.getArity() + " parameters, but none are given.");
76                         return Types.metaVar(Kinds.metaVar());
77                     }
78                     return alias.body;
79                 }
80                 con = tdesc.name;
81             }
82         }
83         
84         Kind providedKind = context.getKind(con);
85         context.unify(location, providedKind, expectedKind);
86         return con;
87     }
88     
89     @Override
90     public Type toType(TypeElaborationContext context) {
91         char c = name.charAt(0);
92         Type con;
93         block: {
94             if(c == '(') {
95                 for(int i=1;i<name.length()-1;++i)
96                     if(name.charAt(i) != ',') {
97                         con = context.resolveTypeConstructor(name.substring(1, name.length()-1));
98                         if(con == null) {
99                             System.err.println("Didn't find type constructor " + name + ".");
100                             return Types.metaVar(Kinds.STAR);
101                         }
102                         break block;
103                     }
104                 con = Types.con(Types.BUILTIN, name);
105             }
106             else if(Character.isLowerCase(c))
107                 return context.resolveTypeVariable(name);
108             else {                
109                 con = context.resolveTypeConstructor(name);
110                 if(con == null) {
111                     System.err.println("Didn't find type constructor " + name + ".");
112                     return Types.metaVar(Kinds.STAR);
113                 }
114             }
115         }
116         
117         return con;
118     }
119     
120     /**
121      * Translate this variable reference to an effect Type. Lower initial names are treated as
122      * type meta-variables. Capitalized names are resolved as effect name constants.
123      * 
124      * Error messages about unresolved or ambiguous effect names are logged, with a new meta-variable
125      * as the return value.
126      */
127     @Override
128     public Type toEffect(TypeTranslationContext context) {
129         char c = name.charAt(0);
130         if(Character.isLowerCase(c))
131             return context.resolveTypeVariable(location, name, Kinds.EFFECT);
132         else {
133             TCon con;
134             try {
135                 con = Environments.getEffectConstructorName(context.getEnvironment(), name);
136             } catch (AmbiguousNameException e) {
137                 context.getErrorLog().log(location, e.getMessage());
138                 return Types.metaVar(Kinds.EFFECT);
139             }
140             if(con == null) {
141                 context.getErrorLog().log(location, "Didn't find effect constructor " + name + ".");
142                 return Types.metaVar(Kinds.EFFECT);
143             }
144             return con;
145         }
146     }
147     
148     @Override
149     public Type toEffect(TypeElaborationContext context) {
150         char c = name.charAt(0);
151         if(Character.isLowerCase(c))
152             return context.resolveTypeVariable(name);
153         else {
154             Type con = context.resolveTypeConstructor(name);
155             if(con == null) {
156                 System.err.println("Didn't find effect constructor " + name + ".");
157                 return Types.metaVar(Kinds.EFFECT);
158             }
159             return con;
160         }
161     }
162
163     @Override
164     public int getPrecedence() {
165         return 0;
166     }
167
168     @Override
169     public void collectReferences(TObjectIntHashMap<String> typeNameMap,
170             TIntHashSet set) {
171         if(typeNameMap.containsKey(name))
172             set.add(typeNameMap.get(name));
173     }
174 }