--- a/progs/fun_llvm.scala Fri Oct 04 11:21:30 2019 +0100
+++ b/progs/fun_llvm.scala Mon Oct 07 20:53:25 2019 +0100
@@ -15,7 +15,7 @@
-object Compiler {
+//object Compiler {
import java.io._
import scala.util._
@@ -43,26 +43,6 @@
// copied from http://www.ceng.metu.edu.tr/courses/ceng444/link/jvm-cpm.html
//
-val library = """
-.class public XXX.XXX
-.super java/lang/Object
-
-.method public <init>()V
- aload_0
- invokenonvirtual java/lang/Object/<init>()V
- return
-.end method
-
-.method public static write(I)V
- .limit locals 1
- .limit stack 2
- getstatic java/lang/System/out Ljava/io/PrintStream;
- iload 0
- invokevirtual java/io/PrintStream/println(I)V
- return
-.end method
-
-"""
// for generating new labels
var counter = -1
@@ -72,6 +52,56 @@
x ++ "_" ++ counter.toString()
}
+
+
+// Abstract syntax trees for the Fun language
+abstract class KExp
+
+case class KVar(s: String) extends KExp
+case class KNum(i: Int) extends KExp
+case class KAop(o: String, x1: String, x2: String) extends KExp
+case class KIfeq(x1: String, x2: String, e1: KExp, e2: KExp) extends KExp
+case class KCall(o: String, vrs: List[String]) extends KExp
+case class KLet(x: String, e1: KExp, e2: KExp) extends KExp {
+ override def toString = s"let $x = $e1 in \n$e2"
+}
+
+def K(e: Exp) : KExp = e match {
+ case Var(s) => KVar(s)
+ case Num(i) => KNum(i)
+ case Aop(o, a1, a2) => {
+ val x1 = Fresh("tmp")
+ val x2 = Fresh("tmp")
+ KLet(x1, K(a1), KLet(x2, K(a2), KAop(o, x1, x2)))
+ }
+ case Call(name: String, args: List[Exp]) => {
+ val args_new = args.map{a => (Fresh("x"), K(a))}
+ def aux(as: List[(String, KExp)]) : KExp = as match {
+ case Nil => KCall(name, args_new.map(_._1))
+ case (x, a)::rest => KLet(x, a, aux(rest))
+ }
+ aux(args_new)
+ }
+
+}
+
+def Denest(e: KExp) : KExp = e match {
+ case KLet(xt, e1, e2) => {
+ def insert(e: KExp) : KExp = e match {
+ case KLet(yt, e3, e4) => KLet(yt, e3, insert(e4))
+ case e => KLet(xt, e, Denest(e2))
+ }
+ insert(Denest(e1))
+ }
+ case _ => e
+}
+
+val e = Aop("*", Aop("+", Num(1), Call("foo", List(Num(2), Num(3)))), Num(4))
+println(K(e))
+println(Denest(K(e)))
+
+
+
// convenient string interpolations
// for instructions, labels and methods
import scala.language.implicitConversions
@@ -86,15 +116,28 @@
type Env = Map[String, Int]
+
+
// compile expressions
-def compile_exp(a: Exp, env : Env) : String = a match {
- case Num(i) => i"ldc $i"
- case Var(s) => i"iload ${env(s)}"
- case Aop("+", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"iadd"
- case Aop("-", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"isub"
- case Aop("*", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"imul"
- case Aop("/", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"idiv"
- case Aop("%", a1, a2) => compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"irem"
+def compile_exp(a: Exp, env : Env, k: Int) : (String, Int) = a match {
+ case Num(i) => (i"%$k = add i32 0, i32 $i", k)
+ case Var(s) => (i"%$k = add i32 0, i32 %${env(s)}", k)
+ case Aop("+", a1, a2) => {
+ val (cs1, k1) = compile_exp(a1, env, k)
+ val (cs2, k2) = compile_exp(a2, env, k1 + 1)
+ (cs1 ++ cs2 ++ i"%${k2+1} = add i32 %$k1, i32 %$k2", k2 + 1)
+ }
+ case Aop("-", a1, a2) => {
+ val (cs1, k1) = compile_exp(a1, env, k)
+ val (cs2, k2) = compile_exp(a2, env, k1 + 1)
+ (cs1 ++ cs2 ++ i"%${k2+1} = sub i32 %$k1, i32 %$k2", k2 + 1)
+ }
+ case Aop("*", a1, a2) => {
+ val (cs1, k1) = compile_exp(a1, env, k)
+ val (cs2, k2) = compile_exp(a2, env, k1 + 1)
+ (cs1 ++ cs2 ++ i"%${k2+1} = mul i32 %$k1, i32 %$k2", k2 + 1)
+ }
+ /*
case If(b, a1, a2) => {
val if_else = Fresh("If_else")
val if_end = Fresh("If_end")
@@ -118,8 +161,13 @@
i"dup" ++
i"invokestatic XXX/XXX/write(I)V"
}
+ */
}
+val e = Aop("*", Aop("+", Num(2), Num(4)), Num(5))
+compile_exp(e, Map(), 1)._1.mkString
+
+
// compile boolean expressions
def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match {
case Bop("==", a1, a2) =>