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