]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java
(refs #7866) Better error location for the NPE in compilation
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / translation / CHRTranslation.java
index 6972eb8647a1e6646fd88956d6ddee9c9dc52121..107905ae32e5debae35bd01f93f7e857cddd1e8a 100644 (file)
@@ -5,24 +5,25 @@ import java.util.Arrays;
 
 import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
 import org.simantics.scl.compiler.elaboration.chr.CHRQuery;
-import org.simantics.scl.compiler.elaboration.chr.CHRRule;
 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
 import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.expressions.EApply;
 import org.simantics.scl.compiler.elaboration.expressions.EBinary;
+import org.simantics.scl.compiler.elaboration.expressions.ERecord;
 import org.simantics.scl.compiler.elaboration.expressions.EVar;
 import org.simantics.scl.compiler.elaboration.expressions.Expression;
-import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;
+import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
 import org.simantics.scl.compiler.environment.AmbiguousNameException;
 import org.simantics.scl.compiler.environment.Environments;
 import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
 
 public class CHRTranslation {
@@ -35,18 +36,27 @@ public class CHRTranslation {
     }
 
     private static CHRLiteral convertConstraint(boolean remove, boolean negated, Expression expression) {
-        ArrayList<Expression> parameters = new ArrayList<Expression>(4);
-        while(expression instanceof EApply) {
+        long location = expression.location;
+        Expression[] parameters;
+        FieldAssignment[] fields = null;
+        if(expression instanceof EApply) {
             EApply apply = (EApply)expression;
-            for(int i=apply.parameters.length-1;i>=0;--i)
-                parameters.add(apply.parameters[i]);
+            parameters = apply.parameters;
             expression = apply.function;
         }
-        EVar var = (EVar)expression;
-        Expression[] parametersArray = new Expression[parameters.size()];
-        for(int i=0,j=parametersArray.length-1;i<parametersArray.length;++i,--j)
-            parametersArray[i] = parameters.get(j);
-        return new CHRLiteral(expression.location, new UnresolvedCHRRelation(var.location, var.name), parametersArray, remove, negated);
+        else if(expression instanceof ERecord) {
+            ERecord record = (ERecord)expression;
+            parameters = null;
+            fields = record.fields;
+            expression = record.constructor;
+        }
+        else // if(expression instanceof EVar)
+            parameters = Expression.EMPTY_ARRAY;
+        EVar var = (EVar)expression; // this should succeed because of isConstraint test
+        CHRLiteral literal = new CHRLiteral(location, new UnresolvedCHRRelation(var.location, var.name),
+                parameters, remove, negated);
+        literal.fields = fields;
+        return literal;
     }
     
     private static CHRLiteral convertListQualifier(TranslationContext context, boolean isHead, ListQualifier qualifier) {
@@ -102,8 +112,10 @@ public class CHRTranslation {
     }
     
     private static boolean isConstraint(TranslationContext context, Expression expression) {
-        while(expression instanceof EApply)
+        if(expression instanceof EApply)
             expression = ((EApply)expression).function;
+        else if(expression instanceof ERecord)
+            expression = ((ERecord)expression).constructor;
         if(!(expression instanceof EVar))
             return false;
         String name = ((EVar)expression).name;
@@ -116,27 +128,35 @@ public class CHRTranslation {
         }
     }
 
-    public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) {
-        ArrayList<CHRLiteral> head = new ArrayList<CHRLiteral>(statement.head.length);
-        for(ListQualifier qualifier : statement.head) {
-            CHRLiteral literal = convertListQualifier(context, true, qualifier);
-            if(literal != null)
-                head.add(literal);
-        }
-        ArrayList<CHRLiteral> body = new ArrayList<CHRLiteral>(statement.body.length);
-        for(ListQualifier qualifier : statement.body) {
-            CHRLiteral literal = convertListQualifier(context, false, qualifier);
+    public static CHRQuery convertCHRQuery(TranslationContext context, boolean isHead, ListQualifier[] lqs) {
+        long location = Locations.NO_LOCATION;
+        ArrayList<CHRLiteral> query = new ArrayList<CHRLiteral>(lqs.length);
+        for(ListQualifier qualifier : lqs) {
+            location = Locations.combine(location, qualifier.location);
+            CHRLiteral literal = convertListQualifier(context, isHead, qualifier);
             if(literal != null)
-                body.add(literal);
+                query.add(literal);
         }
+        return new CHRQuery(location, query.toArray(new CHRLiteral[query.size()]));
+    }
+    
+    /*public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) {
         return new CHRRule(statement.location,
-                new CHRQuery(head.toArray(new CHRLiteral[head.size()])),
-                new CHRQuery(body.toArray(new CHRLiteral[body.size()])),
+                convertCHRQuery(context, true, statement.head),
+                convertCHRQuery(context, false, statement.body),
                 null);
-    }
+    }*/
 
     public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) {
-        return new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));
+        CHRConstraint constraint = new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));
+        for(DAnnotationAst annotation : statement.annotations)
+            applyConstraintAnnotation(context, constraint, annotation);
+        constraint.fieldNames = statement.fieldNames;
+        return constraint;
+    }
+
+    private static void applyConstraintAnnotation(TranslationContext context, CHRConstraint constraint, DAnnotationAst annotation) {
+        context.getErrorLog().log(annotation.location, "Invalid constraint annotation");
     }
     
 }