--- 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