]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/QAbstractCombiner.java
52a59585f1b88b375b8db78f499f290937f7301e
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / query / QAbstractCombiner.java
1 package org.simantics.scl.compiler.elaboration.query;
2
3 import java.util.Arrays;
4
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
7 import org.simantics.scl.compiler.elaboration.expressions.EApply;
8 import org.simantics.scl.compiler.elaboration.expressions.EVar;
9 import org.simantics.scl.compiler.elaboration.expressions.Expression;
10 import org.simantics.scl.compiler.elaboration.expressions.Variable;
11 import org.simantics.scl.compiler.elaboration.query.pre.QPreExists;
12 import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
13 import org.simantics.scl.compiler.errors.Locations;
14
15 import gnu.trove.map.hash.TObjectIntHashMap;
16 import gnu.trove.set.hash.THashSet;
17 import gnu.trove.set.hash.TIntHashSet;
18
19 public abstract class QAbstractCombiner extends Query {
20     public Query[] queries;
21     
22     public QAbstractCombiner(Query[] queries) {
23         this.queries = queries;
24     }
25
26     public void collectFreeVariables(THashSet<Variable> vars) {
27         for(Query query : queries)
28             query.collectFreeVariables(vars);
29     }
30     
31     @Override
32     public Query resolve(TranslationContext context) {
33         Query modifiedQuery = handleExistsStatement(context);
34         if(modifiedQuery != null)
35             return modifiedQuery.resolve(context);
36             
37         for(int i=0;i<queries.length;++i)
38             queries[i] = queries[i].resolve(context);
39         return this;
40     }
41     
42     private QPreExists handleExistsStatement(TranslationContext context) {
43         if(queries.length == 0)
44             return null;
45         if(!(queries[0] instanceof QPreGuard))
46             return null;
47         Expression exp = ((QPreGuard)queries[0]).guard;
48         if(!(exp instanceof EApply))
49             return null;
50         EApply apply = (EApply)exp;
51         if(!(apply.getFunction() instanceof EVar))
52             return null;
53         if(!((EVar)apply.getFunction()).name.equals("exists"))
54             return null;
55         
56         queries = Arrays.copyOfRange(queries, 1, queries.length);
57         
58         Expression[] pars = apply.getParameters();
59         String[] variableNames = new String[pars.length];
60         for(int i=0;i<pars.length;++i) {
61             if(pars[i] instanceof EVar)
62                 variableNames[i] = ((EVar)pars[i]).name;
63             else {
64                 context.getErrorLog().log(pars[i].getLocation(), "Exists statement may only contain variables as parameters.");
65                 return null;
66             }
67         }
68         return new QPreExists(variableNames, this);
69     }
70
71     @Override
72     public void checkType(TypingContext context) {
73         for(Query query : queries)
74             query.checkType(context);
75     }
76     
77     @Override
78     public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
79         for(Query query : queries)
80             query.collectRefs(allRefs, refs);
81     }
82     
83     @Override
84     public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
85         for(Query query : queries)
86             query.collectVars(allVars, vars);
87     }
88     
89     @Override
90     public void setLocationDeep(long loc) {
91         if(location == Locations.NO_LOCATION) {
92             location = loc;
93             for(Query query : queries)
94                 query.setLocationDeep(loc);
95         }
96     }
97 }