1 package org.simantics.scl.compiler.elaboration.chr;
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.ReplaceContext;
9 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
10 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
11 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext.ExistentialFrame;
12 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
13 import org.simantics.scl.compiler.elaboration.expressions.ERecord;
14 import org.simantics.scl.compiler.elaboration.expressions.Expression;
15 import org.simantics.scl.compiler.elaboration.expressions.Variable;
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;
26 import gnu.trove.map.hash.TObjectIntHashMap;
27 import gnu.trove.set.hash.TIntHashSet;
29 public class CHRLiteral extends Symbol {
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;
40 public CHRLiteral(long location, CHRRelation relation, Expression[] parameters, boolean killAfterMatch, boolean negated) {
41 this.location = location;
42 this.relation = relation;
43 this.parameters = parameters;
44 this.killAfterMatch = killAfterMatch;
45 this.negated = negated;
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);
54 if(parameters != null) {
55 for(int i=0;i<parameters.length;++i)
56 parameters[i] = parameters[i].resolve(context);
58 if(relation instanceof UnresolvedCHRRelation) {
59 UnresolvedCHRRelation unresolved = (UnresolvedCHRRelation)relation;
60 CHRConstraint constraint = context.resolveCHRConstraint(unresolved.name);
61 if(constraint != null) {
62 relation = constraint;
66 SCLRelation sclRelation = context.resolveRelation(unresolved.location, unresolved.name);
67 if(sclRelation != null)
68 relation = new ExternalCHRRelation(sclRelation);
70 if(unresolved.name.contains(".")) {
71 context.getErrorLog().log(unresolved.location, "Couldn't resolve relation " + unresolved.name + ".");
74 if(parameters == null) {
75 context.getErrorLog().log(location, "Relation must be declared if record syntax is used.");
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;
86 //context.getErrorLog().log(unresolved.location, "Couldn't resolve constraint " + unresolved.name + ".");
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.");
96 parameters = ERecord.translateFieldsToFunctionParameters(context, fields, fieldNames);
97 if(parameters == null)
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.");
106 parameters[i] = frame.createBlank(location);
109 parameters[i] = parameters[i].resolve(context);
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;
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;
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");
136 for(int i=0;i<parameters.length;++i)
137 parameters[i] = parameters[i].checkType(context, parameterTypes[i]);
139 typeConstraintEvidenceParameters = context.addConstraints(Types.replace(relation.getTypeConstraints(), typeVariables, typeParameters));
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);
151 public void setLocationDeep(long loc) {
152 if(location == Locations.NO_LOCATION) {
154 for(Expression parameter : parameters)
155 parameter.setLocationDeep(loc);
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);
167 public String toString() {
168 StringBuilder b = new StringBuilder();
169 ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
174 public CHRLiteral replace(ReplaceContext context) {
175 CHRLiteral copy = new CHRLiteral(location, relation, context.replace(parameters), killAfterMatch, negated);
176 for(int i=0;i<parameters.length;++i)
177 copy.parameters[i] = copy.parameters[i].replace(context);
178 copy.passive = passive;
179 copy.typeConstraintEvidenceParameters = context.replace(typeConstraintEvidenceParameters);
180 copy.typeParameters = context.replace(typeParameters);
181 copy.fields = context.replace(fields);