diff -r 4980f421b3b0 -r c112a6cb5e52 progs/compile_arr.scala --- a/progs/compile_arr.scala Mon Jan 27 10:11:44 2020 +0000 +++ b/progs/compile_arr.scala Tue Jan 28 12:23:53 2020 +0000 @@ -101,34 +101,49 @@ case "*" => i"imul" } +def compile_num(i: Int) = + if (0 <= i && i <= 5) i"iconst_$i" else i"ldc $i" + +def compile_aload(i: Int) = + if (0 <= i && i <= 3) i"aload_$i" else i"aload $i" + +def compile_iload(i: Int) = + if (0 <= i && i <= 3) i"iload_$i" else i"iload $i" + +def compile_istore(i: Int) = + if (0 <= i && i <= 3) i"istore_$i" else i"istore $i" + // arithmetic expression compilation def compile_aexp(a: AExp, env : Env) : String = a match { - case Num(i) => i"ldc $i" - case Var(s) => i"iload ${env(s)}" + case Num(i) => compile_num(i) + case Var(s) => compile_iload(env(s)) case Aop(op, a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op) - case Ref(s, a) => - i"aload ${env(s)}" ++ compile_aexp(a, env) ++ i"iaload" + case Ref(s, a) => + compile_aload(env(s)) ++ compile_aexp(a, env) ++ i"iaload" } +def compile_bop(op: String, jmp: String) = op match { + case "==" => i"if_icmpne $jmp" + case "!=" => i"if_icmpeq $jmp" + case "<" => i"if_icmpge $jmp" +} + + // boolean expression compilation def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { case True => "" case False => i"goto $jmp" - case Bop("==", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp" - case Bop("!=", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp" - case Bop("<", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp" + case Bop(op, a1, a2) => + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_bop(op, jmp) } // statement compilation def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { case Skip => ("", env) case Assign(x, a) => { - val index = env.getOrElse(x, env.keys.size) - (compile_aexp(a, env) ++ i"istore $index \t\t; $x", env + (x -> index)) + val index = env.getOrElse(x, env.keys.size) // + (compile_aexp(a, env) ++ compile_istore(index), env + (x -> index)) } case If(b, bl1, bl2) => { val if_else = Fresh("If_else") @@ -153,12 +168,12 @@ l"$loop_end", env1) } case Write(x) => - (i"iload ${env(x)} \t\t; $x" ++ + (compile_iload(env(x)) ++ i"invokestatic XXX/XXX/write(I)V", env) case Read(x) => { val index = env.getOrElse(x, env.keys.size) - (i"invokestatic XXX/XXX/read()I" ++ - i"istore $index \t\t; $x", env + (x -> index)) + (i"invokestatic XXX/XXX/read()I" ++ + compile_istore(index), env + (x -> index)) } case ArrayDef(s: String, n: Int) => { val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else @@ -170,7 +185,7 @@ case AssignA(s, a1, a2) => { val index = if (env.isDefinedAt(s)) env(s) else throw new Exception("array not defined") - (i"aload ${env(s)}" ++ + (compile_aload(env(s)) ++ compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"iastore", env) @@ -243,7 +258,7 @@ println("generated .j file") (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! println("generated .class file ") - println("Time: " + time_needed(1, (s"java ${class_name}/${class_name}").!)._1) + println("Time: " + time_needed(3, (s"java ${class_name}/${class_name}").!)._1) } @@ -510,8 +525,9 @@ // Mandelbrot Set //---------------- // -// Note: Parsing of the generated WHILE program (around 60K in size) -// takes approximately 10 minutes +// Note: Parsing of the generated WHILE program (around 56K in size) +// takes approximately 10 minutes. The final class file runs +// for around 23 seconds. bf_run("""A mandelbrot set fractal viewer in brainf*** written by Erik Bosman +++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[