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, boolean isHead, ArrayList<CHRLiteral> literals) {
91 isConstraint(context, expression) ?
92 convertConstraint(remove, expression) :
93 convertExpression(isHead, expression));
96 private static boolean isConstraint(TranslationContext context, Expression expression) {
97 if(expression instanceof EApply)
98 expression = ((EApply)expression).function;
99 else if(expression instanceof ERecord)
100 expression = ((ERecord)expression).constructor;
101 if(!(expression instanceof EVar))
103 String name = ((EVar)expression).name;
104 if(TranslationContext.isConstructorName(name))
107 return Environments.getRelation(context.getEnvironment(), name) != null;
108 } catch (AmbiguousNameException e) {
113 private static CHRLiteral convertExpression(boolean isHead, Expression expression) {
115 return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);
117 return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);
120 private static CHRLiteral convertConstraint(boolean remove, Expression expression) {
121 long location = expression.location;
122 Expression[] parameters;
123 FieldAssignment[] fields = null;
124 if(expression instanceof EApply) {
125 EApply apply = (EApply)expression;
126 parameters = apply.parameters;
127 expression = apply.function;
129 else if(expression instanceof ERecord) {
130 ERecord record = (ERecord)expression;
132 fields = record.fields;
133 expression = record.constructor;
135 else // if(expression instanceof EVar)
136 parameters = Expression.EMPTY_ARRAY;
137 EVar var = (EVar)expression; // this should succeed because of isConstraint test
138 CHRLiteral literal = new CHRLiteral(location, new UnresolvedCHRRelation(var.location, var.name),
139 parameters, remove, false);
140 literal.fields = fields;