1 package org.simantics.scl.compiler.elaboration.query.compilation;
\r
3 import gnu.trove.map.hash.THashMap;
\r
4 import gnu.trove.procedure.TObjectObjectProcedure;
\r
5 import gnu.trove.set.hash.TIntHashSet;
\r
7 import java.util.ArrayList;
\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
18 public class ExpressionConstraint extends QueryConstraint {
\r
20 Expression expression;
\r
23 long forwardVariableMask;
\r
24 long backwardVariableMask;
\r
26 ArrayList<Variable> globalVariables;
\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
34 final TIntHashSet vars = new TIntHashSet();
\r
35 expression.collectVars(context.getVariableMap(), vars);
\r
37 int var1 = context.variableMap.get(variable);
\r
39 backwardVariableMask = 1L << var1;
\r
41 variables = vars.toArray();
\r
43 for(int v : variables)
\r
44 forwardVariableMask |= 1L << v;
\r
45 forwardVariableMask ^= backwardVariableMask;
\r
47 this.globalVariables = context.variables;
\r
50 private boolean canBeSolvedForwards(long boundVariables) {
\r
51 return (forwardVariableMask & boundVariables) == forwardVariableMask;
\r
54 private boolean canBeSolvedBackwards(long boundVariables) {
\r
55 return (backwardVariableMask & boundVariables) == backwardVariableMask;
\r
59 public boolean canBeSolvedFrom(long boundVariables) {
\r
60 return canBeSolvedForwards(boundVariables) || (isPattern && canBeSolvedBackwards(boundVariables));
\r
64 public double getSolutionCost(long boundVariables) {
\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
75 return Double.POSITIVE_INFINITY;
\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
84 context.let(variable, expression);
\r
86 else if(canBeSolvedBackwards(finalBoundVariables)) {
\r
87 Expression pattern = expression;
\r
89 long mask = forwardVariableMask & finalBoundVariables;
\r
90 THashMap<Variable, Expression> map = new THashMap<Variable, Expression>();
\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
99 ReplaceContext replaceContext = new ReplaceContext(new THashMap<TVar,Type>(0), map, context.getTypingContext());
\r
100 pattern = pattern.replace(replaceContext);
\r
102 context.match(pattern, new EVariable(variable), true);
\r
103 map.forEachEntry(new TObjectObjectProcedure<Variable, Expression>() {
\r
105 public boolean execute(Variable a, Expression b) {
\r
106 context.equalityCondition(Locations.NO_LOCATION, new EVariable(a), b);
\r
112 throw new InternalCompilerError(expression.location, "Error happened when tried to solve the query.");
\r