]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRSelect.java
(refs #7371) Support for select keyword for CHR constraints
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / ECHRSelect.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRSelect.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRSelect.java
new file mode 100644 (file)
index 0000000..47c007d
--- /dev/null
@@ -0,0 +1,152 @@
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.constants.NoRepConstant;
+import org.simantics.scl.compiler.elaboration.chr.CHRQuery;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanRealizer;
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ECHRSelect extends Expression {
+    CHRQuery query;
+    Variable[] existentialVariables;
+    Expression expression;
+    private ArrayList<PlanOp> planOps;
+    private CHRRuleset currentRuleset;
+    
+    public ECHRSelect(Expression expression, CHRQuery query) {
+        this.expression = expression;
+        this.query = query;
+    }
+
+    @Override
+    public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        query.collectRefs(allRefs, refs);
+        expression.collectRefs(allRefs, refs);
+    }
+
+    @Override
+    public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+        query.collectVars(allVars, vars);
+        expression.collectVars(allVars, vars);
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        query.forVariables(procedure);
+        expression.forVariables(procedure);
+    }
+
+    @Override
+    protected void updateType() throws MatchException {
+        setType(Types.list(expression.getType()));
+    }
+
+    @Override
+    public Expression inferType(TypingContext context) {
+        for(Variable variable : existentialVariables)
+            variable.setType(Types.metaVar(Kinds.STAR));
+        query.checkType(context);
+        expression = expression.inferType(context);
+        return this;
+    }
+    
+    @Override
+    public Expression simplify(SimplificationContext simplificationContext) {
+        this.expression = expression.simplify(simplificationContext);
+        query.simplify(simplificationContext);
+        
+        CompilationContext compilationContext = simplificationContext.getCompilationContext();
+        QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
+        if(query.createQueryPlan(context, null, -1, null))
+            planOps = context.getPlanOps();
+
+        return this;
+    }
+    
+    @Override
+    public IVal toVal(CompilationContext context, CodeWriter w) {
+        IVal list = w.apply(location, context.getValue(Names.MList_create).getValue(), NoRepConstant.UNIT);
+        planOps.add(new PlanOp(location) {
+            @Override
+            public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {
+                w.apply(location, context.getValue(Names.MList_add).getValue(), list, expression.toVal(context, w));
+            }
+        });
+        PlanRealizer realizer = new PlanRealizer(context, currentRuleset, currentRuleset != null ? currentRuleset.runtimeRulesetVariable : null, null, planOps);
+        realizer.nextOp(w);
+        return w.apply(location, context.getValue(Names.MList_freeze).getValue(), list);
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        query.collectFreeVariables(vars);
+        expression.collectFreeVariables(vars);
+        if(existentialVariables != null)
+            for(Variable variable : existentialVariables)
+                vars.remove(variable);
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        currentRuleset = context.currentRuleset;
+        
+        context.pushExistentialFrame();
+        query.resolve(context);
+        context.disallowNewExistentials();
+        expression = expression.resolve(context);
+        existentialVariables = context.popExistentialFrame();
+        return this;
+    }
+
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            query.setLocationDeep(loc);
+            expression.setLocationDeep(loc);
+        }
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        this.expression = decorator.decorate(expression);
+        return this;
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        expression.collectEffects(effects);
+        query.collectQueryEffects(effects);
+        effects.add(Types.PROC);
+    }
+
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+}