1 package org.simantics.scl.compiler.elaboration.query;
3 import java.util.ArrayList;
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
8 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
9 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
10 import org.simantics.scl.compiler.elaboration.expressions.EError;
11 import org.simantics.scl.compiler.elaboration.expressions.Expression;
12 import org.simantics.scl.compiler.elaboration.expressions.QueryTransformer;
13 import org.simantics.scl.compiler.elaboration.expressions.Variable;
14 import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
15 import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
16 import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectRefsVisitor;
17 import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectVarsVisitor;
18 import org.simantics.scl.compiler.elaboration.expressions.visitors.ForVariablesUsesVisitor;
19 import org.simantics.scl.compiler.elaboration.expressions.visitors.StandardExpressionVisitor;
20 import org.simantics.scl.compiler.elaboration.query.compilation.ConstraintCollectionContext;
21 import org.simantics.scl.compiler.elaboration.query.compilation.DerivateException;
22 import org.simantics.scl.compiler.elaboration.query.compilation.DynamicProgrammingOrdering;
23 import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
24 import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
25 import org.simantics.scl.compiler.elaboration.query.compilation.QueryConstraint;
26 import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;
27 import org.simantics.scl.compiler.elaboration.relations.CompositeRelation;
28 import org.simantics.scl.compiler.elaboration.relations.LocalRelation;
29 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
30 import org.simantics.scl.compiler.internal.parsing.Symbol;
32 import gnu.trove.map.hash.THashMap;
33 import gnu.trove.map.hash.TIntObjectHashMap;
34 import gnu.trove.map.hash.TObjectIntHashMap;
35 import gnu.trove.set.hash.TIntHashSet;
37 public abstract class Query extends Symbol {
38 public static final Query[] EMPTY_ARRAY = new Query[0];
40 public abstract void checkType(TypingContext context);
42 public Query resolve(TranslationContext context) {
43 throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support resolve.");
46 public Expression generateEnforce(EnforcingContext context) {
47 context.getErrorLog().log(location, getClass().getSimpleName() + " does not support enforcing.");
48 return new EError(location);
51 public abstract void collectConstraints(ConstraintCollectionContext context) throws UnsolvableQueryException;
53 protected QueryConstraint[] getOrderedConstraints(QueryCompilationContext context) throws UnsolvableQueryException {
54 ConstraintCollectionContext collectionContext = new ConstraintCollectionContext(context);
55 collectConstraints(collectionContext);
56 QueryConstraint[] constraints = collectionContext.getConstraints();
57 DynamicProgrammingOrdering.order(collectionContext, constraints, 0L);
61 protected void applyConstraints(QueryCompilationContext context, QueryConstraint[] constraints) {
62 for(int i=constraints.length-1;i>=0;--i)
63 constraints[i].generateAndUpdateCost(context);
66 public void generate(QueryCompilationContext context) throws UnsolvableQueryException {
67 applyConstraints(context, getOrderedConstraints(context));
70 protected static final TIntObjectHashMap<ArrayList<Query>> NO_DERIVATE = new TIntObjectHashMap<ArrayList<Query>>();
72 public static class Diffable {
75 public Variable[] parameters;
76 public Diffable(int id, SCLRelation relation, Variable[] parameters) {
78 this.relation = relation;
79 this.parameters = parameters;
83 public static class Diff {
87 public Diff(int id, Query query) {
93 public static final Diff[] NO_DIFF = new Diff[0];
95 public Diff[] derivate(THashMap<LocalRelation, Diffable> diffables) throws DerivateException {
96 throw new DerivateException(location);
99 public static final QDisjunction EMPTY_QUERY = new QDisjunction();
101 public Query removeRelations(Set<SCLRelation> relations) {
102 throw new UnsupportedOperationException();
105 public Query copy() {
106 return replace(new ReplaceContext(null));
109 public Query copy(TypingContext context) {
110 return replace(new ReplaceContext(context));
113 public abstract Query replace(ReplaceContext context);
115 public abstract void setLocationDeep(long loc);
117 public abstract void accept(QueryVisitor visitor);
119 public void collectRelationRefs(
120 final TObjectIntHashMap<SCLRelation> allRefs, final TIntHashSet refs) {
121 accept(new StandardExpressionVisitor() {
123 public void visit(QAtom query) {
124 visit(query.relation);
126 private void visit(SCLRelation relation) {
127 int id = allRefs.get(relation);
130 else if(relation instanceof CompositeRelation)
131 for(SCLRelation subrelation : ((CompositeRelation)relation).getSubrelations())
137 public TIntObjectHashMap<ArrayList<Query>> splitToPhases() {
138 TIntObjectHashMap<ArrayList<Query>> result = new TIntObjectHashMap<ArrayList<Query>>(2);
139 splitToPhases(result);
143 public void splitToPhases(TIntObjectHashMap<ArrayList<Query>> result) {
144 throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support splitToPhases.");
148 public String toString() {
149 StringBuilder b = new StringBuilder();
150 ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
155 public abstract Query accept(QueryTransformer transformer);
157 public void forVariables(VariableProcedure procedure) {
158 accept(new ForVariablesUsesVisitor(procedure));
160 public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
161 accept(new CollectRefsVisitor(allRefs, refs));
164 public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
165 accept(new CollectVarsVisitor(allVars, vars));