1 package org.simantics.scl.compiler.elaboration.chr.ast;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collections;
7 import org.simantics.scl.compiler.common.names.Name;
8 import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
9 import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
10 import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;
11 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
12 import org.simantics.scl.compiler.elaboration.expressions.EApply;
13 import org.simantics.scl.compiler.elaboration.expressions.EBinary;
14 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
15 import org.simantics.scl.compiler.elaboration.expressions.ERecord;
16 import org.simantics.scl.compiler.elaboration.expressions.EVar;
17 import org.simantics.scl.compiler.elaboration.expressions.Expression;
18 import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
19 import org.simantics.scl.compiler.environment.AmbiguousNameException;
20 import org.simantics.scl.compiler.environment.Environments;
21 import org.simantics.scl.compiler.errors.Locations;
22 import org.simantics.scl.compiler.types.Types;
24 public class CHRAstAtom extends CHRAstQuery {
25 public Expression expression;
26 public boolean remove;
28 public CHRAstAtom(Expression expression, boolean remove) {
29 this.expression = expression;
34 public void accept(CHRAstQueryVisitor visitor) {
38 public static CHRAstQuery atom(Expression expression) {
39 boolean remove = false;
40 if(expression instanceof EVar) {
41 EVar var = (EVar)expression;
42 if(var.name.equals("True")) {
43 CHRAstConjunction query = new CHRAstConjunction(Collections.emptyList());
44 query.location = expression.location;
48 else if(expression instanceof EBinary) {
49 EBinary binary = (EBinary)expression;
50 if(binary.negation != null && binary.rights.isEmpty()) {
52 expression = binary.left;
54 // If query is marked for removal, it must be an atom
56 else if(expression instanceof EApply) {
57 EApply apply = (EApply)expression;
58 if(apply.function instanceof EVar && ((EVar)apply.function).name.equals("not")) {
59 Expression subExpression;
60 if(apply.parameters.length == 1)
61 subExpression = apply.parameters[0];
63 subExpression = new EApply(
64 Locations.combine(apply.parameters[0].location, apply.parameters[apply.parameters.length-1].location),
66 Arrays.copyOfRange(apply.parameters, 1, apply.parameters.length));
67 CHRAstNegation query = new CHRAstNegation(atom(subExpression));
68 query.location = expression.location;
71 else if(apply.function instanceof EConstant) {
72 Name valueName = ((EConstant)apply.function).getValue().getName();
73 if(valueName.module.equals(Types.BUILTIN) && valueName.name.startsWith("(")) {
74 CHRAstQuery[] conjuncts = new CHRAstQuery[apply.parameters.length];
75 for(int i=0;i<conjuncts.length;++i)
76 conjuncts[i] = atom(apply.parameters[i]);
77 CHRAstQuery query = CHRAstConjunction.conjunction(conjuncts);
78 query.location = expression.location;
83 CHRAstAtom query = new CHRAstAtom(expression, remove);
84 query.location = expression.location;
89 protected void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals) {
90 if(isConstraint(context, expression)) {
91 literals.add(convertConstraint(remove, expression));
95 context.getErrorLog().log(location, "Only constraints can be marked for removal");
97 literals.add(convertExpression(mode, expression));
101 private static boolean isConstraint(TranslationContext context, Expression expression) {
102 if(expression instanceof EApply)
103 expression = ((EApply)expression).function;
104 else if(expression instanceof ERecord)
105 expression = ((ERecord)expression).constructor;
106 if(!(expression instanceof EVar))
108 String name = ((EVar)expression).name;
109 if(TranslationContext.isConstructorName(name))
112 return Environments.getRelation(context.getEnvironment(), name) != null;
113 } catch (AmbiguousNameException e) {
118 private static CHRLiteral convertExpression(CHRQueryTranslationMode mode, Expression expression) {
120 return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);
122 return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);
125 private static CHRLiteral convertConstraint(boolean remove, Expression expression) {
126 long location = expression.location;
127 Expression[] parameters;
128 FieldAssignment[] fields = null;
129 if(expression instanceof EApply) {
130 EApply apply = (EApply)expression;
131 parameters = apply.parameters;
132 expression = apply.function;
134 else if(expression instanceof ERecord) {
135 ERecord record = (ERecord)expression;
137 fields = record.fields;
138 expression = record.constructor;
140 else // if(expression instanceof EVar)
141 parameters = Expression.EMPTY_ARRAY;
142 EVar var = (EVar)expression; // this should succeed because of isConstraint test
143 CHRLiteral literal = new CHRLiteral(location, new UnresolvedCHRRelation(var.location, var.name),
144 parameters, remove, false);
145 literal.fields = fields;