]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRLiteral.java
918dd9fb309ef25d4d9dfd3f156e60b7d4b097e5
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / CHRLiteral.java
1 package org.simantics.scl.compiler.elaboration.chr;
2
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
4 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
5 import org.simantics.scl.compiler.elaboration.chr.relations.ExternalCHRRelation;
6 import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
7 import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;
8 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
9 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
10 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext.ExistentialFrame;
11 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
12 import org.simantics.scl.compiler.elaboration.expressions.ERecord;
13 import org.simantics.scl.compiler.elaboration.expressions.Expression;
14 import org.simantics.scl.compiler.elaboration.expressions.Variable;
15 import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
16 import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
17 import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
18 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
19 import org.simantics.scl.compiler.errors.Locations;
20 import org.simantics.scl.compiler.internal.parsing.Symbol;
21 import org.simantics.scl.compiler.types.TVar;
22 import org.simantics.scl.compiler.types.Type;
23 import org.simantics.scl.compiler.types.Types;
24 import org.simantics.scl.compiler.types.kinds.Kinds;
25
26 import gnu.trove.map.hash.TObjectIntHashMap;
27 import gnu.trove.set.hash.THashSet;
28 import gnu.trove.set.hash.TIntHashSet;
29
30 public class CHRLiteral extends Symbol {
31     
32     public CHRRelation relation;
33     public Type[] typeParameters;
34     public Expression[] parameters;
35     public FieldAssignment[] fields; // optional
36     public Expression[] typeConstraintEvidenceParameters;
37     public boolean killAfterMatch;
38     public boolean negated;
39     public boolean passive = true;
40     
41     public CHRLiteral(long location, CHRRelation relation, Expression[] parameters, boolean remove, boolean negated) {
42         this.location = location;
43         this.relation = relation;
44         this.parameters = parameters;
45         this.killAfterMatch = remove;
46         this.negated = negated;
47     }
48
49     public void resolve(TranslationContext context) {
50         if(relation == SpecialCHRRelation.ASSIGN) {
51             parameters[1] = parameters[1].resolve(context);
52             parameters[0] = parameters[0].resolveAsPattern(context);
53             return;
54         }
55         if(parameters != null) {
56             for(int i=0;i<parameters.length;++i)
57                 parameters[i] = parameters[i].resolve(context);
58         }
59         if(relation instanceof UnresolvedCHRRelation) {
60             UnresolvedCHRRelation unresolved = (UnresolvedCHRRelation)relation;
61             CHRConstraint constraint = context.resolveCHRConstraint(unresolved.name);
62             if(constraint != null) {
63                 relation = constraint;
64                 passive = false;
65             }
66             else {
67                 SCLRelation sclRelation = context.resolveRelation(unresolved.location, unresolved.name);
68                 if(sclRelation != null)
69                     relation = new ExternalCHRRelation(sclRelation);
70                 else {
71                     if(unresolved.name.contains(".")) {
72                         context.getErrorLog().log(unresolved.location, "Couldn't resolve relation " + unresolved.name + ".");
73                         return;
74                     }   
75                     if(parameters == null) {
76                         context.getErrorLog().log(location, "Relation must be declared if record syntax is used.");
77                         return;
78                     }
79                     Type[] parameterTypes = new Type[parameters.length];
80                     for(int i=0;i<parameterTypes.length;++i)
81                         parameterTypes[i] = Types.metaVar(Kinds.STAR);
82                     constraint = new CHRConstraint(location, unresolved.name, parameterTypes);
83                     constraint.implicitlyDeclared = true;
84                     context.newCHRConstraint(constraint.name, constraint);
85                     relation = constraint;
86                     passive = false;
87                     //context.getErrorLog().log(unresolved.location, "Couldn't resolve constraint " + unresolved.name + ".");
88                 }
89             }
90         }
91         if(parameters == null && fields != null) {
92             String[] fieldNames = relation.getFieldNames();
93             if(fieldNames == null) {
94                 context.getErrorLog().log(location, "Relation " + relation + " does not define field names.");
95                 return;
96             }
97             parameters = ERecord.translateFieldsToFunctionParameters(context, fields, fieldNames);
98             if(parameters == null)
99                 return;
100             for(int i=0;i<parameters.length;++i) {
101                 Expression parameter = parameters[i];
102                 if(parameter == null) {
103                     ExistentialFrame frame = context.getCurrentExistentialFrame();
104                     if(frame == null || frame.disallowNewExistentials)
105                         context.getErrorLog().log(location, "Field " + fieldNames[i] + " not defined.");
106                     else
107                         parameters[i] = frame.createBlank(location);
108                 }
109                 else
110                     parameters[i] = parameters[i].resolve(context);
111             }
112             fields = null;
113         }
114     }
115
116     public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
117         for(Expression parameter : parameters)
118             parameter.collectRefs(allRefs, refs);
119         if(typeConstraintEvidenceParameters != null)
120             for(Expression parameter : typeConstraintEvidenceParameters)
121                 parameter.collectRefs(allRefs, refs);
122     }
123
124     public void checkType(TypingContext context) {
125         if(relation == SpecialCHRRelation.EXECUTE) {
126             if(parameters.length != 1)
127                 throw new InternalCompilerError("Wrong number of parameters for EXECUTE constraint.");
128             parameters[0] = parameters[0].checkIgnoredType(context);
129             typeConstraintEvidenceParameters = Expression.EMPTY_ARRAY;
130         }
131         else if(relation == SpecialCHRRelation.ASSIGN) {
132             parameters[1] = parameters[1].inferType(context);
133             parameters[0] = parameters[0].checkTypeAsPattern(context, parameters[1].getType());
134             typeConstraintEvidenceParameters = Expression.EMPTY_ARRAY;
135         }
136         else {
137             TVar[] typeVariables = relation.getTypeVariables();
138             typeParameters = typeVariables.length == 0 ? Type.EMPTY_ARRAY : new Type[typeVariables.length];
139             for(int i=0;i<typeVariables.length;++i)
140                 typeParameters[i] = Types.metaVar(typeVariables[i].getKind());
141             Type[] parameterTypes = Types.replace(relation.getParameterTypes(), typeVariables, typeParameters);
142             if(parameterTypes.length != parameters.length)
143                 context.getErrorLog().log(location, "Constraint is applied with wrong number of parameters");
144             else
145                 for(int i=0;i<parameters.length;++i)
146                     parameters[i] = parameters[i].checkType(context, parameterTypes[i]);
147             
148             typeConstraintEvidenceParameters = context.addConstraints(Types.replace(relation.getTypeConstraints(), typeVariables, typeParameters));
149         }
150     }
151
152     public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
153         for(Expression parameter : parameters)
154             parameter.collectVars(allVars, vars);
155         if(typeConstraintEvidenceParameters != null)
156             for(Expression parameter : typeConstraintEvidenceParameters)
157                 parameter.collectVars(allVars, vars);
158     }
159
160     public void forVariables(VariableProcedure procedure) {
161         for(Expression parameter : parameters)
162             parameter.forVariables(procedure);
163         if(typeConstraintEvidenceParameters != null)
164             for(Expression parameter : typeConstraintEvidenceParameters)
165                 parameter.forVariables(procedure);
166     }
167
168     public void collectFreeVariables(THashSet<Variable> vars) {
169         if(relation == SpecialCHRRelation.ASSIGN) {
170             parameters[1].collectFreeVariables(vars);
171         }
172         else {
173             for(Expression parameter : parameters)
174                 parameter.collectFreeVariables(vars);
175             if(typeConstraintEvidenceParameters != null)
176                 for(Expression parameter : typeConstraintEvidenceParameters)
177                     parameter.collectFreeVariables(vars);
178         }
179     }
180
181     public void setLocationDeep(long loc) {
182         if(location == Locations.NO_LOCATION) {
183             this.location = loc;
184             for(Expression parameter : parameters)
185                 parameter.setLocationDeep(loc);
186         }
187     }
188     
189     public void simplify(SimplificationContext context) {
190         for(int i=0;i<parameters.length;++i)
191             parameters[i] = parameters[i].simplify(context);
192         if(typeConstraintEvidenceParameters != null)
193             for(int i=0;i<typeConstraintEvidenceParameters.length;++i)
194                 typeConstraintEvidenceParameters[i] = typeConstraintEvidenceParameters[i].simplify(context);
195     }
196     
197     public String toString() {
198         StringBuilder b = new StringBuilder();
199         ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
200         visitor.visit(this);
201         return b.toString();
202     }
203
204     public void collectQueryEffects(THashSet<Type> effects) {
205         // TODO
206     }
207
208     public void collectEnforceEffects(THashSet<Type> effects) {
209         // TODO
210     }
211 }