99 case "+" => i"iadd" |
99 case "+" => i"iadd" |
100 case "-" => i"isub" |
100 case "-" => i"isub" |
101 case "*" => i"imul" |
101 case "*" => i"imul" |
102 } |
102 } |
103 |
103 |
|
104 def compile_num(i: Int) = |
|
105 if (0 <= i && i <= 5) i"iconst_$i" else i"ldc $i" |
|
106 |
|
107 def compile_aload(i: Int) = |
|
108 if (0 <= i && i <= 3) i"aload_$i" else i"aload $i" |
|
109 |
|
110 def compile_iload(i: Int) = |
|
111 if (0 <= i && i <= 3) i"iload_$i" else i"iload $i" |
|
112 |
|
113 def compile_istore(i: Int) = |
|
114 if (0 <= i && i <= 3) i"istore_$i" else i"istore $i" |
|
115 |
104 // arithmetic expression compilation |
116 // arithmetic expression compilation |
105 def compile_aexp(a: AExp, env : Env) : String = a match { |
117 def compile_aexp(a: AExp, env : Env) : String = a match { |
106 case Num(i) => i"ldc $i" |
118 case Num(i) => compile_num(i) |
107 case Var(s) => i"iload ${env(s)}" |
119 case Var(s) => compile_iload(env(s)) |
108 case Aop(op, a1, a2) => |
120 case Aop(op, a1, a2) => |
109 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op) |
121 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op) |
110 case Ref(s, a) => |
122 case Ref(s, a) => |
111 i"aload ${env(s)}" ++ compile_aexp(a, env) ++ i"iaload" |
123 compile_aload(env(s)) ++ compile_aexp(a, env) ++ i"iaload" |
112 } |
124 } |
|
125 |
|
126 def compile_bop(op: String, jmp: String) = op match { |
|
127 case "==" => i"if_icmpne $jmp" |
|
128 case "!=" => i"if_icmpeq $jmp" |
|
129 case "<" => i"if_icmpge $jmp" |
|
130 } |
|
131 |
113 |
132 |
114 // boolean expression compilation |
133 // boolean expression compilation |
115 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { |
134 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { |
116 case True => "" |
135 case True => "" |
117 case False => i"goto $jmp" |
136 case False => i"goto $jmp" |
118 case Bop("==", a1, a2) => |
137 case Bop(op, a1, a2) => |
119 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp" |
138 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_bop(op, jmp) |
120 case Bop("!=", a1, a2) => |
|
121 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp" |
|
122 case Bop("<", a1, a2) => |
|
123 compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp" |
|
124 } |
139 } |
125 |
140 |
126 // statement compilation |
141 // statement compilation |
127 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { |
142 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { |
128 case Skip => ("", env) |
143 case Skip => ("", env) |
129 case Assign(x, a) => { |
144 case Assign(x, a) => { |
130 val index = env.getOrElse(x, env.keys.size) |
145 val index = env.getOrElse(x, env.keys.size) // |
131 (compile_aexp(a, env) ++ i"istore $index \t\t; $x", env + (x -> index)) |
146 (compile_aexp(a, env) ++ compile_istore(index), env + (x -> index)) |
132 } |
147 } |
133 case If(b, bl1, bl2) => { |
148 case If(b, bl1, bl2) => { |
134 val if_else = Fresh("If_else") |
149 val if_else = Fresh("If_else") |
135 val if_end = Fresh("If_end") |
150 val if_end = Fresh("If_end") |
136 val (instrs1, env1) = compile_block(bl1, env) |
151 val (instrs1, env1) = compile_block(bl1, env) |
151 instrs1 ++ |
166 instrs1 ++ |
152 i"goto $loop_begin" ++ |
167 i"goto $loop_begin" ++ |
153 l"$loop_end", env1) |
168 l"$loop_end", env1) |
154 } |
169 } |
155 case Write(x) => |
170 case Write(x) => |
156 (i"iload ${env(x)} \t\t; $x" ++ |
171 (compile_iload(env(x)) ++ |
157 i"invokestatic XXX/XXX/write(I)V", env) |
172 i"invokestatic XXX/XXX/write(I)V", env) |
158 case Read(x) => { |
173 case Read(x) => { |
159 val index = env.getOrElse(x, env.keys.size) |
174 val index = env.getOrElse(x, env.keys.size) |
160 (i"invokestatic XXX/XXX/read()I" ++ |
175 (i"invokestatic XXX/XXX/read()I" ++ |
161 i"istore $index \t\t; $x", env + (x -> index)) |
176 compile_istore(index), env + (x -> index)) |
162 } |
177 } |
163 case ArrayDef(s: String, n: Int) => { |
178 case ArrayDef(s: String, n: Int) => { |
164 val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else |
179 val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else |
165 env.keys.size |
180 env.keys.size |
166 (i"ldc $n" ++ |
181 (i"ldc $n" ++ |
168 i"astore $index", env + (s -> index)) |
183 i"astore $index", env + (s -> index)) |
169 } |
184 } |
170 case AssignA(s, a1, a2) => { |
185 case AssignA(s, a1, a2) => { |
171 val index = if (env.isDefinedAt(s)) env(s) else |
186 val index = if (env.isDefinedAt(s)) env(s) else |
172 throw new Exception("array not defined") |
187 throw new Exception("array not defined") |
173 (i"aload ${env(s)}" ++ |
188 (compile_aload(env(s)) ++ |
174 compile_aexp(a1, env) ++ |
189 compile_aexp(a1, env) ++ |
175 compile_aexp(a2, env) ++ |
190 compile_aexp(a2, env) ++ |
176 i"iastore", env) |
191 i"iastore", env) |
177 } |
192 } |
178 } |
193 } |
241 println(s"Start compilation of $class_name") |
256 println(s"Start compilation of $class_name") |
242 compile_to_file(bl, class_name) |
257 compile_to_file(bl, class_name) |
243 println("generated .j file") |
258 println("generated .j file") |
244 (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! |
259 (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! |
245 println("generated .class file ") |
260 println("generated .class file ") |
246 println("Time: " + time_needed(1, (s"java ${class_name}/${class_name}").!)._1) |
261 println("Time: " + time_needed(3, (s"java ${class_name}/${class_name}").!)._1) |
247 } |
262 } |
248 |
263 |
249 |
264 |
250 val arr_test = |
265 val arr_test = |
251 List(ArrayDef("a", 10), |
266 List(ArrayDef("a", 10), |