]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/pre/QPreGuard.java
287f89919236559366bc50017d207974c07122df
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / query / pre / QPreGuard.java
1 package org.simantics.scl.compiler.elaboration.query.pre;
2
3 import java.util.Arrays;
4
5 import org.simantics.scl.compiler.constants.BooleanConstant;
6 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
7 import org.simantics.scl.compiler.elaboration.expressions.EApply;
8 import org.simantics.scl.compiler.elaboration.expressions.EEntityTypeAnnotation;
9 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
10 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;
11 import org.simantics.scl.compiler.elaboration.expressions.EVar;
12 import org.simantics.scl.compiler.elaboration.expressions.Expression;
13 import org.simantics.scl.compiler.elaboration.expressions.QueryTransformer;
14 import org.simantics.scl.compiler.elaboration.expressions.Variable;
15 import org.simantics.scl.compiler.elaboration.java.CheckRelation;
16 import org.simantics.scl.compiler.elaboration.query.QAtom;
17 import org.simantics.scl.compiler.elaboration.query.QMapping;
18 import org.simantics.scl.compiler.elaboration.query.Query;
19 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
20 import org.simantics.scl.compiler.elaboration.relations.TransitiveClosureRelation;
21 import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
22 import org.simantics.scl.compiler.environment.AmbiguousNameException;
23 import org.simantics.scl.compiler.environment.Environments;
24 import org.simantics.scl.compiler.errors.Locations;
25
26 public class QPreGuard extends PreQuery {
27     public Expression guard;
28     
29     public QPreGuard(Expression guard) {
30         super();
31         this.guard = guard;
32     }
33
34     private static Query resolveAsQuery(TranslationContext context, Expression function,
35             Expression[] parameters) {
36         if(function instanceof EVar) {
37             String relationName = ((EVar)function).name;
38             if(relationName.equals("tc") && parameters.length > 0) {
39                 Query query_ = resolveAsQuery(context, parameters[0],
40                         Arrays.copyOfRange(parameters, 1, parameters.length));
41                 if(query_ == null)
42                     return null;
43                 if(!(query_ instanceof QAtom)) {
44                     context.getErrorLog().log(query_.location, "Cannot form a transitive relation.");
45                     return null;
46                 }
47                 QAtom query = (QAtom)query_;
48                 query.relation = new TransitiveClosureRelation(query.relation);
49                 return query;
50             }
51             
52             MappingRelation mappingRelation;
53             try {
54                 mappingRelation = Environments.getMappingRelation(
55                         context.getEnvironment(), relationName);
56             } catch (AmbiguousNameException e) {
57                 context.getErrorLog().log(function.location, e.getMessage());
58                 return null;
59             }
60             if(mappingRelation != null) {
61                 if(parameters.length != 2)
62                     context.getErrorLog().log(function.location,
63                             "An arity of mapping relation should always be 2.");
64                 for(int i=0;i<parameters.length;++i)
65                     parameters[i] = parameters[i].resolve(context);
66                 return new QMapping(mappingRelation, parameters);
67             }
68             
69             SCLRelation relation = context.resolveRelation(function.getLocation(), relationName);
70             if(relation != null) {
71                 for(int i=0;i<parameters.length;++i)
72                     parameters[i] = parameters[i].resolve(context);
73                 return new QAtom(relation, parameters);
74             }
75         }
76         return null;
77     }
78     
79     private static Query resolveAsQuery(TranslationContext context, Expression expression) {
80         if(expression instanceof EApply) {
81             EApply apply = (EApply)expression;
82             Query query = resolveAsQuery(context, apply.getFunction(), apply.getParameters());
83             if(query != null)
84                 return query;
85         }
86         else if(expression instanceof EEntityTypeAnnotation) {
87             expression = new ESimpleLet(new Variable("_"), expression, new ELiteral(new BooleanConstant(true)));
88         }
89         return new QAtom(CheckRelation.INSTANCE,
90                 new Expression[] { expression.resolve(context) });
91     }
92     
93     @Override
94     public Query resolve(TranslationContext context) {
95         PreQuery oldPreQuery = context.currentPreQuery;
96         context.currentPreQuery = this;
97         Query query = resolveAsQuery(context, guard);
98         context.currentPreQuery = oldPreQuery;
99         query.location = location;
100         return withSideQueries(query);
101     }
102     
103     @Override
104     public void setLocationDeep(long loc) {
105         if(location == Locations.NO_LOCATION) {
106             location = loc;
107             guard.setLocationDeep(loc);
108         }
109     }
110     
111     @Override
112     public Query accept(QueryTransformer transformer) {
113         return transformer.transform(this);
114     }
115 }