updated
authorChristian Urban <urbanc@in.tum.de>
Tue, 08 Oct 2019 21:12:52 +0100
changeset 649 e83afb44f276
parent 648 36379b038438
child 650 3031e3379ea3
updated
coursework/cw05.pdf
coursework/cw05.tex
hws/hw09.tex
progs/fun.scala
progs/fun_llvm.scala
Binary file coursework/cw05.pdf has changed
--- a/coursework/cw05.tex	Mon Oct 07 20:53:25 2019 +0100
+++ b/coursework/cw05.tex	Tue Oct 08 21:12:52 2019 +0100
@@ -8,10 +8,10 @@
 \section*{Coursework (Strand 2)}
 
 \noindent This coursework is worth 20\% and is due on 13 December at
-18:00. You are asked to prove the correctness of the regular
-expression matcher from the lectures using the Isabelle theorem
-prover. You need to submit a theory file containing this proof. The
-Isabelle theorem prover is available from
+18:00. You are asked to prove the correctness of the regular expression
+matcher from the lectures using the Isabelle theorem prover. You need to
+submit a theory file containing this proof and also a document
+describing your proof. The Isabelle theorem prover is available from
 
 \begin{center}
 \url{http://isabelle.in.tum.de}
--- a/hws/hw09.tex	Mon Oct 07 20:53:25 2019 +0100
+++ b/hws/hw09.tex	Tue Oct 08 21:12:52 2019 +0100
@@ -46,6 +46,7 @@
 
 
 \item What does the following LLVM function calculate. Give the
+  expression 
 
 \begin{lstlisting}[language=LLVM,numbers=none]  
 define i32 @foo(i32 %a, i32 %b)  {
--- a/progs/fun.scala	Mon Oct 07 20:53:25 2019 +0100
+++ b/progs/fun.scala	Tue Oct 08 21:12:52 2019 +0100
@@ -212,8 +212,8 @@
 //compile_and_run("defs")
 
 
-def main(args: Array[String]) = 
+def main(args: Array[String]) : Unit = 
    compile_and_run(args(0))
 
 
-}
\ No newline at end of file
+}
--- a/progs/fun_llvm.scala	Mon Oct 07 20:53:25 2019 +0100
+++ b/progs/fun_llvm.scala	Tue Oct 08 21:12:52 2019 +0100
@@ -15,7 +15,7 @@
 
 
 
-//object Compiler {
+object Compiler {
 
 import java.io._  
 import scala.util._
@@ -60,7 +60,10 @@
 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 KIfeq(x1: String, x2: String, e1: KExp, e2: KExp) extends KExp {
+  override def toString = s"KIf $x1 == $x2 \nIF\n$e1\nELSE\n$e2"
+
+}
 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" 
@@ -75,14 +78,18 @@
     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))}
+    val args_new = args.map{a => (Fresh("tmp"), 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)
   }
-  
+  case If(Bop("==", b1, b2), e1, e2) => {
+    val x1 = Fresh("tmp")
+    val x2 = Fresh("tmp") 
+    KLet(x1, K(b1), KLet(x2, K(b2), KIfeq(x1, x2, K(e1), K(e2))))
+  }
 }
 
 def Denest(e: KExp) : KExp = e match {
@@ -93,12 +100,16 @@
     }
     insert(Denest(e1))  
   }
+  case KIfeq(x1, x2, e1, e2) =>  KIfeq(x1, x2, Denest(e1), Denest(e2))
   case _ => e
 }
 
-val e = Aop("*", Aop("+", Num(1), Call("foo", List(Num(2), Num(3)))), Num(4))
+
+val e = Aop("*", Aop("+", Num(1), Call("foo", List(Var("a"), Num(3)))), Num(4))
 println(K(e))
+println()
 println(Denest(K(e)))
+println()
 
 
 
@@ -118,36 +129,33 @@
 
 
 
