]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DRelationAst.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / parsing / declarations / DRelationAst.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DRelationAst.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DRelationAst.java
new file mode 100644 (file)
index 0000000..6d3a3d1
--- /dev/null
@@ -0,0 +1,116 @@
+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);
+    }
+}