]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/ConcreteRelation.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / relations / ConcreteRelation.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/ConcreteRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/ConcreteRelation.java
new file mode 100644 (file)
index 0000000..83714f2
--- /dev/null
@@ -0,0 +1,150 @@
+package org.simantics.scl.compiler.elaboration.relations;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
+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.QExists;
+import org.simantics.scl.compiler.elaboration.query.Query;
+import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
+import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class ConcreteRelation extends Symbol implements SCLRelation {
+
+    public final String name;
+    public Variable[] parameters;
+    private int requiredVariablesMask = 0xffffffff; 
+    
+    public static class QuerySection {
+        public final int pattern;
+        public final double selectivity;
+        public final Variable[] existentials;
+        public final Query query;
+        public Type effect;
+        
+        public QuerySection(int pattern, double selectivity, Variable[] existentials, Query query) {
+            this.pattern = pattern;
+            this.selectivity = selectivity;
+            this.existentials = existentials;
+            this.query = query;
+        }        
+    }
+    
+    private ArrayList<QuerySection> sections = new ArrayList<QuerySection>(4);
+    public Query enforceSection;
+    public Type writingEffect;
+
+    Type[] parameterTypes;
+    public TVar[] typeVariables = TVar.EMPTY_ARRAY;
+    public int phase;
+    
+    public ConcreteRelation(String name) {
+        this.name = name;
+    }
+    
+    public void addSection(int pattern, double selectivity, Variable[] existentials, Query query) {
+        sections.add(new QuerySection(pattern, selectivity, existentials, query));
+        requiredVariablesMask &= pattern;
+    }
+    
+    public QuerySection getSection(int pattern) {
+        for(QuerySection section : sections)
+            if((section.pattern | pattern) == pattern)
+                return section;
+        return null;
+    }
+    
+    public ArrayList<QuerySection> getSections() {
+        return sections;
+    }
+    
+    @Override
+    public TVar[] getTypeVariables() {
+        return typeVariables;
+    }
+    
+    @Override
+    public Type[] getParameterTypes() {
+        if(parameterTypes == null) {
+            parameterTypes = new Type[parameters.length];
+            for(int i=0;i<parameters.length;++i)
+                parameterTypes[i] = Types.canonical(parameters[i].getType());
+        }
+        return parameterTypes;
+    }
+    
+    @Override
+    public int getPhase() {
+        return phase;
+    }
+
+    @Override
+    public double getSelectivity(int boundVariables) {
+        QuerySection section = getSection(boundVariables);
+        if(section == null)
+            return Double.POSITIVE_INFINITY;
+        else
+            return section.selectivity;
+    }
+    
+    @Override
+    public int getRequiredVariablesMask() {
+        return requiredVariablesMask;
+    }
+
+    @Override
+    public void generate(long location,
+            QueryCompilationContext context,
+            Type[] typeParameters, Variable[] parameters, int boundVariables) {
+        QuerySection section = getSection(boundVariables);
+        ReplaceContext replaceContext = new ReplaceContext(context.getTypingContext());
+        ArrayList<Variable> freeVariables = new ArrayList<Variable>(parameters.length); 
+        for(int i=0;i<parameters.length;++i) {
+            replaceContext.varMap.put(this.parameters[i], new EVariable(parameters[i]));
+            if(((boundVariables>>i)&1) == 0)
+                freeVariables.add(parameters[i]);
+        }
+        for(Variable variable : section.existentials) {
+            Variable newVariable = new Variable(variable.getName(), variable.getType());
+            replaceContext.varMap.put(variable, new EVariable(newVariable));
+            freeVariables.add(newVariable);
+        }
+        try {
+            new QExists(freeVariables, section.query.replace(replaceContext)).generate(context);
+        } catch (UnsolvableQueryException e) {
+            throw new InternalCompilerError(e);
+        }
+    }
+
+    @Override
+    public Expression generateEnforce(long location,
+            EnforcingContext context,
+            Type[] typeParameters,
+            Variable[] parameters) {
+        if(this.typeVariables.length != typeParameters.length)
+            throw new InternalCompilerError(location, "Invalid number of type parameters given.");
+        if(this.parameters.length != parameters.length)
+            throw new InternalCompilerError(location, "Invalid number of parameters given.");
+        ReplaceContext replaceContext = new ReplaceContext(context.getTypingContext());
+        for(int i=0;i<this.parameters.length;++i)
+            replaceContext.varMap.put(this.parameters[i], new EVariable(parameters[i]));
+        for(int i=0;i<this.typeVariables.length;++i)
+            replaceContext.tvarMap.put(this.typeVariables[i], typeParameters[i]);
+        Query enforceSectionCopy = enforceSection.replace(replaceContext);
+        return enforceSectionCopy.generateEnforce(context);
+    }
+    
+    @Override
+    public String toString() {
+        return name;
+    }
+
+}