--- /dev/null
+package org.simantics.scl.compiler.elaboration.query;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.EError;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.QueryTransformer;
+import org.simantics.scl.compiler.elaboration.expressions.StandardExpressionVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.query.compilation.ConstraintCollectionContext;
+import org.simantics.scl.compiler.elaboration.query.compilation.DerivateException;
+import org.simantics.scl.compiler.elaboration.query.compilation.DynamicProgrammingOrdering;
+import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryConstraint;
+import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;
+import org.simantics.scl.compiler.elaboration.relations.CompositeRelation;
+import org.simantics.scl.compiler.elaboration.relations.LocalRelation;
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+
+public abstract class Query extends Symbol {
+ public static final Query[] EMPTY_ARRAY = new Query[0];
+
+ public abstract void collectFreeVariables(THashSet<Variable> vars);
+ public abstract void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs);
+ public abstract void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars);
+ public abstract void checkType(TypingContext context);
+
+ public Query resolve(TranslationContext context) {
+ throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support resolve.");
+ }
+
+ public Expression generateEnforce(EnforcingContext context) {
+ context.getErrorLog().log(location, getClass().getSimpleName() + " does not support enforcing.");
+ return new EError(location);
+ }
+
+ public abstract void collectConstraints(ConstraintCollectionContext context) throws UnsolvableQueryException;
+
+ protected QueryConstraint[] getOrderedConstraints(QueryCompilationContext context) throws UnsolvableQueryException {
+ ConstraintCollectionContext collectionContext = new ConstraintCollectionContext(context);
+ collectConstraints(collectionContext);
+ QueryConstraint[] constraints = collectionContext.getConstraints();
+ DynamicProgrammingOrdering.order(collectionContext, constraints, 0L);
+ return constraints;
+ }
+
+ protected void applyConstraints(QueryCompilationContext context, QueryConstraint[] constraints) {
+ for(int i=constraints.length-1;i>=0;--i)
+ constraints[i].generateAndUpdateCost(context);
+ }
+
+ public void generate(QueryCompilationContext context) throws UnsolvableQueryException {
+ applyConstraints(context, getOrderedConstraints(context));
+ }
+
+ protected static final TIntObjectHashMap<ArrayList<Query>> NO_DERIVATE = new TIntObjectHashMap<ArrayList<Query>>();
+
+ public static class Diffable {
+ public int id;
+ SCLRelation relation;
+ public Variable[] parameters;
+ public Diffable(int id, SCLRelation relation, Variable[] parameters) {
+ this.id = id;
+ this.relation = relation;
+ this.parameters = parameters;
+ }
+ }
+
+ public static class Diff {
+ public int id;
+ public Query query;
+
+ public Diff(int id, Query query) {
+ this.id = id;
+ this.query = query;
+ }
+ }
+
+ public static final Diff[] NO_DIFF = new Diff[0];
+
+ public Diff[] derivate(THashMap<LocalRelation, Diffable> diffables) throws DerivateException {
+ throw new DerivateException(location);
+ }
+
+ public static final QDisjunction EMPTY_QUERY = new QDisjunction();
+
+ public Query removeRelations(Set<SCLRelation> relations) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Query copy() {
+ return replace(new ReplaceContext(null));
+ }
+
+ public Query copy(TypingContext context) {
+ return replace(new ReplaceContext(context));
+ }
+
+ public abstract Query replace(ReplaceContext context);
+
+ public abstract void setLocationDeep(long loc);
+
+ public abstract void accept(QueryVisitor visitor);
+
+ public void collectRelationRefs(
+ final TObjectIntHashMap<SCLRelation> allRefs, final TIntHashSet refs) {
+ accept(new StandardExpressionVisitor() {
+ @Override
+ public void visit(QAtom query) {
+ visit(query.relation);
+ }
+ private void visit(SCLRelation relation) {
+ int id = allRefs.get(relation);
+ if(id >= 0)
+ refs.add(id);
+ else if(relation instanceof CompositeRelation)
+ for(SCLRelation subrelation : ((CompositeRelation)relation).getSubrelations())
+ visit(subrelation);
+ }
+ });
+ }
+
+ public abstract void forVariables(VariableProcedure procedure);
+
+ public TIntObjectHashMap<ArrayList<Query>> splitToPhases() {
+ TIntObjectHashMap<ArrayList<Query>> result = new TIntObjectHashMap<ArrayList<Query>>(2);
+ splitToPhases(result);
+ return result;
+ }
+
+ public void splitToPhases(TIntObjectHashMap<ArrayList<Query>> result) {
+ throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support splitToPhases.");
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
+ accept(visitor);
+ return b.toString();
+ }
+
+ public abstract Query accept(QueryTransformer transformer);
+}