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