]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EWhen.java
e7907f3578e62599536bfd89687bebc78e55ab4c
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EWhen.java
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \r
3 import gnu.trove.map.hash.TObjectIntHashMap;\r
4 import gnu.trove.set.hash.THashSet;\r
5 import gnu.trove.set.hash.TIntHashSet;\r
6 \r
7 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\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.query.QExists;\r
13 import org.simantics.scl.compiler.elaboration.query.Query;\r
14 import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;\r
15 import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationMode;\r
16 import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;\r
17 import org.simantics.scl.compiler.errors.Locations;\r
18 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
19 import org.simantics.scl.compiler.types.Type;\r
20 import org.simantics.scl.compiler.types.Types;\r
21 import org.simantics.scl.compiler.types.exceptions.MatchException;\r
22 import org.simantics.scl.compiler.types.exceptions.UnificationException;\r
23 import org.simantics.scl.compiler.types.kinds.Kinds;\r
24 \r
25 public class EWhen extends SimplifiableExpression {\r
26 \r
27     public Query query;\r
28     public Expression action;\r
29     Variable[] variables;\r
30     \r
31     public EWhen(Query query, Expression action) {\r
32         this.query = query;\r
33         this.action = action;\r
34     }\r
35     \r
36     public EWhen(long location, Query query, Expression action, Variable[] variables) {\r
37         if(variables == null)\r
38             throw new NullPointerException();\r
39         if(location == Locations.NO_LOCATION)\r
40             new Exception().printStackTrace();\r
41         this.location = location;\r
42         this.query = query;\r
43         this.action = action;\r
44         this.variables = variables;\r
45     }\r
46 \r
47     @Override\r
48     public void collectRefs(TObjectIntHashMap<Object> allRefs,\r
49             TIntHashSet refs) {\r
50         query.collectRefs(allRefs, refs);\r
51         action.collectRefs(allRefs, refs);\r
52     }\r
53 \r
54     @Override\r
55     public void collectVars(TObjectIntHashMap<Variable> allVars,\r
56             TIntHashSet vars) {\r
57         query.collectVars(allVars, vars);\r
58         action.collectVars(allVars, vars);\r
59     }\r
60     \r
61     @Override\r
62     public void collectEffects(THashSet<Type> effects) {\r
63         throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support collectEffects.");\r
64     }\r
65 \r
66     @Override\r
67     protected void updateType() throws MatchException {\r
68         setType(Types.UNIT);\r
69     }\r
70     \r
71     @Override\r
72     public Expression checkBasicType(TypingContext context, Type requiredType) {\r
73         try {\r
74             Types.unify(requiredType, Types.UNIT);\r
75         } catch (UnificationException e) {\r
76             context.typeError(location, requiredType, Types.UNIT);\r
77             return this;\r
78         }\r
79         for(Variable variable : variables)\r
80             variable.setType(Types.metaVar(Kinds.STAR));\r
81         query.checkType(context);\r
82         action.checkType(context, Types.UNIT);\r
83         \r
84         // Compile query\r
85         return compile(context);\r
86     }\r
87     \r
88     public Expression compile(TypingContext context) {\r
89         try {\r
90             QueryCompilationContext queryCompilationContext =\r
91                     new QueryCompilationContext(context, QueryCompilationMode.ITERATE, null, action);\r
92             new QExists(variables, query).generate(queryCompilationContext);\r
93             return queryCompilationContext.getContinuation();\r
94         } catch(UnsolvableQueryException e) {\r
95             context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" +  e.getMessage());\r
96             return new EError(getLocation());\r
97         }\r
98     }\r
99 \r
100     @Override\r
101     public void collectFreeVariables(THashSet<Variable> vars) {\r
102         action.collectFreeVariables(vars);\r
103         query.collectFreeVariables(vars);\r
104         for(Variable var : variables)\r
105             vars.remove(var);\r
106     }\r
107 \r
108     @Override\r
109     public Expression resolve(TranslationContext context) {\r
110         context.pushExistentialFrame();\r
111         query = query.resolve(context);\r
112         action = action.resolve(context);\r
113         variables = context.popExistentialFrame();\r
114         return this;\r
115     }\r
116 \r
117     @Override\r
118     public Expression decorate(ExpressionDecorator decorator) {     \r
119         return decorator.decorate(this);\r
120     }\r
121     \r
122     @Override\r
123     public Expression replace(ReplaceContext context) {\r
124         Variable[] newVariables = new Variable[variables.length];\r
125         for(int i=0;i<variables.length;++i) {\r
126             Variable variable = variables[i];\r
127             Variable newVariable = new Variable(variable.name, variable.getType());\r
128             newVariables[i] = newVariable;\r
129             context.varMap.put(variable, new EVariable(newVariable));\r
130         }\r
131         EWhen result = new EWhen(location, query.replace(context), action.replace(context), newVariables);\r
132         for(int i=0;i<variables.length;++i)\r
133             context.varMap.remove(variables[i]);\r
134         return result;\r
135     }\r
136 \r
137     @Override\r
138     public void setLocationDeep(long loc) {\r
139         if(location == Locations.NO_LOCATION) {\r
140             location = loc;\r
141             query.setLocationDeep(loc);\r
142             action.setLocationDeep(loc);\r
143         }\r
144     }\r
145     \r
146     @Override\r
147     public void accept(ExpressionVisitor visitor) {\r
148         visitor.visit(this);\r
149     }\r
150     \r
151     public Query getQuery() {\r
152         return query;\r
153     }\r
154     \r
155     public Expression getAction() {\r
156         return action;\r
157     }\r
158 \r
159     @Override\r
160     public void forVariables(VariableProcedure procedure) {\r
161         query.forVariables(procedure);\r
162         action.forVariables(procedure);\r
163     }\r
164     \r
165     @Override\r
166     public Expression simplify(SimplificationContext context) {\r
167         throw new UnsupportedOperationException();\r
168     }\r
169     \r
170     @Override\r
171     public Expression accept(ExpressionTransformer transformer) {\r
172         return transformer.transform(this);\r
173     }\r
174 \r
175 }\r