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