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