-// compile expressions
-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)
+// compile K expressions
+def compile_exp(a: KExp) : String = a match {
+  case KNum(i) => s"?$i?"
+  case KVar(s) => s"?$s?"
+  case KAop("+", x1, x2) => s"add i32 %$x1, i32 %$x2"
+  case KAop("-", x1, x2) => s"sub i32 %$x1, i32 %$x2"
+  case KAop("*", x1, x2) => s"mul i32 %$x1, i32 %$x2"
+  case KLet(x: String, e1: KExp, e2: KExp) => {
+    val is1 = compile_exp(e1)
+    val is2 = compile_exp(e2)
+    i"%$x = $is1" ++ is2
   }
-  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 KIfeq(x1, x2, a1, a2) => {
+    val if_br = Fresh("if_br")
+    val else_br = Fresh("else_br")
+    val x = Fresh("tmp")
+    i"%$x = icmp eq i32 %$x1, i32 %$x2" ++
+    i"br i1 %$x, label %$if_br, label %$else_br" ++
+    l"\n$if_br" ++
+    compile_exp(a1) ++
+    l"\n$else_br" ++ 
+    compile_exp(a2)
   }
-  /*
-  case If(b, a1, a2) => {
-    val if_else = Fresh("If_else")
-    val if_end = Fresh("If_end")
-    compile_bexp(b, env, if_else) ++
-    compile_exp(a1, env) ++
-    i"goto $if_end" ++
-    l"$if_else" ++
-    compile_exp(a2, env) ++
-    l"$if_end"
+  case KCall(x1, args) => {
+    s"Call $x1 ($args)"
   }
+/*
   case Call(name, args) => {
     val is = "I" * args.length
     args.map(a => compile_exp(a, env)).mkString ++
@@ -164,10 +172,7 @@
   */
 }
 
-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) => 
@@ -179,28 +184,24 @@
   case Bop("<=", a1, a2) => 
     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpgt $jmp"
 }
+*/
 
 // compile function for declarations and main
 def compile_decl(d: Decl) : String = d match {
-  case Def(name, args, a) => { 
-    val env = args.zipWithIndex.toMap
-    val is = "I" * args.length
-    m".method public static $name($is)I" ++
-    m".limit locals ${args.length.toString}" ++
-    m".limit stack ${1 + max_stack_exp(a)}" ++
-    l"${name}_Start" ++   
-    compile_exp(a, env) ++
-    i"ireturn" ++
-    m".end method\n"
+  case Def(name, args, body) => { 
+    println(s"DEF\n $name ($args) = \nBODY:")
+    println(Denest(K(body)))
+    println()
+    counter = -1
+    m"define i32 @$name (${args.mkString("i32 %", ", i32 %", "")}) {" ++
+    compile_exp(Denest(K(body))) ++
+    m"}\n"
   }
-  case Main(a) => {
-    m".method public static main([Ljava/lang/String;)V" ++
-    m".limit locals 200" ++
-    m".limit stack 200" ++
-    compile_exp(a, Map()) ++
-    i"invokestatic XXX/XXX/write(I)V" ++
-    i"return" ++
-    m".end method\n"
+  case Main(body) => {
+    m"define i32 @main() {" ++
+    compile_exp(Denest(K(body))) ++
+    i"ret i32 0" ++
+    m"}\n"
   }
 }
 
@@ -222,10 +223,12 @@
 
 def compile(class_name: String) : String = {
   val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil) 
-  val instructions = ast.map(compile_decl).mkString
-  (library + instructions).replaceAllLiterally("XXX", class_name)
+  println(ast(0).toString ++ "\n")
+  val instructions = List(ast(0), ast(2)).map(compile_decl).mkString
+  instructions
 }
 
+/*
 def compile_to_file(class_name: String) = {
   val output = compile(class_name)
   scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output)
@@ -236,7 +239,7 @@
   (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!!
   println("Time: " + time_needed(2, (s"java ${class_name}/${class_name}").!))
 }
-
+*/
 
 // some examples of .fun files
 //compile_to_file("fact")
@@ -244,8 +247,8 @@
 //compile_and_run("defs")
 
 
-def main(args: Array[String]) = 
-   compile_and_run(args(0))
+def main(args: Array[String]) : Unit = 
+   println(compile(args(0)))
 
 
 }
\ No newline at end of file