--- /dev/null
+package org.simantics.scl.compiler.internal.parsing.declarations;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
+import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EVar;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.query.QConjunction;
+import org.simantics.scl.compiler.elaboration.query.Query;
+import org.simantics.scl.compiler.elaboration.relations.ConcreteRelation;
+
+public class DRelationAst extends DeclarationAst {
+ public final Expression lhs;
+ public final Object[] queries;
+ public DDocumentationAst documentation;
+
+ public DRelationAst(Expression lhs, Object[] queries) {
+ this.lhs = lhs;
+ this.queries = queries;
+ }
+
+ @Override
+ public void toString(int indentation, StringBuilder b) {
+ for(int i=0;i<indentation;++i) b.append(" ");
+ b.append(lhs);
+ b.append(" :-");
+ for(Object query : queries) {
+ b.append('\n');
+ for(int i=0;i<=indentation;++i) b.append(" ");
+ System.out.println(query);
+ }
+ }
+
+ public void toString(StringBuilder b) {
+ toString(0, b);
+ }
+
+ public void setLocationDeep(long der) {
+ lhs.setLocationDeep(der);
+ for(Object query : queries)
+ if(query instanceof Query)
+ ((Query)query).setLocationDeep(der);
+ }
+
+ public void translateTo(TranslationContext context,
+ ConcreteRelation relation) {
+
+ // Parameters
+ EApply apply = (EApply)lhs;
+ Expression[] applyParameters = apply.getParameters();
+ relation.parameters = new Variable[applyParameters.length];
+ for(int i=0;i<applyParameters.length;++i) {
+ EVar var = (EVar)applyParameters[i];
+ Variable variable = context.newVariable(var.name);
+ relation.parameters[i] = variable;
+ }
+
+ // Sections
+ ArrayList<Query> ql = new ArrayList<Query>();
+ DAnnotationAst annotation = null;
+ for(Object statement : queries) {
+ if(statement instanceof DAnnotationAst) {
+ if(!ql.isEmpty()) {
+ translateSection(context, annotation, ql, relation);
+ ql.clear();
+ }
+ annotation = (DAnnotationAst)statement;
+ }
+ else
+ ql.add((Query)statement);
+ }
+ if(!ql.isEmpty())
+ translateSection(context, annotation, ql, relation);
+ }
+
+ private void translateSection(TranslationContext context, DAnnotationAst annotation, ArrayList<Query> queries, ConcreteRelation relation) {
+ Query query = queries.size() == 1 ? queries.get(0) : new QConjunction(queries);
+ String sectionName = annotation.id.text.substring(1);
+ if(sectionName.equals("enforce")) {
+ relation.enforceSection = query.resolve(context);
+ if(annotation.parameters.length > 0) {
+ relation.phase = Integer.parseInt(((EIntegerLiteral)annotation.parameters[0]).getValue());
+ }
+ return;
+ }
+
+ int pattern = 0;
+ for(int i=0;i<sectionName.length();++i) {
+ char c = sectionName.charAt(i);
+ if(c == 'b')
+ pattern |= 1 << i;
+ else if(c != 'f') {
+ context.getErrorLog().log(annotation.location, "Invalid section name '" + sectionName + "'.");
+ return;
+ }
+ }
+ if(relation.getSection(pattern) != null)
+ context.getErrorLog().log(annotation.location, "Query section is redundant because the previous sections cover it.");
+ double selectivity = 10.0;
+ if(annotation.parameters.length > 0) {
+ Expression selExp = annotation.parameters[0];
+ if(selExp instanceof ERealLiteral)
+ selectivity = Double.parseDouble(((ERealLiteral)selExp).getValue());
+ else
+ selectivity = Integer.parseInt(((EIntegerLiteral)selExp).getValue());
+ }
+ context.pushExistentialFrame();
+ Query resolvedQuery = query.resolve(context);
+ Variable[] existentials = context.popExistentialFrame();
+ relation.addSection(pattern, selectivity, existentials, resolvedQuery);
+ }
+}