diff -r 68324a8566c1 -r 0974c59e7029 scala/ex_jvm.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scala/ex_jvm.scala Thu Mar 14 18:46:34 2013 +0000 @@ -0,0 +1,110 @@ +// compiles Abacus programs directly to Javabyte code + +import scala.sys.process._ +import lib._ +import abacus._ +import recs._ +import comp2._ + + +def compile_aprog(p: AProg) : String = { + + def compile_inst(i: AInst, l: Int) : List[String] = { + ("L" + l.toString + ":") :: (i match { + case Inc(n) => List("iinc " + n.toString + " 1") + case Dec(n, l) => List("iload " + n.toString, "ifeq L" + l.toString, "iinc " + n.toString + " -1") + case Goto(l) => List("goto L" + l.toString) + }) + } + + val code = for ((i, l) <- p.zipWithIndex) + yield compile_inst(i, l).mkString("", "\n", "\n") + + code.mkString +} + +def init_regs(ns: List[Int]) : String = { + + val code = for ((n, i) <- ns.zipWithIndex) + yield List("bipush " + n.toString, "istore " + i.toString).mkString("", "\n", "\n") + + code.mkString +} + +def print_result(l: Int, r: Int, class_name: String) : String = { + List("L" + l.toString + ":", + "iload " + r.toString, + "invokestatic " + class_name + "/" + class_name + "/write(I)V").mkString("", "\n", "\n") +} + +// compiler preludes +def beginning(class_name: String) : String = { +"\n.class public " + class_name + "." + class_name + """ +.super java/lang/Object + +.method public ()V + aload_0 + invokenonvirtual java/lang/Object/()V + return +.end method + +.method public static write(I)V + .limit locals 5 + .limit stack 5 + iload 0 + getstatic java/lang/System/out Ljava/io/PrintStream; + swap + invokevirtual java/io/PrintStream/println(I)V + return +.end method + + +.method public static main([Ljava/lang/String;)V + .limit locals 200 + .limit stack 200 + +""" } + +val ending = """ + + return + +.end method +""" + + +def compile(f: Rec, ns: List[Int]) : Unit = { + val class_name = "LOOP" + val (aprog, res, max) = compile_rec(f) + + val init_code = init_regs(ns.padTo(max, 0)) + val main_code = compile_aprog(aprog.p) + val fin_code = print_result(aprog.p.length, res, class_name) + val code = init_code.mkString + main_code.mkString + fin_code + + val assembly = beginning(class_name) ++ code ++ ending + + val fw = new java.io.FileWriter(class_name + ".j") + fw.write(assembly) + fw.close() + val _ = ("java -jar jvm/jasmin-2.4/jasmin.jar " + class_name + ".j").!! + val start = System.nanoTime() + val result = ("java " + class_name + "/" + class_name).!! + val end = System.nanoTime() + println("Result: " + result + " Time: " + (end - start) / 1.0e9) +} + + +//compile(S, List(3)) +//compile(Fact, List(11)) +//compile(Fact, List(12)) +//compile(Fact, List(13)) +//compile(Fact, List(14)) + +for (i <- 10 to 20) { + println("Input: " + i) + compile(Prime, List(i)) +} + + +