--- 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