]> gerrit.simantics Code Review - simantics/platform.git/blob
96ace3b6433f0b3be367b81dbe194cd39ff0a171
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.relations;
2
3 import java.util.ArrayList;
4
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;
21
22 public class ConcreteRelation extends Symbol implements SCLRelation {
23
24     public final String name;
25     public Variable[] parameters;
26     private int requiredVariablesMask = 0xffffffff; 
27     
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;
33         public Type effect;
34         
35         public QuerySection(int pattern, double selectivity, Variable[] existentials, Query query) {
36             this.pattern = pattern;
37             this.selectivity = selectivity;
38             this.existentials = existentials;
39             this.query = query;
40         }        
41     }
42     
43     private ArrayList<QuerySection> sections = new ArrayList<QuerySection>(4);
44     public Query enforceSection;
45     public Type writingEffect;
46
47     Type[] parameterTypes;
48     public TVar[] typeVariables = TVar.EMPTY_ARRAY;
49     public int phase;
50     
51     public ConcreteRelation(String name) {
52         this.name = name;
53     }
54     
55     public void addSection(int pattern, double selectivity, Variable[] existentials, Query query) {
56         sections.add(new QuerySection(pattern, selectivity, existentials, query));
57         requiredVariablesMask &= pattern;
58     }
59     
60     public QuerySection getSection(int pattern) {
61         for(QuerySection section : sections)
62             if((section.pattern | pattern) == pattern)
63                 return section;
64         return null;
65     }
66     
67     public ArrayList<QuerySection> getSections() {
68         return sections;
69     }
70     
71     @Override
72     public TVar[] getTypeVariables() {
73         return typeVariables;
74     }
75     
76     @Override
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());
82         }
83         return parameterTypes;
84     }
85     
86     @Override
87     public int getPhase() {
88         return phase;
89     }
90
91     @Override
92     public double getSelectivity(int boundVariables) {
93         QuerySection section = getSection(boundVariables);
94         if(section == null)
95             return Double.POSITIVE_INFINITY;
96         else
97             return section.selectivity;
98     }
99     
100     @Override
101     public int getRequiredVariablesMask() {
102         return requiredVariablesMask;
103     }
104
105     @Override
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]);
116         }
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);
121         }
122         try {
123             new QExists(freeVariables, section.query.replace(replaceContext)).generate(context);
124         } catch (UnsolvableQueryException e) {
125             throw new InternalCompilerError(e);
126         }
127     }
128
129     @Override
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);
145     }
146     
147     @Override
148     public String toString() {
149         return name;
150     }
151
152     @Override
153     public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters,
154             Expression[] typeConstraintEvidenceParameters) {
155         throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce.");
156     }
157     
158     @Override
159     public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,
160             Expression[] expressions, Expression[] typeConstraintEvidenceParameters) {
161         throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate.");
162     }
163 }