]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/LocalRelation.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / relations / LocalRelation.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/LocalRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/LocalRelation.java
new file mode 100644 (file)
index 0000000..900c962
--- /dev/null
@@ -0,0 +1,112 @@
+package org.simantics.scl.compiler.elaboration.relations;
+
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.*;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.elaboration.expressions.ERuleset;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expressions;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+public class LocalRelation extends AbstractRelation {
+    String name;
+    Type[] parameterTypes;
+    public Variable table;
+    
+    public LocalRelation(String name, int arity) {
+        this.name = name;
+        this.parameterTypes = new Type[arity];
+        for(int i=0;i<arity;++i)
+            parameterTypes[i] = Types.metaVar(Kinds.STAR);
+        createTable();
+    }
+    
+    public LocalRelation(String name, Type[] parameterTypes) {
+        this.name = name;
+        this.parameterTypes = parameterTypes;
+        createTable();
+    }
+    
+    private void createTable() {
+        this.table = newVar("table" + name, 
+                Types.apply(ERuleset.MSet, Types.tuple(parameterTypes)));
+    }
+    
+    public int getArity() {
+        return parameterTypes.length;
+    }
+
+    public String getName() {
+        return name;
+    }
+    
+    @Override
+    public TVar[] getTypeVariables() {
+        return TVar.EMPTY_ARRAY;
+    }
+
+    @Override
+    public Type[] getParameterTypes() {
+        return parameterTypes;
+    }
+    
+    @Override
+    public double getSelectivity(int boundVariabes) {
+        double s = 0.95;
+        for(int i=0;i<parameterTypes.length;++i,boundVariabes>>=1)
+            if( (boundVariabes&1) == 0 )
+                s *= 10.0;
+        return s;
+    }
+    
+    @Override
+    public int getRequiredVariablesMask() {
+        return 0;
+    }
+    
+    private static final Name MSet_contains = Name.create("MSet", "contains"); 
+    private static final Name EQ = Name.create("Prelude", "==");
+    @Override
+    public void generate(long location,
+            QueryCompilationContext context,
+            Type[] typeParameters, Variable[] parameters, int boundVariables) {
+        if(table == null)
+            throw new InternalCompilerError(location, "Variable table is undefined.");
+        if(boundVariables + 1 == 1 << parameters.length)
+            context.condition(apply(context, Types.PROC,
+                    MSet_contains, Types.tuple(parameterTypes),
+                    var(table),
+                    tuple(vars(parameters))
+                    ));
+        else {
+            Variable[] aux = new Variable[parameters.length];
+            for(int i=0;i<parameters.length;++i)
+                if(((boundVariables>>i)&1) == 1)
+                    aux[i] = new Variable("aux_" + parameters[i].getName(), parameters[i].getType());
+                else
+                    aux[i] = parameters[i];
+            Variable row = new Variable("row", Types.tuple(parameterTypes));
+            for(int i=0;i<parameters.length;++i)
+                if(((boundVariables>>i)&1) == 1)
+                    context.condition(apply(context, Types.NO_EFFECTS,
+                            EQ, parameterTypes[i],
+                            context.getEvidence(location, Types.pred(Types.EQ, parameterTypes[i])),
+                            var(aux[i]),
+                            var(parameters[i])
+                            ));
+            context.match(Expressions.tuple(Expressions.vars(aux)), new EVariable(row), false);
+            context.iterateMSet(row, new EVariable(table));
+        }
+    }
+    
+    @Override
+    public String toString() {
+        return name;
+    }
+}