184 def compile(bl: Block, class_name: String) : String = { |
184 def compile(bl: Block, class_name: String) : String = { |
185 val instructions = compile_block(bl, Map.empty)._1 |
185 val instructions = compile_block(bl, Map.empty)._1 |
186 (beginning ++ instructions.mkString ++ ending).replaceAllLiterally("XXX", class_name) |
186 (beginning ++ instructions.mkString ++ ending).replaceAllLiterally("XXX", class_name) |
187 } |
187 } |
188 |
188 |
189 // compiling and running files |
189 |
190 // |
190 // main compiler functions |
191 // JVM files can be assembled with |
|
192 // |
|
193 // java -jar jvm/jasmin-2.4/jasmin.jar fib.j |
|
194 // |
|
195 // and started with |
|
196 // |
|
197 // java fib/fib |
|
198 |
|
199 |
|
200 |
|
201 import scala.util._ |
191 import scala.util._ |
202 import scala.sys.process._ |
192 import scala.sys.process._ |
203 import scala.io |
193 import scala.io |
204 |
194 |
205 def compile_tofile(bl: Block, class_name: String) = { |
195 def compile_tofile(bl: Block, class_name: String) = { |
206 val output = compile(bl, class_name) |
196 val output = compile(bl, class_name) |
207 val fw = new java.io.FileWriter(class_name + ".j") |
197 scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output) |
208 fw.write(output) |
|
209 fw.close() |
|
210 } |
198 } |
211 |
199 |
212 def compile_all(bl: Block, class_name: String) : Unit = { |
200 def compile_all(bl: Block, class_name: String) : Unit = { |
213 compile_tofile(bl, class_name) |
201 compile_tofile(bl, class_name) |
214 println("compiled ") |
202 println("compiled ") |
215 val test = ("java -jar jvm/jasmin-2.4/jasmin.jar " + class_name + ".j").!! |
203 (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! |
216 println("assembled ") |
204 println("assembled ") |
217 } |
205 } |
218 |
206 |
219 def time_needed[T](i: Int, code: => T) = { |
207 def time_needed[T](i: Int, code: => T) = { |
220 val start = System.nanoTime() |
208 val start = System.nanoTime() |
225 |
213 |
226 |
214 |
227 def compile_run(bl: Block, class_name: String) : Unit = { |
215 def compile_run(bl: Block, class_name: String) : Unit = { |
228 println("Start compilation") |
216 println("Start compilation") |
229 compile_all(bl, class_name) |
217 compile_all(bl, class_name) |
230 println("running") |
218 println("Start running") |
231 println("Time: " + time_needed(1, ("java " + class_name + "/" + class_name).!)) |
219 println("Time: " + time_needed(1, (s"java ${class_name}/${class_name}").!)) |
232 } |
220 } |
233 |
221 |
234 |
222 // a simple test case |
235 // BF Part |
223 val arr_test = |
236 |
224 List(Array("a", 10), // a[10] |
237 // simple instructions |
225 Array("b", 2), // b[2] |
238 def instr(c: Char) : String = c match { |
226 AssignA("a", Num(0), Num(10)), // a[0] := 10 |
239 case '>' => "ptr := ptr + 1;" |
227 Assign("x", Ref("a", Num(0))), // x := a[0] |
240 case '<' => "ptr := ptr - 1;" |
228 Write("x"), // write x |
241 case '+' => "field[ptr] := field[ptr] + 1;" |
229 AssignA("b", Num(1), Num(5)), // b[1] := 5 |
242 case '-' => "field[ptr] := field[ptr] - 1;" |
230 Assign("x", Ref("b", Num(1))), // x := b[1] |
243 case '.' => "x := field[ptr]; write x;" |
231 Write("x")) // write x |
244 case '[' => "while (field[ptr] != 0) do {" |
232 |
245 case ']' => "skip};" |
233 compile_run(arr_test, "a") |
246 case _ => "" |
234 |
247 } |
|
248 |
|
249 def instrs(prog: String) : String = |
|
250 prog.toList.map(instr).mkString |
|
251 |
|
252 |
|
253 // compound instructions |
|
254 def splice(cs: List[Char], acc: List[(Char, Int)]) : List[(Char, Int)] = (cs, acc) match { |
|
255 case (Nil, acc) => acc |
|
256 case (c :: cs, Nil) => splice(cs, List((c, 1))) |
|
257 case (c :: cs, (d, n) :: acc) => |
|
258 if (c == d) splice(cs, (c, n + 1) :: acc) |
|
259 else splice(cs, (c, 1) :: (d, n) :: acc) |
|
260 } |
|
261 |
|
262 def spl(s: String) = splice(s.toList, Nil).reverse |
|
263 |
|
264 def instr2(c: Char, n: Int) : String = c match { |
|
265 case '>' => s"ptr := ptr + $n;" |
|
266 case '<' => s"ptr := ptr - $n;" |
|
267 case '+' => s"field[ptr] := field[ptr] + $n;" |
|
268 case '-' => s"field[ptr] := field[ptr] - $n;" |
|
269 case '.' => s"x := field[ptr]; write x;" |
|
270 case '[' => s"while (field[ptr] != 0) do {" * n |
|
271 case ']' => s"skip};" * n |
|
272 case _ => "" |
|
273 } |
|
274 |
|
275 def instrs2(prog: String) : String = |
|
276 spl(prog).map{ case (c, n) => instr2(c, n) }.mkString |
|
277 |
|
278 |
|
279 def bf_str(prog: String) : String = { |
|
280 "\n" ++ |
|
281 //"new field[30000];\n" ++ |
|
282 "ptr := 15000;" ++ |
|
283 instrs2(prog) ++ |
|
284 "skip" |
|
285 } |
|
286 |
|
287 def bf_run(bfprog: String, name: String) = { |
|
288 println("BF processing start") |
|
289 val bf_string = bf_str(bfprog).replaceAll("\\s", "") |
|
290 println(s"BF parsing start (string length ${bf_string.length})") |
|
291 val bf_prog = Stmts.parse_all(bf_string).toList.head |
|
292 println("BF Compile start") |
|
293 compile_run(Array("field", 30000) :: bf_prog, name) |
|
294 } |
|
295 |
|
296 |
|
297 |
|
298 val bf1 = """++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[ |
|
299 ->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<< |
|
300 ]>.>+[>>]>+]""" |
|
301 |
|
302 bf_run(bf1, "sier") |
|
303 |
|
304 bf_run("""++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++ |
|
305 ..+++.>>.<-.<.+++.------.--------.>>+.>++.""", "hello") |
|
306 |
|
307 bf_run("""+++++++++++ |
|
308 >+>>>>++++++++++++++++++++++++++++++++++++++++++++ |
|
309 >++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+> |
|
310 +<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[- |
|
311 <-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<< |
|
312 -]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]] |
|
313 >[<<+>>[-]]<<<<<<<]>>>>>[+++++++++++++++++++++++++ |
|
314 +++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++ |
|
315 ++++++++++++++++++++++++++++++++++++++++++++.[-]<< |
|
316 <<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<< |
|
317 [-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]""", "fibs") |
|