1 package org.simantics.scl.compiler.elaboration.relations;
3 import java.util.ArrayList;
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
6 import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;
7 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
8 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
9 import org.simantics.scl.compiler.elaboration.expressions.Expression;
10 import org.simantics.scl.compiler.elaboration.expressions.Variable;
11 import org.simantics.scl.compiler.elaboration.query.QExists;
12 import org.simantics.scl.compiler.elaboration.query.Query;
13 import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
14 import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
15 import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;
16 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
17 import org.simantics.scl.compiler.internal.parsing.Symbol;
18 import org.simantics.scl.compiler.types.TVar;
19 import org.simantics.scl.compiler.types.Type;
20 import org.simantics.scl.compiler.types.Types;
22 public class ConcreteRelation extends Symbol implements SCLRelation {
24 public final String name;
25 public Variable[] parameters;
26 private int requiredVariablesMask = 0xffffffff;
28 public static class QuerySection {
29 public final int pattern;
30 public final double selectivity;
31 public final Variable[] existentials;
32 public final Query query;
35 public QuerySection(int pattern, double selectivity, Variable[] existentials, Query query) {
36 this.pattern = pattern;
37 this.selectivity = selectivity;
38 this.existentials = existentials;
43 private ArrayList<QuerySection> sections = new ArrayList<QuerySection>(4);
44 public Query enforceSection;
45 public Type writingEffect;
47 Type[] parameterTypes;
48 public TVar[] typeVariables = TVar.EMPTY_ARRAY;
51 public ConcreteRelation(String name) {
55 public void addSection(int pattern, double selectivity, Variable[] existentials, Query query) {
56 sections.add(new QuerySection(pattern, selectivity, existentials, query));
57 requiredVariablesMask &= pattern;
60 public QuerySection getSection(int pattern) {
61 for(QuerySection section : sections)
62 if((section.pattern | pattern) == pattern)
67 public ArrayList<QuerySection> getSections() {
72 public TVar[] getTypeVariables() {
77 public Type[] getParameterTypes() {
78 if(parameterTypes == null) {
79 parameterTypes = new Type[parameters.length];
80 for(int i=0;i<parameters.length;++i)
81 parameterTypes[i] = Types.canonical(parameters[i].getType());
83 return parameterTypes;
87 public int getPhase() {
92 public double getSelectivity(int boundVariables) {
93 QuerySection section = getSection(boundVariables);
95 return Double.POSITIVE_INFINITY;
97 return section.selectivity;
101 public int getRequiredVariablesMask() {
102 return requiredVariablesMask;
106 public void generate(long location,
107 QueryCompilationContext context,
108 Type[] typeParameters, Variable[] parameters, int boundVariables) {
109 QuerySection section = getSection(boundVariables);
110 ReplaceContext replaceContext = new ReplaceContext(context.getTypingContext());
111 ArrayList<Variable> freeVariables = new ArrayList<Variable>(parameters.length);
112 for(int i=0;i<parameters.length;++i) {
113 replaceContext.varMap.put(this.parameters[i], new EVariable(parameters[i]));
114 if(((boundVariables>>i)&1) == 0)
115 freeVariables.add(parameters[i]);
117 for(Variable variable : section.existentials) {
118 Variable newVariable = new Variable(variable.getName(), variable.getType());
119 replaceContext.varMap.put(variable, new EVariable(newVariable));
120 freeVariables.add(newVariable);
123 new QExists(freeVariables, section.query.replace(replaceContext)).generate(context);
124 } catch (UnsolvableQueryException e) {
125 throw new InternalCompilerError(e);
130 public Expression generateEnforce(long location,
131 EnforcingContext context,
132 Type[] typeParameters,
133 Variable[] parameters) {
134 if(this.typeVariables.length != typeParameters.length)
135 throw new InternalCompilerError(location, "Invalid number of type parameters given.");
136 if(this.parameters.length != parameters.length)
137 throw new InternalCompilerError(location, "Invalid number of parameters given.");
138 ReplaceContext replaceContext = new ReplaceContext(context.getTypingContext());
139 for(int i=0;i<this.parameters.length;++i)
140 replaceContext.varMap.put(this.parameters[i], new EVariable(parameters[i]));
141 for(int i=0;i<this.typeVariables.length;++i)
142 replaceContext.tvarMap.put(this.typeVariables[i], typeParameters[i]);
143 Query enforceSectionCopy = enforceSection.replace(replaceContext);
144 return enforceSectionCopy.generateEnforce(context);
148 public String toString() {
153 public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) {
154 throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce.");
158 public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,
159 Expression[] expressions) {
160 throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate.");