]> gerrit.simantics Code Review - simantics/platform.git/blob
0c7c21e3d0b8929e141bb702ce81c7ddd97efab8
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.query.compilation;\r
2 \r
3 import gnu.trove.map.hash.THashMap;\r
4 import gnu.trove.procedure.TObjectObjectProcedure;\r
5 import gnu.trove.set.hash.TIntHashSet;\r
6 \r
7 import java.util.ArrayList;\r
8 \r
9 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
10 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
11 import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
12 import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
13 import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
14 import org.simantics.scl.compiler.errors.Locations;\r
15 import org.simantics.scl.compiler.types.TVar;\r
16 import org.simantics.scl.compiler.types.Type;\r
17 \r
18 public class ExpressionConstraint extends QueryConstraint {\r
19     Variable variable;\r
20     Expression expression;\r
21     boolean isPattern;\r
22     \r
23     long forwardVariableMask;\r
24     long backwardVariableMask;\r
25     \r
26     ArrayList<Variable> globalVariables;\r
27     \r
28     public ExpressionConstraint(final ConstraintCollectionContext context, Variable variable,\r
29             Expression expression, boolean isPattern) {\r
30         this.variable = variable;\r
31         this.expression = expression;\r
32         this.isPattern = isPattern;\r
33         \r
34         final TIntHashSet vars = new TIntHashSet();\r
35         expression.collectVars(context.getVariableMap(), vars);\r
36         \r
37         int var1 = context.variableMap.get(variable);\r
38         vars.add(var1);\r
39         backwardVariableMask = 1L << var1;\r
40         \r
41         variables = vars.toArray();\r
42         \r
43         for(int v : variables)\r
44             forwardVariableMask |= 1L << v;\r
45         forwardVariableMask ^= backwardVariableMask;\r
46         \r
47         this.globalVariables = context.variables;\r
48     }\r
49     \r
50     private boolean canBeSolvedForwards(long boundVariables) {\r
51         return (forwardVariableMask & boundVariables) == forwardVariableMask;\r
52     }\r
53     \r
54     private boolean canBeSolvedBackwards(long boundVariables) {\r
55         return (backwardVariableMask & boundVariables) == backwardVariableMask;\r
56     }\r
57     \r
58     @Override\r
59     public boolean canBeSolvedFrom(long boundVariables) {\r
60         return canBeSolvedForwards(boundVariables) || (isPattern && canBeSolvedBackwards(boundVariables));  \r
61     }\r
62     \r
63     @Override\r
64     public double getSolutionCost(long boundVariables) {\r
65         return 1.0;\r
66     }\r
67     \r
68     @Override\r
69     public double getSolutionBranching(long boundVariables) {\r
70         if(canBeSolvedForwards(boundVariables))\r
71             return (boundVariables&1)==0 ? 1.0 : 0.95;\r
72         else if(isPattern && canBeSolvedBackwards(boundVariables))\r
73             return 0.95;\r
74         else\r
75             return Double.POSITIVE_INFINITY;\r
76     }\r
77     \r
78     @Override\r
79     public void generate(final QueryCompilationContext context) {\r
80         if(canBeSolvedForwards(finalBoundVariables)) {\r
81             if(canBeSolvedBackwards(finalBoundVariables))\r
82                 context.equalityCondition(expression.location, new EVariable(variable), expression);\r
83             else\r
84                 context.let(variable, expression);\r
85         }\r
86         else if(canBeSolvedBackwards(finalBoundVariables)) {\r
87             Expression pattern = expression;\r
88             \r
89             long mask = forwardVariableMask & finalBoundVariables;\r
90             THashMap<Variable, Expression> map = new THashMap<Variable, Expression>();\r
91             if(mask != 0L) {\r
92                 for(int variableId : variables)\r
93                     if( ((mask >> variableId)&1L) == 1L ) {\r
94                         Variable original = globalVariables.get(variableId);\r
95                         Variable newVariable = new Variable(original.getName() + "_temp", original.getType());\r
96                         map.put(original, new EVariable(newVariable));\r
97                     }\r
98                 \r
99                 ReplaceContext replaceContext = new ReplaceContext(new THashMap<TVar,Type>(0), map, context.getTypingContext());\r
100                 pattern = pattern.replace(replaceContext);\r
101             }\r
102             context.match(pattern, new EVariable(variable), true);\r
103             map.forEachEntry(new TObjectObjectProcedure<Variable, Expression>() {\r
104                 @Override\r
105                 public boolean execute(Variable a, Expression b) {\r
106                     context.equalityCondition(Locations.NO_LOCATION, new EVariable(a), b);\r
107                     return true;\r
108                 }\r
109             });\r
110         }\r
111         else\r
112             throw new InternalCompilerError(expression.location, "Error happened when tried to solve the query.");\r
113     }\r
114 }\r