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