]> gerrit.simantics Code Review - simantics/platform.git/blob
83714f26ba78c7eaf8342f87c0cb7a88e11527ea
[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.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;
19
20 public class ConcreteRelation extends Symbol implements SCLRelation {
21
22     public final String name;
23     public Variable[] parameters;
24     private int requiredVariablesMask = 0xffffffff; 
25     
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;
31         public Type effect;
32         
33         public QuerySection(int pattern, double selectivity, Variable[] existentials, Query query) {
34             this.pattern = pattern;
35             this.selectivity = selectivity;
36             this.existentials = existentials;
37             this.query = query;
38         }        
39     }
40     
41     private ArrayList<QuerySection> sections = new ArrayList<QuerySection>(4);
42     public Query enforceSection;
43     public Type writingEffect;
44
45     Type[] parameterTypes;
46     public TVar[] typeVariables = TVar.EMPTY_ARRAY;
47     public int phase;
48     
49     public ConcreteRelation(String name) {
50         this.name = name;
51     }
52     
53     public void addSection(int pattern, double selectivity, Variable[] existentials, Query query) {
54         sections.add(new QuerySection(pattern, selectivity, existentials, query));
55         requiredVariablesMask &= pattern;
56     }
57     
58     public QuerySection getSection(int pattern) {
59         for(QuerySection section : sections)
60             if((section.pattern | pattern) == pattern)
61                 return section;
62         return null;
63     }
64     
65     public ArrayList<QuerySection> getSections() {
66         return sections;
67     }
68     
69     @Override
70     public TVar[] getTypeVariables() {
71         return typeVariables;
72     }
73     
74     @Override
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());
80         }
81         return parameterTypes;
82     }
83     
84     @Override
85     public int getPhase() {
86         return phase;
87     }
88
89     @Override
90     public double getSelectivity(int boundVariables) {
91         QuerySection section = getSection(boundVariables);
92         if(section == null)
93             return Double.POSITIVE_INFINITY;
94         else
95             return section.selectivity;
96     }
97     
98     @Override
99     public int getRequiredVariablesMask() {
100         return requiredVariablesMask;
101     }
102
103     @Override
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]);
114         }
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);
119         }
120         try {
121             new QExists(freeVariables, section.query.replace(replaceContext)).generate(context);
122         } catch (UnsolvableQueryException e) {
123             throw new InternalCompilerError(e);
124         }
125     }
126
127     @Override
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);
143     }
144     
145     @Override
146     public String toString() {
147         return name;
148     }
149
150 }