From 4001e83ed8a12e56e2130cca7a59087b14096d03 Mon Sep 17 00:00:00 2001
From: Philippe Suter <philippe.suter@gmail.com>
Date: Mon, 3 Dec 2012 19:46:06 +0100
Subject: [PATCH] First function compiles :)

---
 src/main/scala/leon/codegen/CodeGen.scala     |  14 ----
 .../scala/leon/codegen/CodeGenPhase.scala     |  43 ++++++++++++
 .../scala/leon/codegen/CodeGeneration.scala   |  61 ++++++++++++++++++
 .../leon/codegen/CompilationEnvironment.scala |  27 ++++++++
 .../leon/codegen/CompilationException.scala   |   6 ++
 .../codegen/purescala/Prog001.scala           |   4 +-
 unmanaged/32/cafebabe_2.9.2-1.2.jar           | Bin 495982 -> 496094 bytes
 7 files changed, 140 insertions(+), 15 deletions(-)
 delete mode 100644 src/main/scala/leon/codegen/CodeGen.scala
 create mode 100644 src/main/scala/leon/codegen/CodeGenPhase.scala
 create mode 100644 src/main/scala/leon/codegen/CodeGeneration.scala
 create mode 100644 src/main/scala/leon/codegen/CompilationEnvironment.scala
 create mode 100644 src/main/scala/leon/codegen/CompilationException.scala

