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