From 3e223b3de1d911981f45869d30a2bef6ed9f0256 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9gis=20Blanc?= <regwblanc@gmail.com>
Date: Mon, 27 Jan 2014 16:47:21 +0100
Subject: [PATCH] implement missing ArrayUpdated in codegen

---
 .../scala/leon/codegen/CodeGeneration.scala   | 24 +++++++++++++++++++
 .../purescala/valid/ArrayUpdated.scala        | 11 +++++++++
 .../test/evaluators/EvaluatorsTests.scala     | 10 +++++++-
 3 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 src/test/resources/regression/verification/purescala/valid/ArrayUpdated.scala

diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index 1a846991f..ffb30cbb2 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -346,6 +346,30 @@ trait CodeGeneration {
           case _ => AALOAD
         })
 
+      case au @ ArrayUpdated(a, i, v) =>
+        mkExpr(a, ch)
+        ch << DUP
+        ch << ARRAYLENGTH
+        val storeInstr = a.getType match {
+          case ArrayType(Int32Type) => ch << NewArray.primitive("T_INT"); IASTORE
+          case ArrayType(BooleanType) => ch << NewArray.primitive("T_BOOLEAN"); BASTORE
+          case ArrayType(other) => ch << NewArray(typeToJVM(other)); AASTORE
+          case other => throw CompilationException("Cannot compile finite array expression whose type is %s.".format(other))
+        } 
+        //srcArrary and targetArray is on the stack
+        ch << DUP_X1 //insert targetArray under srcArray
+        ch << Ldc(0) << SWAP //srcArray, 0, targetArray
+        ch << DUP << ARRAYLENGTH //targetArray, length on stack
+        ch << Ldc(0) << SWAP //final arguments: src, 0, target, 0, length
+        ch << InvokeStatic("java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V")
+
+        //targetArray remains on the stack
+        ch << DUP
+        mkExpr(i, ch)
+        mkExpr(v, ch)
+        ch << storeInstr
+        //returns targetArray
+
       case a @ FiniteArray(es) =>
         ch << Ldc(es.size)
         val storeInstr = a.getType match {
diff --git a/src/test/resources/regression/verification/purescala/valid/ArrayUpdated.scala b/src/test/resources/regression/verification/purescala/valid/ArrayUpdated.scala
new file mode 100644
index 000000000..67d4af25d
--- /dev/null
+++ b/src/test/resources/regression/verification/purescala/valid/ArrayUpdated.scala
@@ -0,0 +1,11 @@
+import leon.Utils._
+
+object Test {
+
+  def test(a: Array[Int]): Int = {
+    require(a.length > 0)
+    val a2 = a.updated(0, 2)
+    a2(0)
+  } ensuring(res => res == 2)
+
+}
diff --git a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
index 6967f38de..51894fc06 100644
--- a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
+++ b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
@@ -377,7 +377,12 @@ class EvaluatorsTests extends LeonTestSuite {
     val p = """|object Program {
                |  def boolArrayRead(bools : Array[Boolean], index : Int) : Boolean = bools(index)
                |
-               |  def intArrayRead(bools : Array[Int], index : Int) : Int = bools(index)
+               |  def intArrayRead(ints : Array[Int], index : Int) : Int = ints(index)
+               |
+               |  def intArrayUpdate(ints : Array[Int], index : Int, value: Int) : Int = {
+               |    val na = ints.updated(index, value)
+               |    na(index)
+               |  }
                |}
                |""".stripMargin
 
@@ -394,6 +399,9 @@ class EvaluatorsTests extends LeonTestSuite {
       checkComp(e, mkCall("intArrayRead", ia, IL(1)), IL(42))
       checkComp(e, ArrayLength(ia), IL(3))
 
+      checkComp(e, mkCall("intArrayUpdate", ia, IL(0), IL(13)), IL(13))
+      checkComp(e, mkCall("intArrayUpdate", ia, IL(1), IL(17)), IL(17))
+
       checkError(e, mkCall("boolArrayRead", ba, IL(2)))
     }
   }
-- 
GitLab