diff -r 47a299e7010f -r 8d0af38389bc progs/compile.scala --- a/progs/compile.scala Sun Jul 28 01:00:41 2019 +0100 +++ b/progs/compile.scala Sun Jul 28 14:24:46 2019 +0100 @@ -1,6 +1,7 @@ // A Small Compiler for the WHILE Language // (it does not use a parser and lexer) + // the abstract syntax trees abstract class Stmt abstract class AExp @@ -85,16 +86,18 @@ .limit locals 200 .limit stack 200 +; COMPILED CODE STARTS + """ val ending = """ - +; COMPILED CODE ENDS return .end method """ -println("Start compilation") +// Compiler functions // for generating new labels @@ -105,46 +108,51 @@ x ++ "_" ++ counter.toString() } -// environments and instructions +// convenient string interpolations +// for instructions and labels +import scala.language.implicitConversions +import scala.language.reflectiveCalls + +implicit def sring_inters(sc: StringContext) = new { + def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" + def l(args: Any*): String = sc.s(args:_*) ++ ":\n" +} + + +// environments type Env = Map[String, String] -type Instrs = List[String] // arithmetic expression compilation -def compile_aexp(a: AExp, env : Env) : Instrs = a match { - case Num(i) => List("ldc " + i.toString + "\n") - case Var(s) => List("iload " + env(s) + "\n") +def compile_aexp(a: AExp, env : Env) : String = a match { + case Num(i) => i"ldc $i" + case Var(s) => i"iload ${env(s)}" case Aop("+", a1, a2) => - compile_aexp(a1, env) ++ - compile_aexp(a2, env) ++ List("iadd\n") + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"iadd" case Aop("-", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("isub\n") + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"isub" case Aop("*", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("imul\n") + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"imul" } // boolean expression compilation -def compile_bexp(b: BExp, env : Env, jmp: String) : Instrs = b match { - case True => Nil - case False => List("goto " + jmp + "\n") +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) ++ - List("if_icmpne " + jmp + "\n") + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp" case Bop("!=", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ - List("if_icmpeq " + jmp + "\n") + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp" case Bop("<", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ - List("if_icmpge " + jmp + "\n") + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp" } // statement compilation -def compile_stmt(s: Stmt, env: Env) : (Instrs, Env) = s match { - case Skip => (Nil, env) +def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { + case Skip => ("", env) case Assign(x, a) => { val index = if (env.isDefinedAt(x)) env(x) else env.keys.size.toString - (compile_aexp(a, env) ++ - List("istore " + index + "\n"), env + (x -> index)) + (compile_aexp(a, env) ++ i"istore $index", env + (x -> index)) } case If(b, bl1, bl2) => { val if_else = Fresh("If_else") @@ -153,35 +161,35 @@ val (instrs2, env2) = compile_block(bl2, env1) (compile_bexp(b, env, if_else) ++ instrs1 ++ - List("goto " + if_end + "\n") ++ - List("\n" + if_else + ":\n\n") ++ + i"goto $if_end" ++ + l"$if_else" ++ instrs2 ++ - List("\n" + if_end + ":\n\n"), env2) + l"$if_end", env2) } case While(b, bl) => { val loop_begin = Fresh("Loop_begin") val loop_end = Fresh("Loop_end") val (instrs1, env1) = compile_block(bl, env) - (List("\n" + loop_begin + ":\n\n") ++ + (l"$loop_begin" ++ compile_bexp(b, env, loop_end) ++ instrs1 ++ - List("goto " + loop_begin + "\n") ++ - List("\n" + loop_end + ":\n\n"), env1) + i"goto $loop_begin" ++ + l"$loop_end", env1) } case Write(x) => - (List("iload " + env(x) + "\n" + - "invokestatic XXX/XXX/write(I)V\n"), env) + (i"iload ${env(x)}" ++ + i"invokestatic XXX/XXX/write(I)V", env) case Read(x) => { val index = if (env.isDefinedAt(x)) env(x) else env.keys.size.toString - (List("invokestatic XXX/XXX/read()I\n" + - "istore " + index + "\n"), env + (x -> index)) + (i"invokestatic XXX/XXX/read()I" ++ + i"istore $index", env + (x -> index)) } } // compilation of a block (i.e. list of instructions) -def compile_block(bl: Block, env: Env) : (Instrs, Env) = bl match { - case Nil => (Nil, env) +def compile_block(bl: Block, env: Env) : (String, Env) = bl match { + case Nil => ("", env) case s::bl => { val (instrs1, env1) = compile_stmt(s, env) val (instrs2, env2) = compile_block(bl, env1) @@ -237,6 +245,7 @@ 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).!)) }