]> gerrit.simantics Code Review - simantics/platform.git/blob
590cbbd96bf75ab80fd0d7d674b7c47d9164e6d6
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \r
3 import java.util.ArrayList;\r
4 \r
5 import org.simantics.scl.compiler.common.names.Name;\r
6 import org.simantics.scl.compiler.common.precedence.Precedence;\r
7 import org.simantics.scl.compiler.constants.Constant;\r
8 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
9 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
10 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
11 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
12 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
13 import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
14 import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;\r
15 import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
16 import org.simantics.scl.compiler.environment.Environment;\r
17 import org.simantics.scl.compiler.errors.Locations;\r
18 import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
19 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
20 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
21 import org.simantics.scl.compiler.internal.interpreted.IConstant;\r
22 import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
23 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
24 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
25 import org.simantics.scl.compiler.top.ValueNotFound;\r
26 import org.simantics.scl.compiler.types.TForAll;\r
27 import org.simantics.scl.compiler.types.TMetaVar;\r
28 import org.simantics.scl.compiler.types.Type;\r
29 import org.simantics.scl.compiler.types.Types;\r
30 import org.simantics.scl.compiler.types.exceptions.MatchException;\r
31 import org.simantics.scl.compiler.types.util.MultiFunction;\r
32 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
33 \r
34 import gnu.trove.map.hash.TObjectIntHashMap;\r
35 import gnu.trove.set.hash.THashSet;\r
36 import gnu.trove.set.hash.TIntHashSet;\r
37 \r
38 public class EConstant extends Expression {\r
39     SCLValue value;\r
40     Type[] typeParameters;\r
41     \r
42     public EConstant(SCLValue value, Type ... typeParameters) {\r
43         if(SCLCompilerConfiguration.DEBUG)\r
44             if(value == null)\r
45                 throw new NullPointerException();\r
46         this.value = value;\r
47         this.typeParameters = typeParameters;\r
48     }\r
49 \r
50     public EConstant(SCLValue value) {\r
51         if(SCLCompilerConfiguration.DEBUG)\r
52             if(value == null)\r
53                 throw new NullPointerException();\r
54         this.value = value;\r
55         this.typeParameters = Type.EMPTY_ARRAY;\r
56     }\r
57 \r
58     public EConstant(long loc, SCLValue value) {\r
59         super(loc);\r
60         if(SCLCompilerConfiguration.DEBUG)\r
61             if(value == null)\r
62                 throw new NullPointerException();\r
63         this.value = value;\r
64         this.typeParameters = Type.EMPTY_ARRAY;\r
65     }\r
66     \r
67     public EConstant(long loc, SCLValue value, Type ... typeParameters) {\r
68         super(loc);\r
69         if(SCLCompilerConfiguration.DEBUG)\r
70             if(value == null)\r
71                 throw new NullPointerException();\r
72         this.value = value;\r
73         this.typeParameters = typeParameters;\r
74     }\r
75 \r
76     public void addTypeParameters(Type ... newTypeParameters) {\r
77         typeParameters = Types.concat(typeParameters, newTypeParameters);\r
78     }\r
79     \r
80     public Expression applyType(Type type) {\r
81         typeParameters = Types.concat(typeParameters, new Type[] {type});\r
82         if(getType() != null)\r
83             setType(Types.instantiate(getType(), type));\r
84         return this;\r
85     }\r
86 \r
87         public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
88         int id = allRefs.get(value);\r
89         if(id >= 0)\r
90             refs.add(id);\r
91     }\r
92         \r
93         @Override\r
94         public void collectVars(TObjectIntHashMap<Variable> allVars,\r
95                 TIntHashSet vars) {   \r
96         }\r
97 \r
98         public void toString(StringBuilder b, TypeUnparsingContext tuc) {\r
99             Name name = value.getName();\r
100             if(name.module.equals("Builtin") || name.module.equals("Prelude"))\r
101                 b.append(name.name);\r
102             else\r
103                 b.append(name);\r
104         /*for(Type type : typeParameters) {\r
105             b.append(" <");\r
106             b.append(type.toString(tuc));\r
107             b.append(">");\r
108         }*/\r
109     }\r
110 \r
111     @Override\r
112     protected void updateType() throws MatchException {\r
113         setType(Types.instantiate(value.getType(), typeParameters));\r
114     }\r
115     \r
116         @Override\r
117         public IVal toVal(Environment env, CodeWriter w) {\r
118             IVal val = value.getValue();                \r
119             if(typeParameters.length > 0) {\r
120                 val = val.createSpecialization(typeParameters);\r
121             }\r
122             return val;\r
123     }\r
124 \r
125     @Override\r
126     public void collectFreeVariables(THashSet<Variable> vars) {\r
127     }\r
128 \r
129     @Override\r
130     public Expression simplify(SimplificationContext context) {\r
131         if(value.getInlineInSimplification()) {\r
132             if(typeParameters.length > 0) {\r
133                 context.getErrorLog().log(location, \r
134                         "Inlining with type parameters not currently supported in simplification.");\r
135                 return this;\r
136             }\r
137             else\r
138                 return value.getExpression().copy().simplify(context);\r
139         }\r
140         return this;\r
141     }\r
142 \r
143     @Override\r
144     public Expression resolve(TranslationContext context) {\r
145         return this;\r
146     }\r
147     \r
148     @Override\r
149     public void getParameters(TranslationContext translationContext,\r
150             ArrayList<Expression> parameters) {\r
151     }\r
152     \r
153     public SCLValue getValue() {\r
154         return value;\r
155     }\r
156     \r
157     @Override\r
158     public Expression resolveAsPattern(TranslationContext context) {\r
159         return this;\r
160     }\r
161        \r
162     @Override\r
163     public void removeFreeVariables(THashSet<Variable> vars) {     \r
164     }\r
165 \r
166     @Override\r
167     public Expression replace(ReplaceContext context) {\r
168         Type[] newTypeParameters;\r
169         if(typeParameters.length == 0)\r
170             newTypeParameters = Type.EMPTY_ARRAY;\r
171         else {\r
172             newTypeParameters = new Type[typeParameters.length];\r
173             for(int i=0;i<newTypeParameters.length;++i)\r
174                 newTypeParameters[i] = typeParameters[i].replace(context.tvarMap);\r
175         }\r
176         return new EConstant(value, newTypeParameters);\r
177     }\r
178     \r
179     public Type[] getTypeParameters() {\r
180         return typeParameters;\r
181     }\r
182 \r
183     @Override\r
184     public LhsType getLhsType() throws NotPatternException {\r
185         return new PatternMatchingLhs();\r
186     }\r
187     \r
188     @Override\r
189     public IExpression toIExpression(ExpressionInterpretationContext target) {\r
190         Name name = value.getName();\r
191         try {\r
192             return new IConstant(target.runtimeEnvironment.getRuntimeModule(name.module).getValue(name.name));\r
193         } catch (ValueNotFound e) {\r
194             throw new UnsupportedOperationException();\r
195         }\r
196     }\r
197     \r
198     @Override\r
199     public Expression inferType(TypingContext context) {\r
200         if(context.recursiveValues != null &&\r
201                 context.recursiveValues.contains(value)) {\r
202             // Handles the case where the constant is one of the recursive definitions we are currently checking\r
203             // This kind of value is not yet generalized, i.e. it is not necessary to instantiate it.\r
204             EPlaceholder placeholder = new EPlaceholder(location, this);\r
205             placeholder.setType(value.getType());\r
206             \r
207             context.recursiveReferences.add(placeholder);\r
208             return placeholder;\r
209         }\r
210         else if(context.isInPattern()) {\r
211             /* This is little hackish code that handles the following kind of constructors:\r
212              *   data Thunk a = Thunk s (a -> s)\r
213              * in\r
214              *   match thunk with Thunk s f -> f s\r
215              * We cannot assign s with an unbound metaVar because its type depends on \r
216              * how it has been constructed. Therefore we parametrize the function with\r
217              * existential variable.\r
218              */\r
219             Type resultType = value.getType();\r
220             if(resultType instanceof TForAll) {\r
221                 ArrayList<TMetaVar> vars = new ArrayList<TMetaVar>(); \r
222                 resultType = Types.instantiate(resultType, vars);\r
223                 MultiFunction mfun = Types.matchFunction(resultType);\r
224                 resultType = mfun.returnType;\r
225                 \r
226                 for(TMetaVar var : vars) {\r
227                     if(resultType.contains(var))\r
228                         break;\r
229                     addTypeParameters(Types.var(var.getKind()));                    \r
230                 }\r
231             }\r
232             return this;\r
233         }\r
234         else\r
235             return applyPUnit(context);\r
236     }\r
237 \r
238     @Override\r
239     public Expression decorate(ExpressionDecorator decorator) {\r
240         return decorator.decorate(this);\r
241     }\r
242     \r
243     @Override\r
244     public boolean isEffectful() {\r
245         return false;\r
246     }\r
247 \r
248     @Override\r
249     public void collectEffects(THashSet<Type> effects) {\r
250     }\r
251     \r
252     @Override\r
253     public void setLocationDeep(long loc) {\r
254         if(location == Locations.NO_LOCATION)\r
255             location = loc;\r
256     }\r
257     \r
258     @Override\r
259     public void accept(ExpressionVisitor visitor) {\r
260         visitor.visit(this);\r
261     }\r
262     \r
263     @Override\r
264     public Precedence getPrecedence() {\r
265         return value.getPrecedence();\r
266     }\r
267 \r
268     @Override\r
269     public void forVariables(VariableProcedure procedure) {\r
270     }\r
271     \r
272     @Override\r
273     public boolean isPattern(int arity) {\r
274         IVal val = value.getValue();\r
275         if(!(val instanceof Constant))\r
276             return false;\r
277         Constant constant = (Constant)val;\r
278         return constant.constructorTag() >= 0 && constant.getArity() == arity;\r
279     }\r
280     \r
281     @Override\r
282     public Expression accept(ExpressionTransformer transformer) {\r
283         return transformer.transform(this);\r
284     }\r
285 \r
286 }\r