(refs #7375) Replaced collectFreeVariables method by a visitor
[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.TIntHashSet;
17
18 public abstract class QAbstractCombiner extends Query {
19     public Query[] queries;
20     
21     public QAbstractCombiner(Query[] queries) {
22         this.queries = queries;
23     }
24     
25     @Override
26     public Query resolve(TranslationContext context) {
27         Query modifiedQuery = handleExistsStatement(context);
28         if(modifiedQuery != null)
29             return modifiedQuery.resolve(context);
30             
31         for(int i=0;i<queries.length;++i)
32             queries[i] = queries[i].resolve(context);
33         return this;
34     }
35     
36     private QPreExists handleExistsStatement(TranslationContext context) {
37         if(queries.length == 0)
38             return null;
39         if(!(queries[0] instanceof QPreGuard))
40             return null;
41         Expression exp = ((QPreGuard)queries[0]).guard;
42         if(!(exp instanceof EApply))
43             return null;
44         EApply apply = (EApply)exp;
45         if(!(apply.getFunction() instanceof EVar))
46             return null;
47         if(!((EVar)apply.getFunction()).name.equals("exists"))
48             return null;
49         
50         queries = Arrays.copyOfRange(queries, 1, queries.length);
51         
52         Expression[] pars = apply.getParameters();
53         String[] variableNames = new String[pars.length];
54         for(int i=0;i<pars.length;++i) {
55             if(pars[i] instanceof EVar)
56                 variableNames[i] = ((EVar)pars[i]).name;
57             else {
58                 context.getErrorLog().log(pars[i].getLocation(), "Exists statement may only contain variables as parameters.");
59                 return null;
60             }
61         }
62         return new QPreExists(variableNames, this);
63     }
64
65     @Override
66     public void checkType(TypingContext context) {
67         for(Query query : queries)
68             query.checkType(context);
69     }
70     
71     @Override
72     public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
73         for(Query query : queries)
74             query.collectVars(allVars, vars);
75     }
76     
77     @Override
78     public void setLocationDeep(long loc) {
79         if(location == Locations.NO_LOCATION) {
80             location = loc;
81             for(Query query : queries)
82                 query.setLocationDeep(loc);
83         }
84     }
85 }