From a9c9719f34457971bb161ae97154bd29374a8556 Mon Sep 17 00:00:00 2001
From: Etienne Kneuss <etienne.kneuss@epfl.ch>
Date: Mon, 9 Mar 2015 15:02:29 +0100
Subject: [PATCH] Block positions, explicit errors from xlang features.

---
 src/main/scala/leon/utils/Positions.scala     | 27 +++++++++++++++
 .../leon/xlang/NoXLangFeaturesChecking.scala  | 33 +++++++++++++++----
 src/main/scala/leon/xlang/Trees.scala         |  4 +++
 3 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/src/main/scala/leon/utils/Positions.scala b/src/main/scala/leon/utils/Positions.scala
index c38d1ab53..44065df86 100644
--- a/src/main/scala/leon/utils/Positions.scala
+++ b/src/main/scala/leon/utils/Positions.scala
@@ -34,6 +34,33 @@ abstract class Position extends Ordered[Position] {
   def isDefined: Boolean
 }
 
+object Position {
+  def between(a: Position, b: Position): Position = {
+    if (a.file == b.file) {
+      if (a.line == b.line && a.col == b.col) {
+        a
+      } else {
+        val (from, to) = if (a < b) (a, b) else (b, a)
+
+        (from, to) match {
+          case (p1: OffsetPosition, p2: OffsetPosition) =>
+            RangePosition(p1.line, p1.col, p1.point, p2.line, p2.col, p2.point, p1.file)
+          case (p1: RangePosition, p2: RangePosition) =>
+            RangePosition(p1.lineFrom, p1.colFrom, p1.pointFrom, p2.lineTo, p2.colTo, p2.pointTo, p1.file)
+          case (p1: OffsetPosition, p2: RangePosition) =>
+            RangePosition(p1.line, p1.col, p1.point, p2.lineTo, p2.colTo, p2.pointTo, p1.file)
+          case (p1: RangePosition, p2: OffsetPosition) =>
+            RangePosition(p1.lineFrom, p1.colFrom, p1.pointFrom, p2.line, p2.col, p2.point, p1.file)
+          case (a,b) =>
+            a
+        }
+      }
+    } else {
+      a
+    }
+  }
+}
+
 abstract class DefinedPosition extends Position {
   override def toString = line+":"+col
   override def fullString = file.getPath+":"+line+":"+col
diff --git a/src/main/scala/leon/xlang/NoXLangFeaturesChecking.scala b/src/main/scala/leon/xlang/NoXLangFeaturesChecking.scala
index 05b9c2553..0c6f11a8d 100644
--- a/src/main/scala/leon/xlang/NoXLangFeaturesChecking.scala
+++ b/src/main/scala/leon/xlang/NoXLangFeaturesChecking.scala
@@ -6,11 +6,13 @@ package xlang
 import purescala.Common._
 import purescala.TypeTrees._
 import purescala.Trees._
+import purescala.TreeOps.collect
 import purescala.Definitions._
 import purescala.Constructors._
 
+import utils.Position
+
 import xlang.Trees._
-import xlang.TreeOps.isXLang
 
 object NoXLangFeaturesChecking extends UnitPhase[Program] {
 
@@ -18,11 +20,30 @@ object NoXLangFeaturesChecking extends UnitPhase[Program] {
   val description = "Ensure and enforce that no xlang features are used"
 
   override def apply(ctx: LeonContext, pgm: Program): Unit = {
-    pgm.definedFunctions.foreach(fd => {
-      if(isXLang(fd.fullBody)) {
-        ctx.reporter.fatalError(fd.fullBody.getPos, "Expr is using xlang features")
-      }
-    })
+    val errors = pgm.definedFunctions.flatMap(fd => collect[(Position, String)]{
+      case (e: Block) =>
+        Set((e.getPos, "Block expressions require xlang desugaring"))
+      case (e: Assignment) =>
+        Set((e.getPos, "Mutating variables requires xlang desugaring"))
+      case (e: While) =>
+        Set((e.getPos, "While expressions require xlang desugaring"))
+      case (e: Epsilon) =>
+        Set((e.getPos, "Usage of epsilons requires xlang desugaring"))
+      case (e: EpsilonVariable) =>
+        Set((e.getPos, "Usage of epsilons requires xlang desugaring"))
+      case (e: LetVar) =>
+        Set((e.getPos, "Mutable variables (e.g. 'var x' instead of 'val x') require xlang desugaring"))
+      case (e: Waypoint) =>
+        Set((e.getPos, "Usage of waypoints requires xlang desugaring"))
+      case (e: ArrayUpdate) =>
+        Set((e.getPos, "In-place updates of arrays require xlang desugaring"))
+      case _ =>
+        Set()
+    }(fd.fullBody))
+
+    for ((p, msg) <- errors) {
+      ctx.reporter.error(p, msg)
+    }
   }
 
 }
diff --git a/src/main/scala/leon/xlang/Trees.scala b/src/main/scala/leon/xlang/Trees.scala
index 2740b3d5c..6c3864204 100644
--- a/src/main/scala/leon/xlang/Trees.scala
+++ b/src/main/scala/leon/xlang/Trees.scala
@@ -24,6 +24,10 @@ object Trees {
       Some((exprs :+ last, exprs => Block(exprs.init, exprs.last)))
     }
 
+    override def getPos = {
+      Position.between(exprs.head.getPos, last.getPos)
+    }
+
     def printWith(implicit pctx: PrinterContext) {
       p"""|{
           |  ${nary(exprs :+ last, "\n")}
-- 
GitLab