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.contexts.ReplaceContext;
7 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
8 import org.simantics.scl.compiler.elaboration.expressions.Expression;
9 import org.simantics.scl.compiler.elaboration.expressions.Variable;
10 import org.simantics.scl.compiler.elaboration.query.QExists;
11 import org.simantics.scl.compiler.elaboration.query.Query;
12 import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
13 import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
14 import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;
15 import org.simantics.scl.compiler.internal.parsing.Symbol;
16 import org.simantics.scl.compiler.types.TVar;
17 import org.simantics.scl.compiler.types.Type;
18 import org.simantics.scl.compiler.types.Types;
20 public class ConcreteRelation extends Symbol implements SCLRelation {
22 public final String name;
23 public Variable[] parameters;
24 private int requiredVariablesMask = 0xffffffff;
26 public static class QuerySection {
27 public final int pattern;
28 public final double selectivity;
29 public final Variable[] existentials;
30 public final Query query;
33 public QuerySection(int pattern, double selectivity, Variable[] existentials, Query query) {
34 this.pattern = pattern;
35 this.selectivity = selectivity;
36 this.existentials = existentials;
41 private ArrayList<QuerySection> sections = new ArrayList<QuerySection>(4);
42 public Query enforceSection;
43 public Type writingEffect;
45 Type[] parameterTypes;
46 public TVar[] typeVariables = TVar.EMPTY_ARRAY;
49 public ConcreteRelation(String name) {
53 public void addSection(int pattern, double selectivity, Variable[] existentials, Query query) {
54 sections.add(new QuerySection(pattern, selectivity, existentials, query));
55 requiredVariablesMask &= pattern;
58 public QuerySection getSection(int pattern) {
59 for(QuerySection section : sections)
60 if((section.pattern | pattern) == pattern)
65 public ArrayList<QuerySection> getSections() {
70 public TVar[] getTypeVariables() {
75 public Type[] getParameterTypes() {
76 if(parameterTypes == null) {
77 parameterTypes = new Type[parameters.length];
78 for(int i=0;i<parameters.length;++i)
79 parameterTypes[i] = Types.canonical(parameters[i].getType());
81 return parameterTypes;
85 public int getPhase() {
90 public double getSelectivity(int boundVariables) {
91 QuerySection section = getSection(boundVariables);
93 return Double.POSITIVE_INFINITY;
95 return section.selectivity;
99 public int getRequiredVariablesMask() {
100 return requiredVariablesMask;
104 public void generate(long location,
105 QueryCompilationContext context,
106 Type[] typeParameters, Variable[] parameters, int boundVariables) {
107 QuerySection section = getSection(boundVariables);
108 ReplaceContext replaceContext = new ReplaceContext(context.getTypingContext());
109 ArrayList<Variable> freeVariables = new ArrayList<Variable>(parameters.length);
110 for(int i=0;i<parameters.length;++i) {
111 replaceContext.varMap.put(this.parameters[i], new EVariable(parameters[i]));
112 if(((boundVariables>>i)&1) == 0)
113 freeVariables.add(parameters[i]);
115 for(Variable variable : section.existentials) {
116 Variable newVariable = new Variable(variable.getName(), variable.getType());
117 replaceContext.varMap.put(variable, new EVariable(newVariable));
118 freeVariables.add(newVariable);
121 new QExists(freeVariables, section.query.replace(replaceContext)).generate(context);
122 } catch (UnsolvableQueryException e) {
123 throw new InternalCompilerError(e);
128 public Expression generateEnforce(long location,
129 EnforcingContext context,
130 Type[] typeParameters,
131 Variable[] parameters) {
132 if(this.typeVariables.length != typeParameters.length)
133 throw new InternalCompilerError(location, "Invalid number of type parameters given.");
134 if(this.parameters.length != parameters.length)
135 throw new InternalCompilerError(location, "Invalid number of parameters given.");
136 ReplaceContext replaceContext = new ReplaceContext(context.getTypingContext());
137 for(int i=0;i<this.parameters.length;++i)
138 replaceContext.varMap.put(this.parameters[i], new EVariable(parameters[i]));
139 for(int i=0;i<this.typeVariables.length;++i)
140 replaceContext.tvarMap.put(this.typeVariables[i], typeParameters[i]);
141 Query enforceSectionCopy = enforceSection.replace(replaceContext);
142 return enforceSectionCopy.generateEnforce(context);
146 public String toString() {