1 package org.simantics.scl.compiler.elaboration.query;
3 import java.util.ArrayList;
4 import java.util.Collection;
7 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
8 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
9 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;
10 import org.simantics.scl.compiler.elaboration.expressions.Expression;
11 import org.simantics.scl.compiler.elaboration.expressions.QueryTransformer;
12 import org.simantics.scl.compiler.elaboration.expressions.Variable;
13 import org.simantics.scl.compiler.elaboration.java.Builtins;
14 import org.simantics.scl.compiler.elaboration.query.compilation.ConstraintCollectionContext;
15 import org.simantics.scl.compiler.elaboration.query.compilation.DerivateException;
16 import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
17 import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;
18 import org.simantics.scl.compiler.elaboration.relations.LocalRelation;
19 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
20 import org.simantics.scl.compiler.types.Types;
22 import gnu.trove.map.hash.THashMap;
23 import gnu.trove.map.hash.TIntObjectHashMap;
26 public class QConjunction extends QAbstractCombiner {
28 public QConjunction(Query ... queries) {
32 public QConjunction(Collection<Query> queries) {
33 this(queries.toArray(new Query[queries.size()]));
36 public Expression generateEnforce(EnforcingContext context) {
37 Expression result = new EConstant(Builtins.TUPLE_CONSTRUCTORS[0]);
38 for(int i=queries.length-1;i>=0;--i)
39 result = new ESimpleLet(
40 new Variable("_", Types.tupleConstructor(0)),
41 queries[i].generateEnforce(context),
48 public void collectConstraints(ConstraintCollectionContext context) throws UnsolvableQueryException {
49 for(Query query : queries)
50 query.collectConstraints(context);
53 private static class DerEntry {
57 public DerEntry(Query base, Diff[] diffs) {
64 public Diff[] derivate(THashMap<LocalRelation, Diffable> diffables) throws DerivateException {
65 ArrayList<Query> cons = new ArrayList<Query>(queries.length);
66 ArrayList<DerEntry> ders = new ArrayList<DerEntry>(queries.length);
67 for(Query query : queries) {
68 Diff[] diffs = query.derivate(diffables);
72 ders.add(new DerEntry(query, diffs));
77 Query base = new QConjunction(cons.toArray(new Query[cons.size()]));
78 Diff[] diffs = NO_DIFF;
79 for(DerEntry entry : ders) {
80 ArrayList<Diff> newDiffs = new ArrayList<Diff>();
81 for(Diff diff : diffs)
82 newDiffs.add(new Diff(diff.id, new QConjunction(diff.query, entry.base)));
83 for(Diff newDiff : entry.diffs) {
84 newDiffs.add(new Diff(newDiff.id, new QConjunction(base, newDiff.query)));
85 for(Diff diff : diffs)
86 if(diff.id == newDiff.id)
87 newDiffs.add(new Diff(diff.id, new QConjunction(diff.query, newDiff.query)));
89 base = new QConjunction(base, entry.base);
90 diffs = newDiffs.toArray(new Diff[newDiffs.size()]);
96 public Query removeRelations(Set<SCLRelation> relations) {
97 for(int i=0;i<queries.length;++i) {
98 Query query = queries[i];
99 Query newQuery = query.removeRelations(relations);
100 if(query != newQuery) {
101 if(newQuery == EMPTY_QUERY)
103 Query[] newQueries = new Query[queries.length];
105 System.arraycopy(queries, 0, newQueries, 0, i-1);
106 newQueries[i] = newQuery;
107 for(++i;i<queries.length;++i) {
109 newQuery = query.removeRelations(relations);
110 if(newQuery == EMPTY_QUERY)
112 newQueries[i] = query;
114 return new QConjunction(newQueries);
121 public Query replace(ReplaceContext context) {
122 Query[] newQueries = new Query[queries.length];
123 for(int i=0;i<queries.length;++i)
124 newQueries[i] = queries[i].replace(context);
125 return new QConjunction(newQueries);
129 public void accept(QueryVisitor visitor) {
134 public void splitToPhases(TIntObjectHashMap<ArrayList<Query>> result) {
135 for(Query query : queries)
136 query.splitToPhases(result);
140 public Query accept(QueryTransformer transformer) {
141 return transformer.transform(this);