1 package org.simantics.modeling.scl;
\r
3 import org.simantics.db.Resource;
\r
4 import org.simantics.scl.compiler.common.names.Name;
\r
5 import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;
\r
6 import org.simantics.scl.compiler.elaboration.expressions.EApply;
\r
7 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
\r
8 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
\r
9 import org.simantics.scl.compiler.elaboration.expressions.Expression;
\r
10 import org.simantics.scl.compiler.elaboration.expressions.Variable;
\r
11 import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
\r
12 import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
\r
13 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
\r
14 import org.simantics.scl.compiler.environment.Environment;
\r
15 import org.simantics.scl.compiler.errors.Locations;
\r
16 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
\r
17 import org.simantics.scl.compiler.types.TVar;
\r
18 import org.simantics.scl.compiler.types.Type;
\r
19 import org.simantics.scl.compiler.types.Types;
\r
21 public class GraphRelation implements SCLRelation {
\r
24 double relationSelectivity;
\r
25 Resource inverseRelation;
\r
26 double inverseRelationSelectivity;
\r
28 public GraphRelation(Resource relation, double relationSelectivity,
\r
29 Resource inverseRelation, double inverseRelationSelectivity) {
\r
30 this.relation = relation;
\r
31 this.relationSelectivity = relationSelectivity;
\r
32 this.inverseRelation = inverseRelation;
\r
33 this.inverseRelationSelectivity = inverseRelationSelectivity;
\r
37 public TVar[] getTypeVariables() {
\r
38 return TVar.EMPTY_ARRAY;
\r
41 private static final Type[] PARAMETER_TYPES = new Type[] { Types.RESOURCE, Types.RESOURCE };
\r
44 public Type[] getParameterTypes() {
\r
45 return PARAMETER_TYPES;
\r
49 public double getSelectivity(int boundVariables) {
\r
50 switch(boundVariables) {
\r
51 case FF: return Double.POSITIVE_INFINITY;
\r
52 case BF: return relationSelectivity;
\r
53 case FB: return inverseRelation == null ? Double.POSITIVE_INFINITY : inverseRelationSelectivity;
\r
54 case BB: return 0.1;
\r
55 default: throw new IllegalArgumentException();
\r
60 public int getRequiredVariablesMask() {
\r
61 return inverseRelation == null ? BF : FF;
\r
64 private static final Name GET_OBJECTS = Name.create("Simantics/DB", "#");
\r
65 private static final Name HAS_STATEMENT = Name.create("Simantics/DB", "existsStatement3");
\r
68 public void generate(long location, QueryCompilationContext context,
\r
69 Type[] typeParameters, Variable[] parameters, int boundVariables) {
\r
70 switch(boundVariables) {
\r
72 context.iterateList(parameters[1], new EApply(
\r
73 Locations.NO_LOCATION,
\r
75 context.getCompilationContext().getConstant(GET_OBJECTS),
\r
76 new EVariable(parameters[0]),
\r
77 new EExternalConstant(relation, Types.RESOURCE)
\r
81 if(inverseRelation == null)
\r
82 throw new IllegalArgumentException();
\r
83 context.iterateList(parameters[0], new EApply(
\r
84 Locations.NO_LOCATION,
\r
86 context.getCompilationContext().getConstant(GET_OBJECTS),
\r
87 new EVariable(parameters[1]),
\r
88 new EExternalConstant(inverseRelation, Types.RESOURCE)
\r
93 inverseRelation == null || relationSelectivity <= inverseRelationSelectivity
\r
95 Locations.NO_LOCATION,
\r
97 context.getCompilationContext().getConstant(HAS_STATEMENT),
\r
99 new EVariable(parameters[0]),
\r
100 new EExternalConstant(relation, Types.RESOURCE),
\r
101 new EVariable(parameters[1])
\r
105 Locations.NO_LOCATION,
\r
107 context.getCompilationContext().getConstant(HAS_STATEMENT),
\r
109 new EVariable(parameters[1]),
\r
110 new EExternalConstant(inverseRelation, Types.RESOURCE),
\r
111 new EVariable(parameters[0])
\r
115 default: throw new IllegalArgumentException();
\r
119 private static final Name CLAIM = Name.create("Simantics/DB", "claim");
\r
122 public Expression generateEnforce(long location, EnforcingContext context,
\r
123 Type[] typeParameters, Variable[] parameters) {
\r
125 Locations.NO_LOCATION,
\r
127 context.getCompilationContext().getConstant(CLAIM),
\r
128 new EVariable(parameters[0]),
\r
129 new EExternalConstant(relation, Types.RESOURCE),
\r
130 new EVariable(parameters[1])
\r
135 public int getPhase() {
\r
140 public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,
\r
141 Expression[] expressions) {
\r
142 Environment env = context.context.environment;
\r
143 switch(boundMask) {
\r
145 context.iterateList(location, w, variables[1],
\r
147 env.getValue(GET_OBJECTS).getValue(),
\r
148 expressions[0].toVal(env, w),
\r
149 w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE)));
\r
152 if(inverseRelation == null)
\r
153 throw new IllegalArgumentException();
\r
154 context.iterateList(location, w, variables[0],
\r
156 env.getValue(GET_OBJECTS).getValue(),
\r
157 expressions[1].toVal(env, w),
\r
158 w.getModuleWriter().getExternalConstant(inverseRelation, Types.RESOURCE)));
\r
161 context.check(location, w,
\r
162 inverseRelation == null || relationSelectivity <= inverseRelationSelectivity
\r
163 ? w.apply(location, env.getValue(HAS_STATEMENT).getValue(),
\r
164 expressions[0].toVal(env, w),
\r
165 w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE),
\r
166 expressions[1].toVal(env, w))
\r
167 : w.apply(location, env.getValue(HAS_STATEMENT).getValue(),
\r
168 expressions[1].toVal(env, w),
\r
169 w.getModuleWriter().getExternalConstant(inverseRelation, Types.RESOURCE),
\r
170 expressions[0].toVal(env, w)));
\r
172 default: throw new IllegalArgumentException();
\r
177 public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) {
\r
178 Environment env = context.context.environment;
\r
180 env.getValue(CLAIM).getValue(),
\r
181 parameters[0].toVal(env, w),
\r
182 w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE),
\r
183 parameters[1].toVal(env, w));
\r