--- /dev/null
+package org.simantics.modeling.scl;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;\r
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class GraphPropertyRelation implements SCLRelation {\r
+\r
+ Resource propertyRelation;\r
+ Type valueType;\r
+ Type[] parameterTypes;\r
+\r
+ private static final Type RESOURCE = Types.con("Simantics/DB", "Resource");\r
+ \r
+ public GraphPropertyRelation(Resource propertyRelation, Type valueType) {\r
+ this.propertyRelation = propertyRelation;\r
+ this.valueType = valueType;\r
+ this.parameterTypes = new Type[] { RESOURCE, valueType };\r
+ }\r
+\r
+ @Override\r
+ public TVar[] getTypeVariables() {\r
+ return TVar.EMPTY_ARRAY;\r
+ }\r
+ \r
+ @Override\r
+ public Type[] getParameterTypes() {\r
+ return parameterTypes;\r
+ }\r
+\r
+ @Override\r
+ public double getSelectivity(int boundVariables) {\r
+ switch(boundVariables) {\r
+ case FF:\r
+ case FB: return Double.POSITIVE_INFINITY;\r
+ case BF: return 1.0;\r
+ case BB: return 0.01;\r
+ default: throw new IllegalArgumentException();\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public int getRequiredVariablesMask() {\r
+ return BF;\r
+ }\r
+ \r
+ private static final Name POSSIBLE_RELATED_VALUE = Name.create("Simantics/DB", "possibleRelatedValue");\r
+ \r
+ @Override\r
+ public void generate(long location, QueryCompilationContext context,\r
+ Type[] typeParameters, Variable[] parameters, int boundVariables) {\r
+ Expression possibleValue = new EApply(\r
+ Locations.NO_LOCATION,\r
+ Types.READ_GRAPH,\r
+ context.getTypingContext().getConstant(POSSIBLE_RELATED_VALUE, valueType),\r
+ context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),\r
+ new EVariable(parameters[0]),\r
+ new EExternalConstant(propertyRelation, RESOURCE)\r
+ );\r
+ switch(boundVariables) {\r
+ case BB: {\r
+ Variable temp = new Variable("temp", valueType);\r
+ context.condition(new EApply(\r
+ context.getTypingContext().getConstant(Name.create("Prelude", "=="), valueType),\r
+ new Expression[] {\r
+ context.getEvidence(location, Types.pred(Types.EQ, valueType)),\r
+ new EVariable(temp),\r
+ new EVariable(parameters[1])\r
+ }\r
+ ));\r
+ context.iterateMaybe(temp, possibleValue);\r
+ } break;\r
+ case BF: context.iterateMaybe(parameters[1], possibleValue);\r
+ break;\r
+ default: throw new IllegalArgumentException();\r
+ }\r
+ }\r
+\r
+ private static final Name CLAIM_RELATED_VALUE = Name.create("Simantics/DB", "claimRelatedValue");\r
+ \r
+ @Override\r
+ public Expression generateEnforce(long location, EnforcingContext context,\r
+ Type[] typeParameters, Variable[] parameters) {\r
+ return new EApply(\r
+ Locations.NO_LOCATION,\r
+ Types.WRITE_GRAPH,\r
+ context.getTypingContext().getConstant(CLAIM_RELATED_VALUE, valueType),\r
+ context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),\r
+ new EVariable(parameters[0]),\r
+ new EExternalConstant(propertyRelation, RESOURCE),\r
+ new EVariable(parameters[1])\r
+ );\r
+ }\r
+\r
+ @Override\r
+ public int getPhase() {\r
+ return 0;\r
+ }\r
+ \r
+}\r