diff --git a/src/main/scala/leon/codegen/CodeGen.scala b/src/main/scala/leon/codegen/CodeGen.scala
deleted file mode 100644
index 7f84a8976..000000000
--- a/src/main/scala/leon/codegen/CodeGen.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package leon
-package codegen
-
-import purescala.Common._
-import purescala.Definitions._
-
-object CodeGenPhase extends LeonPhase[Program,CompilationResult] {
-  val name = "CodeGen"
-  val description = "Compiles a Leon program into Java methods"
-
-  def run(ctx : LeonContext)(p : Program) : CompilationResult = {
-    CompilationResult(successful = true)
-  } 
-}
diff --git a/src/main/scala/leon/codegen/CodeGenPhase.scala b/src/main/scala/leon/codegen/CodeGenPhase.scala
new file mode 100644
index 000000000..5c6c0ef16
--- /dev/null
+++ b/src/main/scala/leon/codegen/CodeGenPhase.scala
@@ -0,0 +1,43 @@
+package leon
+package codegen
+
+import purescala.Common._
+import purescala.Definitions._
+
+import cafebabe._
+import cafebabe.ClassFileTypes.U2
+import cafebabe.Flags._
+
+object CodeGenPhase extends LeonPhase[Program,CompilationResult] {
+  val name = "CodeGen"
+  val description = "Compiles a Leon program into Java methods"
+
+  def run(ctx : LeonContext)(p : Program) : CompilationResult = {
+    import CodeGeneration._
+
+    implicit val env = CompilationEnvironment.fromProgram(p)
+
+    val cName = programToClassName(p)
+
+    val cf = new ClassFile(cName, None)
+    cf.setFlags(
+      (cf.getFlags | CLASS_ACC_PUBLIC | CLASS_ACC_FINAL).asInstanceOf[U2]
+    )
+
+    // This assumes that all functions of a given program get compiled
+    // as methods of a single class file.
+    for(funDef <- p.definedFunctions;
+        (_,mn) <- env.funDefToMethod(funDef)) {
+
+      val m = cf.addMethod(
+        typeToJVM(funDef.returnType),
+        mn,
+        funDef.args.map(a => typeToJVM(a.tpe)) : _*
+      )
+ 
+      CodeGeneration.compileFunDef(funDef, m.codeHandler)
+    }
+
+    CompilationResult(successful = true)
+  } 
+}
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
new file mode 100644
index 000000000..3fd57a438
--- /dev/null
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -0,0 +1,61 @@
+package leon
+package codegen
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Trees._
+import purescala.TypeTrees._
+
+import cafebabe._
+import cafebabe.ByteCodes._
+import cafebabe.AbstractByteCodes._
+
+object CodeGeneration {
+  def programToClassName(p : Program) : String = "Leon$CodeGen$" + p.mainObject.id.uniqueName
+
+  def typeToJVM(tpe : TypeTree)(implicit env : CompilationEnvironment) : String = tpe match {
+    case Int32Type => "I"
+    case BooleanType => "Z"
+    case _ => throw CompilationException("Unsupported type : " + tpe)
+  }
+
+  // Assumes the CodeHandler has never received any bytecode.
+  // Generates method body, and freezes the handler at the end.
+  def compileFunDef(funDef : FunDef, ch : CodeHandler)(implicit env : CompilationEnvironment) {
+    // TODO, change environment to include args.
+    mkExpr(funDef.getBody, ch)
+
+    funDef.returnType match {
+      case Int32Type | BooleanType =>
+        ch << IRETURN
+
+      case other =>
+        throw CompilationException("Unsupported return type : " + other)
+    }
+
+    ch.freeze
+  }
+
+  private def mkExpr(e : Expr, ch : CodeHandler)(implicit env : CompilationEnvironment) {
+    e match {
+      case IntLiteral(v) => ch << Ldc(v)
+      case BooleanLiteral(true) => ch << Ldc(1)
+      case BooleanLiteral(false) => ch << Ldc(0)
+
+      case Plus(l, r) =>
+        mkExpr(l, ch)
+        mkExpr(r, ch)
+        ch << IADD
+
+      case Minus(l, r) =>
+        mkExpr(l, ch)
+        mkExpr(r, ch)
+        ch << ISUB
+
+      case UMinus(e) =>
+        mkExpr(Minus(IntLiteral(0), e), ch)
+
+      case _ => throw CompilationException("Unsupported expr : " + e) 
+    }
+  }
+}
diff --git a/src/main/scala/leon/codegen/CompilationEnvironment.scala b/src/main/scala/leon/codegen/CompilationEnvironment.scala
new file mode 100644
index 000000000..1eb9514e1
--- /dev/null
+++ b/src/main/scala/leon/codegen/CompilationEnvironment.scala
@@ -0,0 +1,27 @@
+package leon
+package codegen
+
+import purescala.Common._
+import purescala.Definitions._
+
+abstract class CompilationEnvironment() {
+  // Should contain:
+  //   - a mapping of function defs to class + method name
+  //   - a mapping of class defs to class names
+  //   - a mapping of class fields to fields
+
+  def funDefToMethod(funDef : FunDef) : Option[(String,String)]
+}
+
+object CompilationEnvironment {
+  def fromProgram(p : Program) : CompilationEnvironment = {
+    val className = CodeGeneration.programToClassName(p)
+
+    val fs = p.definedFunctions.filter(_.hasImplementation)
+    val fPairs : Map[FunDef,String] = fs.map(fd => (fd -> fd.id.uniqueName)).toMap
+
+    new CompilationEnvironment {
+      def funDefToMethod(funDef : FunDef) = fPairs.get(funDef).map(n => (className, n))
+    }
+  }
+}
diff --git a/src/main/scala/leon/codegen/CompilationException.scala b/src/main/scala/leon/codegen/CompilationException.scala
new file mode 100644
index 000000000..236cc586e
--- /dev/null
+++ b/src/main/scala/leon/codegen/CompilationException.scala
@@ -0,0 +1,6 @@
+package leon
+package codegen
+
+case class CompilationException(msg : String) extends Exception {
+  override def getMessage = msg
+}
diff --git a/src/test/resources/regression/codegen/purescala/Prog001.scala b/src/test/resources/regression/codegen/purescala/Prog001.scala
index c0eb52647..c0edc779f 100644
--- a/src/test/resources/regression/codegen/purescala/Prog001.scala
+++ b/src/test/resources/regression/codegen/purescala/Prog001.scala
@@ -1,3 +1,5 @@
 object Prog001 {
-  def plus(x : Int, y : Int) : Int = x + y
+  def fortyTwo() = 42
+
+  // def plus(x : Int, y : Int) = x + y
 }
diff --git a/unmanaged/32/cafebabe_2.9.2-1.2.jar b/unmanaged/32/cafebabe_2.9.2-1.2.jar
index 57defc82adbd3db0baa2f7bfe33f08f1ee2f9e38..a7f91ed1b7e26933e0b0c657dbd2f240a423dc50 100644
GIT binary patch
delta 9454
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

delta 9337
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
KEX2;hzyJWd&5;%W

-- 
GitLab