diff -r 53f08d873e09 -r 7af2eea19646 solutions/cw4/compiler.sc --- a/solutions/cw4/compiler.sc Sun Sep 17 19:12:57 2023 +0100 +++ b/solutions/cw4/compiler.sc Tue Sep 19 09:54:41 2023 +0100 @@ -92,7 +92,7 @@ x ++ "_" ++ counter.toString() } -implicit def string_interpolations(sc: StringContext) = new { +extension (sc: StringContext) { def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" def l(args: Any*): String = sc.s(args:_*) ++ ":\n" } @@ -138,7 +138,7 @@ compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"${compile_bop(op)} $jmp" } -def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { +def compile_stmt(s: Stmt, env: Env, break: String) : (String, Env) = s match { case Skip => ("", env) case Assign(x, a) => { val index = env.getOrElse(x, env.keys.size) @@ -147,8 +147,8 @@ case If(b, bl1, bl2) => { val if_else = Fresh("If_else") val if_end = Fresh("If_end") - val (instrs1, env1) = compile_block(bl1, env) - val (instrs2, env2) = compile_block(bl2, env1) + val (instrs1, env1) = compile_block(bl1, env, break) + val (instrs2, env2) = compile_block(bl2, env1, break) (compile_bexp(b, env, if_else) ++ instrs1 ++ i"goto $if_end" ++ @@ -159,7 +159,7 @@ case While(b, bl) => { val loop_begin = Fresh("Loop_begin") val loop_end = Fresh("Loop_end") - val (instrs1, env1) = compile_block(bl, env) + val (instrs1, env1) = compile_block(bl, env, break) (l"$loop_begin" ++ compile_bexp(b, env, loop_end) ++ instrs1 ++ @@ -167,17 +167,18 @@ l"$loop_end", env1) } case For(id, lower, upper, code) => { - val (assignment_code, env1) = compile_stmt(Assign(id, lower), env) // id := lower; + val (assignment_code, env1) = compile_stmt(Assign(id, lower), env, break) // id := lower; val while_equivalent = While( Or(Bop("<", Var(id), upper), Bop("==", Var(id), upper)), // while id <= upper do { code ++ // code List( Assign(id, Aop("+", Var(id), Num(1))) // id := id + 1 )) // }; - - val (while_code, env2) = compile_stmt(while_equivalent, env1) - (assignment_code ++ while_code, env2) + val new_break = Fresh("for_break") + val (while_code, env2) = compile_stmt(while_equivalent, env1, new_break) + (assignment_code ++ while_code ++ l"$new_break", env2) } + case Break => (i"goto $break", env) case WriteId(x) => (i"iload ${env(x)} \t\t; $x" ++ i"invokestatic XXX/XXX/write(I)V", env) case WriteString(x) => (s" ldc ${x}\n" ++ @@ -189,38 +190,33 @@ } } -def compile_block(bl: Block, env: Env) : (String, Env) = bl match { +def compile_block(bl: Block, env: Env, break: String) : (String, Env) = bl match { case Nil => ("", env) case s::bl => { - val (instrs1, env1) = compile_stmt(s, env) - val (instrs2, env2) = compile_block(bl, env1) + val (instrs1, env1) = compile_stmt(s, env, break) + val (instrs2, env2) = compile_block(bl, env1, break) (instrs1 ++ instrs2, env2) } } def compile(bl: Block, class_name: String) : String = { - val instructions = compile_block(bl, Map.empty)._1 - (beginning ++ instructions ++ ending).replaceAllLiterally("XXX", class_name) + val prog_end = Fresh("Prog_end") + val instructions = compile_block(bl, Map.empty, prog_end)._1 + (beginning ++ instructions ++ l"$prog_end" ++ ending).replaceAllLiterally("XXX", class_name) } // Compiling and running -import scala.util._ -import scala.sys.process._ -import scala.io -def compile_tofile(bl: Block, class_name: String) = { - val output = compile(bl, class_name) - val fw = new java.io.FileWriter(class_name + ".j") - fw.write(output) - fw.close() -} +def compile_to_file(bl: Block, class_name: String) : Unit = + os.write.over(os.pwd / s"$class_name.j", compile(bl, class_name)) def compile_all(bl: Block, class_name: String) : Unit = { - compile_tofile(bl, class_name) - println("compiled ") - val test = ("java -jar jasmin.jar " + class_name + ".j").!! - println("assembled ") + println(s"Start of compilation") + compile_to_file(bl, class_name) + println(s"generated $class_name.j file") + os.proc("java", "-jar", "jasmin.jar", s"$class_name.j").call() + println(s"generated $class_name.class file ") } def time_needed[T](i: Int, code: => T) = { @@ -231,10 +227,10 @@ } def compile_run(bl: Block, class_name: String) : Unit = { - println("Start compilation") compile_all(bl, class_name) println("running") - println("Time: " + time_needed(1, ("java " + class_name + "/" + class_name).!)) + os.proc("java", s"${class_name}/${class_name}").call(stdout = os.Inherit) + println(s"done.") } // ---- Q1 @@ -280,4 +276,8 @@ }""")).head, "nestedloop") */ -compile_run(Stmts.parse_all(tokenise(os.read(os.pwd / "collatz2.while"))).head, "collatz2") +//compile_run(Stmts.parse_all(tokenise(os.read(os.pwd / "collatz2.while"))).head, "collatz2") + + +println(tokenise(os.read(os.pwd / "forloop.while"))) +compile_run(Stmts.parse_all(tokenise(os.read(os.pwd / "forloop.while"))).head, "forloop") \ No newline at end of file