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