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