(refs #7866) Better error location for the NPE in compilation 11/1711/2
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 12 Apr 2018 07:04:44 +0000 (10:04 +0300)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 12 Apr 2018 07:13:54 +0000 (10:13 +0300)
Change-Id: I3027ac4cd1061edefed6b46ddf1c79773d03caca

bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/exceptions/InternalCompilerError.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstQuery.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR14.scl [new file with mode: 0644]

index 71b6193015b1b4aafb8d9e0cc226131a0f7f928b..1c2709665765562067f185a96bff6ece7243b17a 100644 (file)
@@ -36,5 +36,16 @@ public class InternalCompilerError extends RuntimeException {
         super(cause);
         this.location = location;
     }
+    
+    public static InternalCompilerError injectLocation(long location, Throwable cause) {
+        if(cause instanceof InternalCompilerError) {
+            InternalCompilerError e = (InternalCompilerError)cause;
+            if(e.location == Locations.NO_LOCATION)
+                e.location = location;
+            return e;
+        }
+        else
+            return new InternalCompilerError(location, cause);
+    }
    
 }
index 2d97ab51819e4d271cea111e42050878da58c6a2..7bee6eae06b08a481652df67e5009d76629dfde4 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.scl.compiler.elaboration.chr;
 
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
 import org.simantics.scl.compiler.elaboration.chr.plan.PostCommitOp;
 import org.simantics.scl.compiler.elaboration.chr.plan.PreCommitOp;
 import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
@@ -20,8 +21,9 @@ import gnu.trove.set.hash.TIntHashSet;
 public class CHRQuery extends Symbol {
     public CHRLiteral[] literals;
 
-    public CHRQuery(CHRLiteral[] literals) {
+    public CHRQuery(long location, CHRLiteral[] literals) {
         this.literals = literals;
+        this.location = location;
     }
 
     public void resolve(TranslationContext context) {
@@ -48,17 +50,21 @@ public class CHRQuery extends Symbol {
     }
     
     public boolean createQueryPlan(QueryPlanningContext context, Expression inputFact, int activeLiteralId, CHRConstraint initConstraint) {
-        for(int i=0;i<literals.length;++i) {
-            CHRLiteral literal = literals[i];
-            if(i == activeLiteralId)
-                context.activate(literal, inputFact, i);
-            else
-                context.add(literal, i);
+        try {
+            for(int i=0;i<literals.length;++i) {
+                CHRLiteral literal = literals[i];
+                if(i == activeLiteralId)
+                    context.activate(literal, inputFact, i);
+                else
+                    context.add(literal, i);
+            }
+            if(activeLiteralId == -1 && inputFact != null) {
+                context.addInitFact(initConstraint, inputFact);
+            }  
+            return context.createQueryPlan();
+        } catch(Exception e) {
+            throw InternalCompilerError.injectLocation(location, e);
         }
-        if(activeLiteralId == -1 && inputFact != null) {
-            context.addInitFact(initConstraint, inputFact);
-        }      
-        return context.createQueryPlan();
     }
     
     public void simplify(SimplificationContext context) {
@@ -84,6 +90,6 @@ public class CHRQuery extends Symbol {
         CHRLiteral[] newLiterals = new CHRLiteral[literals.length];
         for(int i=0;i<literals.length;++i)
             newLiterals[i] = literals[i].replace(context);
-        return new CHRQuery(newLiterals);
+        return new CHRQuery(location, newLiterals);
     }
 }
index e655c78e762c6694e907262988929a8ff9f2d691..d77562ad9868778fb5559089145f19d9be67a923 100644 (file)
@@ -11,7 +11,7 @@ public abstract class CHRAstQuery extends Symbol {
     public CHRQuery translate(TranslationContext context, CHRQueryTranslationMode mode) {
         ArrayList<CHRLiteral> literals = new ArrayList<CHRLiteral>(); 
         translate(context, mode, literals);
-        return new CHRQuery(literals.toArray(new CHRLiteral[literals.size()]));
+        return new CHRQuery(location, literals.toArray(new CHRLiteral[literals.size()]));
     }
 
     protected abstract void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals);
index 260927b74c6c3659e12997035a80cfd5c5fb167a..107905ae32e5debae35bd01f93f7e857cddd1e8a 100644 (file)
@@ -129,13 +129,15 @@ public class CHRTranslation {
     }
 
     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)
                 query.add(literal);
         }
-        return new CHRQuery(query.toArray(new CHRLiteral[query.size()]));
+        return new CHRQuery(location, query.toArray(new CHRLiteral[query.size()]));
     }
     
     /*public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) {
index 7b693aa62212a6bf42bfb776d646c19ea748bbd3..3eb098933c1f6e2b5975920fb20c663c119a31d1 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.scl.compiler.tests;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.simantics.scl.compiler.top.ValueNotFound;
 
@@ -36,6 +37,7 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void CHR11() { test(); }
     @Test public void CHR12() { test(); }
     @Test public void CHR13() { test(); }
+    @Ignore @Test public void CHR14() { test(); }
     @Test public void CHRSelect1() { test(); }
     @Test public void CHRSelect2() { test(); }
     @Test public void CHRSelect3() { test(); }
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR14.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR14.scl
new file mode 100644 (file)
index 0000000..f9f1779
--- /dev/null
@@ -0,0 +1,16 @@
+module { export = [main], features = [chr] }
+import "Prelude"
+
+ruleset A where
+    constraint AR Integer Integer
+    
+pcombine :: A -> <Proc> ()
+pcombine a = ()
+  where
+    include A a
+
+    -AR ?a ?b => True
+
+main = ()
+--
+()
\ No newline at end of file