1 package org.simantics.scl.compiler.elaboration.query.pre;
3 import java.util.Arrays;
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;
26 public class QPreGuard extends PreQuery {
27 public Expression guard;
29 public QPreGuard(Expression guard) {
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));
43 if(!(query_ instanceof QAtom)) {
44 context.getErrorLog().log(query_.location, "Cannot form a transitive relation.");
47 QAtom query = (QAtom)query_;
48 query.relation = new TransitiveClosureRelation(query.relation);
52 MappingRelation mappingRelation;
54 mappingRelation = Environments.getMappingRelation(
55 context.getEnvironment(), relationName);
56 } catch (AmbiguousNameException e) {
57 context.getErrorLog().log(function.location, e.getMessage());
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);
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);
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());
86 else if(expression instanceof EEntityTypeAnnotation) {
87 expression = new ESimpleLet(new Variable("_"), expression, new ELiteral(new BooleanConstant(true)));
89 return new QAtom(CheckRelation.INSTANCE,
90 new Expression[] { expression.resolve(context) });
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);
104 public void setLocationDeep(long loc) {
105 if(location == Locations.NO_LOCATION) {
107 guard.setLocationDeep(loc);
112 public Query accept(QueryTransformer transformer) {
113 return transformer.transform(this);