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