|
1 // compiles Abacus programs directly to Javabyte code |
|
2 |
|
3 import scala.sys.process._ |
|
4 import lib._ |
|
5 import abacus._ |
|
6 import recs._ |
|
7 import comp2._ |
|
8 |
|
9 |
|
10 def compile_aprog(p: AProg) : String = { |
|
11 |
|
12 def compile_inst(i: AInst, l: Int) : List[String] = { |
|
13 ("L" + l.toString + ":") :: (i match { |
|
14 case Inc(n) => List("iinc " + n.toString + " 1") |
|
15 case Dec(n, l) => List("iload " + n.toString, "ifeq L" + l.toString, "iinc " + n.toString + " -1") |
|
16 case Goto(l) => List("goto L" + l.toString) |
|
17 }) |
|
18 } |
|
19 |
|
20 val code = for ((i, l) <- p.zipWithIndex) |
|
21 yield compile_inst(i, l).mkString("", "\n", "\n") |
|
22 |
|
23 code.mkString |
|
24 } |
|
25 |
|
26 def init_regs(ns: List[Int]) : String = { |
|
27 |
|
28 val code = for ((n, i) <- ns.zipWithIndex) |
|
29 yield List("bipush " + n.toString, "istore " + i.toString).mkString("", "\n", "\n") |
|
30 |
|
31 code.mkString |
|
32 } |
|
33 |
|
34 def print_result(l: Int, r: Int, class_name: String) : String = { |
|
35 List("L" + l.toString + ":", |
|
36 "iload " + r.toString, |
|
37 "invokestatic " + class_name + "/" + class_name + "/write(I)V").mkString("", "\n", "\n") |
|
38 } |
|
39 |
|
40 // compiler preludes |
|
41 def beginning(class_name: String) : String = { |
|
42 "\n.class public " + class_name + "." + class_name + """ |
|
43 .super java/lang/Object |
|
44 |
|
45 .method public <init>()V |
|
46 aload_0 |
|
47 invokenonvirtual java/lang/Object/<init>()V |
|
48 return |
|
49 .end method |
|
50 |
|
51 .method public static write(I)V |
|
52 .limit locals 5 |
|
53 .limit stack 5 |
|
54 iload 0 |
|
55 getstatic java/lang/System/out Ljava/io/PrintStream; |
|
56 swap |
|
57 invokevirtual java/io/PrintStream/println(I)V |
|
58 return |
|
59 .end method |
|
60 |
|
61 |
|
62 .method public static main([Ljava/lang/String;)V |
|
63 .limit locals 200 |
|
64 .limit stack 200 |
|
65 |
|
66 """ } |
|
67 |
|
68 val ending = """ |
|
69 |
|
70 return |
|
71 |
|
72 .end method |
|
73 """ |
|
74 |
|
75 |
|
76 def compile(f: Rec, ns: List[Int]) : Unit = { |
|
77 val class_name = "LOOP" |
|
78 val (aprog, res, max) = compile_rec(f) |
|
79 |
|
80 val init_code = init_regs(ns.padTo(max, 0)) |
|
81 val main_code = compile_aprog(aprog.p) |
|
82 val fin_code = print_result(aprog.p.length, res, class_name) |
|
83 val code = init_code.mkString + main_code.mkString + fin_code |
|
84 |
|
85 val assembly = beginning(class_name) ++ code ++ ending |
|
86 |
|
87 val fw = new java.io.FileWriter(class_name + ".j") |
|
88 fw.write(assembly) |
|
89 fw.close() |
|
90 val _ = ("java -jar jvm/jasmin-2.4/jasmin.jar " + class_name + ".j").!! |
|
91 val start = System.nanoTime() |
|
92 val result = ("java " + class_name + "/" + class_name).!! |
|
93 val end = System.nanoTime() |
|
94 println("Result: " + result + " Time: " + (end - start) / 1.0e9) |
|
95 } |
|
96 |
|
97 |
|
98 //compile(S, List(3)) |
|
99 //compile(Fact, List(11)) |
|
100 //compile(Fact, List(12)) |
|
101 //compile(Fact, List(13)) |
|
102 //compile(Fact, List(14)) |
|
103 |
|
104 for (i <- 10 to 20) { |
|
105 println("Input: " + i) |
|
106 compile(Prime, List(i)) |
|
107 } |
|
108 |
|
109 |
|
110 |