]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphRelation.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / scl / GraphRelation.java
1 package org.simantics.modeling.scl;\r
2 \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
20 \r
21 public class GraphRelation implements SCLRelation {\r
22 \r
23     Resource relation;\r
24     double relationSelectivity;\r
25     Resource inverseRelation;\r
26     double inverseRelationSelectivity;\r
27     \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
34     }\r
35 \r
36     @Override\r
37     public TVar[] getTypeVariables() {\r
38         return TVar.EMPTY_ARRAY;\r
39     }\r
40     \r
41     private static final Type[] PARAMETER_TYPES = new Type[] { Types.RESOURCE, Types.RESOURCE };\r
42     \r
43     @Override\r
44     public Type[] getParameterTypes() {\r
45         return PARAMETER_TYPES;\r
46     }\r
47 \r
48     @Override\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
56         }\r
57     }\r
58     \r
59     @Override\r
60     public int getRequiredVariablesMask() {\r
61         return inverseRelation == null ? BF : FF;\r
62     }\r
63     \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
66     \r
67     @Override\r
68     public void generate(long location, QueryCompilationContext context,\r
69             Type[] typeParameters, Variable[] parameters, int boundVariables) {\r
70         switch(boundVariables) {\r
71         case BF: \r
72             context.iterateList(parameters[1], new EApply(\r
73                     Locations.NO_LOCATION,\r
74                     Types.READ_GRAPH,\r
75                     context.getCompilationContext().getConstant(GET_OBJECTS),\r
76                     new EVariable(parameters[0]),\r
77                     new EExternalConstant(relation, Types.RESOURCE)\r
78                     ));\r
79             break;\r
80         case FB:\r
81             if(inverseRelation == null)\r
82                 throw new IllegalArgumentException();\r
83             context.iterateList(parameters[0], new EApply(\r
84                     Locations.NO_LOCATION,\r
85                     Types.READ_GRAPH,\r
86                     context.getCompilationContext().getConstant(GET_OBJECTS),\r
87                     new EVariable(parameters[1]),\r
88                     new EExternalConstant(inverseRelation, Types.RESOURCE)\r
89                     ));\r
90             break;\r
91         case BB:\r
92             context.condition(\r
93                     inverseRelation == null || relationSelectivity <= inverseRelationSelectivity\r
94                     ? new EApply(\r
95                             Locations.NO_LOCATION,\r
96                             Types.READ_GRAPH,\r
97                             context.getCompilationContext().getConstant(HAS_STATEMENT),\r
98                             new Expression[] {\r
99                                 new EVariable(parameters[0]),\r
100                                 new EExternalConstant(relation, Types.RESOURCE),\r
101                                 new EVariable(parameters[1])\r
102                             }\r
103                             )\r
104                     : new EApply(\r
105                             Locations.NO_LOCATION,\r
106                             Types.READ_GRAPH,\r
107                             context.getCompilationContext().getConstant(HAS_STATEMENT),\r
108                             new Expression[] {\r
109                                 new EVariable(parameters[1]),\r
110                                 new EExternalConstant(inverseRelation, Types.RESOURCE),\r
111                                 new EVariable(parameters[0])\r
112                             }\r
113                             ));\r
114             break;\r
115         default: throw new IllegalArgumentException();\r
116         }\r
117     }\r
118 \r
119     private static final Name CLAIM = Name.create("Simantics/DB", "claim");\r
120     \r
121     @Override\r
122     public Expression generateEnforce(long location, EnforcingContext context,\r
123             Type[] typeParameters, Variable[] parameters) {\r
124         return new EApply(\r
125                 Locations.NO_LOCATION,\r
126                 Types.WRITE_GRAPH,\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
131                 );\r
132     }\r
133 \r
134     @Override\r
135     public int getPhase() {\r
136         return 0;\r
137     }\r
138 \r
139     @Override\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
144         case BF:\r
145             context.iterateList(location, w, variables[1],\r
146                     w.apply(location,\r
147                             env.getValue(GET_OBJECTS).getValue(),\r
148                             expressions[0].toVal(env, w),\r
149                             w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE)));\r
150             break;\r
151         case FB:\r
152             if(inverseRelation == null)\r
153                 throw new IllegalArgumentException();\r
154             context.iterateList(location, w, variables[0],\r
155                     w.apply(location,\r
156                             env.getValue(GET_OBJECTS).getValue(),\r
157                             expressions[1].toVal(env, w),\r
158                             w.getModuleWriter().getExternalConstant(inverseRelation, Types.RESOURCE)));\r
159             break;\r
160         case BB:\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
171             break;\r
172         default: throw new IllegalArgumentException();\r
173         }\r
174     }\r
175 \r
176     @Override\r
177     public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) {\r
178         Environment env = context.context.environment;\r
179         w.apply(location,\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
184     }\r
185 }\r