--- /dev/null
+package org.simantics.modeling.scl.ontologymodule;
+
+import org.simantics.db.Resource;
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class GraphPropertyRelation implements SCLRelation {
+
+ Resource propertyRelation;
+ Type valueType;
+ Type[] parameterTypes;
+
+ private static final Type RESOURCE = Types.con("Simantics/DB", "Resource");
+
+ public GraphPropertyRelation(Resource propertyRelation, Type valueType) {
+ this.propertyRelation = propertyRelation;
+ this.valueType = valueType;
+ this.parameterTypes = new Type[] { RESOURCE, valueType };
+ }
+
+ @Override
+ public TVar[] getTypeVariables() {
+ return TVar.EMPTY_ARRAY;
+ }
+
+ @Override
+ public TPred[] getTypeConstraints() {
+ return new TPred[] {Types.pred(Types.SERIALIZABLE, valueType)};
+ }
+
+ @Override
+ public Type[] getParameterTypes() {
+ return parameterTypes;
+ }
+
+ @Override
+ public double getSelectivity(int boundVariables) {
+ switch(boundVariables) {
+ case FF:
+ case FB: return Double.POSITIVE_INFINITY;
+ case BF: return 1.0;
+ case BB: return 0.01;
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public int getRequiredVariablesMask() {
+ return BF;
+ }
+
+ private static final Name POSSIBLE_RELATED_VALUE = Name.create("Simantics/DB", "possibleRelatedValue");
+
+ @Override
+ public void generate(long location, QueryCompilationContext context,
+ Type[] typeParameters, Variable[] parameters, int boundVariables) {
+ Expression possibleValue = new EApply(
+ Locations.NO_LOCATION,
+ Types.READ_GRAPH,
+ context.getCompilationContext().getConstant(POSSIBLE_RELATED_VALUE, valueType),
+ context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),
+ new EVariable(parameters[0]),
+ new EExternalConstant(propertyRelation, RESOURCE)
+ );
+ switch(boundVariables) {
+ case BB: {
+ Variable temp = new Variable("temp", valueType);
+ context.condition(new EApply(
+ context.getCompilationContext().getConstant(Names.Builtin_equals, valueType),
+ new Expression[] {
+ new EVariable(temp),
+ new EVariable(parameters[1])
+ }
+ ));
+ context.iterateMaybe(temp, possibleValue);
+ } break;
+ case BF: context.iterateMaybe(parameters[1], possibleValue);
+ break;
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ private static final Name CLAIM_RELATED_VALUE = Name.create("Simantics/DB", "claimRelatedValue");
+
+ @Override
+ public Expression generateEnforce(long location, EnforcingContext context,
+ Type[] typeParameters, Variable[] parameters) {
+ return new EApply(
+ Locations.NO_LOCATION,
+ Types.WRITE_GRAPH,
+ context.getCompilationContext().getConstant(CLAIM_RELATED_VALUE, valueType),
+ context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),
+ new EVariable(parameters[0]),
+ new EExternalConstant(propertyRelation, RESOURCE),
+ new EVariable(parameters[1])
+ );
+ }
+
+ @Override
+ public int getPhase() {
+ return 0;
+ }
+
+ @Override
+ public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,
+ Expression[] expressions, Expression[] typeConstraintEvidenceParameters) {
+ CompilationContext compilationContext = context.context;
+ switch(boundMask) {
+ case BF:
+ context.iterateMaybe(location, w, variables[1],
+ w.apply(location,
+ compilationContext.environment.getValue(POSSIBLE_RELATED_VALUE).getValue().createSpecialization(valueType),
+ typeConstraintEvidenceParameters[0].toVal(compilationContext, w),
+ expressions[0].toVal(compilationContext, w),
+ w.getModuleWriter().getExternalConstant(propertyRelation, Types.RESOURCE)));
+ break;
+ case BB:
+ context.checkEqualsJust(location, w, expressions[1].toVal(compilationContext, w),
+ w.apply(location,
+ compilationContext.environment.getValue(POSSIBLE_RELATED_VALUE).getValue().createSpecialization(valueType),
+ typeConstraintEvidenceParameters[0].toVal(compilationContext, w),
+ expressions[0].toVal(compilationContext, w),
+ w.getModuleWriter().getExternalConstant(propertyRelation, Types.RESOURCE)));
+ break;
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters, Expression[] typeConstraintEvidenceParameters) {
+ CompilationContext compilationContext = context.context;
+ w.apply(location,
+ compilationContext.environment.getValue(CLAIM_RELATED_VALUE).getValue().createSpecialization(valueType),
+ typeConstraintEvidenceParameters[0].toVal(compilationContext, w),
+ parameters[0].toVal(compilationContext, w),
+ w.getModuleWriter().getExternalConstant(propertyRelation, Types.RESOURCE),
+ parameters[1].toVal(compilationContext, w));
+ }
+
+ @Override
+ public Type getEnforceEffect() {
+ return Types.WRITE_GRAPH;
+ }
+
+ @Override
+ public Type getQueryEffect() {
+ return Types.READ_GRAPH;
+ }
+}