]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphPropertyRelation.java
a6009426f36d7422473128b5be520f90ae7eefbd
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / scl / GraphPropertyRelation.java
1 package org.simantics.modeling.scl;
2
3 import org.simantics.db.Resource;
4 import org.simantics.scl.compiler.common.names.Name;
5 import org.simantics.scl.compiler.common.names.Names;
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.environment.Environment;
16 import org.simantics.scl.compiler.errors.Locations;
17 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
18 import org.simantics.scl.compiler.types.TPred;
19 import org.simantics.scl.compiler.types.TVar;
20 import org.simantics.scl.compiler.types.Type;
21 import org.simantics.scl.compiler.types.Types;
22
23 public class GraphPropertyRelation implements SCLRelation {
24
25     Resource propertyRelation;
26     Type valueType;
27     Type[] parameterTypes;
28
29     private static final Type RESOURCE = Types.con("Simantics/DB", "Resource");
30
31     public GraphPropertyRelation(Resource propertyRelation, Type valueType) {
32         this.propertyRelation = propertyRelation;
33         this.valueType = valueType;
34         this.parameterTypes = new Type[] { RESOURCE, valueType };
35     }
36
37     @Override
38     public TVar[] getTypeVariables() {
39         return TVar.EMPTY_ARRAY;
40     }
41
42     @Override
43     public TPred[] getTypeConstraints() {
44         return new TPred[] {Types.pred(Types.SERIALIZABLE, valueType)};
45     }
46
47     @Override
48     public Type[] getParameterTypes() {
49         return parameterTypes;
50     }
51
52     @Override
53     public double getSelectivity(int boundVariables) {
54         switch(boundVariables) {
55         case FF:
56         case FB: return Double.POSITIVE_INFINITY;
57         case BF: return 1.0;
58         case BB: return 0.01;
59         default: throw new IllegalArgumentException();
60         }
61     }
62
63     @Override
64     public int getRequiredVariablesMask() {
65         return BF;
66     }
67
68     private static final Name POSSIBLE_RELATED_VALUE = Name.create("Simantics/DB", "possibleRelatedValue");
69
70     @Override
71     public void generate(long location, QueryCompilationContext context,
72             Type[] typeParameters, Variable[] parameters, int boundVariables) {
73         Expression possibleValue = new EApply(
74                 Locations.NO_LOCATION,
75                 Types.READ_GRAPH,
76                 context.getCompilationContext().getConstant(POSSIBLE_RELATED_VALUE, valueType),
77                 context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),
78                 new EVariable(parameters[0]),
79                 new EExternalConstant(propertyRelation, RESOURCE)
80                 );
81         switch(boundVariables) {
82         case BB: {
83             Variable temp = new Variable("temp", valueType);
84             context.condition(new EApply(
85                     context.getCompilationContext().getConstant(Names.Builtin_equals, valueType),
86                     new Expression[] {
87                             new EVariable(temp),
88                             new EVariable(parameters[1])
89                     }
90                     ));
91             context.iterateMaybe(temp, possibleValue);
92         } break;
93         case BF: context.iterateMaybe(parameters[1], possibleValue);
94         break;
95         default: throw new IllegalArgumentException();
96         }
97     }
98
99     private static final Name CLAIM_RELATED_VALUE = Name.create("Simantics/DB", "claimRelatedValue");
100
101     @Override
102     public Expression generateEnforce(long location, EnforcingContext context,
103             Type[] typeParameters, Variable[] parameters) {
104         return new EApply(
105                 Locations.NO_LOCATION,
106                 Types.WRITE_GRAPH,
107                 context.getCompilationContext().getConstant(CLAIM_RELATED_VALUE, valueType),
108                 context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),
109                 new EVariable(parameters[0]),
110                 new EExternalConstant(propertyRelation, RESOURCE),
111                 new EVariable(parameters[1])
112                 );
113     }
114
115     @Override
116     public int getPhase() {
117         return 0;
118     }
119
120     @Override
121     public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,
122             Expression[] expressions, Expression[] typeConstraintEvidenceParameters) {
123         Environment env = context.context.environment;
124         switch(boundMask) {
125         case BF:
126             context.iterateMaybe(location, w, variables[1],
127                     w.apply(location,
128                             env.getValue(POSSIBLE_RELATED_VALUE).getValue().createSpecialization(valueType),
129                             typeConstraintEvidenceParameters[0].toVal(env, w),
130                             expressions[0].toVal(env, w),
131                             w.getModuleWriter().getExternalConstant(propertyRelation, Types.RESOURCE)));
132             break;
133         case BB:
134             context.checkEqualsJust(location, w, expressions[1].toVal(env, w),
135                     w.apply(location,
136                             env.getValue(POSSIBLE_RELATED_VALUE).getValue().createSpecialization(valueType),
137                             typeConstraintEvidenceParameters[0].toVal(env, w),
138                             expressions[0].toVal(env, w),
139                             w.getModuleWriter().getExternalConstant(propertyRelation, Types.RESOURCE)));
140             break;
141         default: throw new IllegalArgumentException();
142         }
143     }
144
145     @Override
146     public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters, Expression[] typeConstraintEvidenceParameters) {
147         Environment env = context.context.environment;
148         w.apply(location,
149                 env.getValue(CLAIM_RELATED_VALUE).getValue().createSpecialization(valueType),
150                 typeConstraintEvidenceParameters[0].toVal(env, w),
151                 parameters[0].toVal(env, w),
152                 w.getModuleWriter().getExternalConstant(propertyRelation, Types.RESOURCE),
153                 parameters[1].toVal(env, w));
154     }
155 }