116 implicit def sring_inters(sc: StringContext) = new { | 
   116 implicit def sring_inters(sc: StringContext) = new { | 
   117     def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"  | 
   117     def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"  | 
   118     def l(args: Any*): String = sc.s(args:_*) ++ ":\n"  | 
   118     def l(args: Any*): String = sc.s(args:_*) ++ ":\n"  | 
   119 }  | 
   119 }  | 
   120   | 
   120   | 
         | 
   121 // this allows you to write things like  | 
         | 
   122 // i"add" and l"Lable"  | 
         | 
   123   | 
   121   | 
   124   | 
   122 // environments   | 
   125 // environments   | 
   123 type Env = Map[String, Int]  | 
   126 type Env = Map[String, Int]  | 
   124   | 
   127   | 
   125   | 
   128   | 
   130 }  | 
   133 }  | 
   131   | 
   134   | 
   132 // arithmetic expression compilation  | 
   135 // arithmetic expression compilation  | 
   133 def compile_aexp(a: AExp, env : Env) : String = a match { | 
   136 def compile_aexp(a: AExp, env : Env) : String = a match { | 
   134   case Num(i) => i"ldc $i"  | 
   137   case Num(i) => i"ldc $i"  | 
   135   case Var(s) => i"iload ${env(s)}" | 
   138   case Var(s) => i"iload ${env(s)} \t\t; $s" | 
   136   case Aop(op, a1, a2) =>   | 
   139   case Aop(op, a1, a2) =>   | 
   137     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op)  | 
   140     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op)  | 
   138 }  | 
   141 }  | 
   139   | 
   142   | 
   140 // boolean expression compilation  | 
   143 // boolean expression compilation  | 
         | 
   144 //  - the jump-label is for where to jump if the condition is not true  | 
   141 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { | 
   145 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match { | 
   142   case True => ""  | 
   146   case True => ""  | 
   143   case False => i"goto $jmp"  | 
   147   case False => i"goto $jmp"  | 
   144   case Bop("=", a1, a2) =>  | 
   148   case Bop("==", a1, a2) =>  | 
   145     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp"  | 
   149     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp"  | 
   146   case Bop("!=", a1, a2) =>  | 
   150   case Bop("!=", a1, a2) =>  | 
   147     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp"  | 
   151     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp"  | 
   148   case Bop("<", a1, a2) =>  | 
   152   case Bop("<", a1, a2) =>  | 
   149     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp"  | 
   153     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp"  | 
   151   | 
   155   | 
   152 // statement compilation  | 
   156 // statement compilation  | 
   153 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { | 
   157 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match { | 
   154   case Skip => ("", env) | 
   158   case Skip => ("", env) | 
   155   case Assign(x, a) => { | 
   159   case Assign(x, a) => { | 
   156     val index = if (env.isDefinedAt(x)) env(x) else env.keys.size  | 
   160     val index = env.getOrElse(x, env.keys.size)  | 
   157     (compile_aexp(a, env) ++ i"istore $index", env + (x -> index))  | 
   161     (compile_aexp(a, env) ++ i"istore $index \t\t; $x", env + (x -> index))  | 
   158   }   | 
   162   }   | 
   159   case If(b, bl1, bl2) => { | 
   163   case If(b, bl1, bl2) => { | 
   160     val if_else = Fresh("If_else") | 
   164     val if_else = Fresh("If_else") | 
   161     val if_end = Fresh("If_end") | 
   165     val if_end = Fresh("If_end") | 
   162     val (instrs1, env1) = compile_block(bl1, env)  | 
   166     val (instrs1, env1) = compile_block(bl1, env)  | 
   177      instrs1 ++  | 
   181      instrs1 ++  | 
   178      i"goto $loop_begin" ++  | 
   182      i"goto $loop_begin" ++  | 
   179      l"$loop_end", env1)  | 
   183      l"$loop_end", env1)  | 
   180   }  | 
   184   }  | 
   181   case Write(x) =>   | 
   185   case Write(x) =>   | 
   182     (i"iload ${env(x)}" ++  | 
   186     (i"iload ${env(x)} \t\t; $x" ++  | 
   183      i"invokestatic XXX/XXX/write(I)V", env)  | 
   187      i"invokestatic XXX/XXX/write(I)V", env)  | 
   184   case Read(x) => { | 
   188   case Read(x) => { | 
   185     val index = if (env.isDefinedAt(x)) env(x) else env.keys.size  | 
   189     val index = env.getOrElse(x, env.keys.size)   | 
   186     (i"invokestatic XXX/XXX/read()I" ++   | 
   190     (i"invokestatic XXX/XXX/read()I" ++   | 
   187      i"istore $index", env + (x -> index))  | 
   191      i"istore $index \t\t; $x", env + (x -> index))  | 
   188   }  | 
   192   }  | 
   189 }  | 
   193 }  | 
   190   | 
   194   | 
   191 // compilation of a block (i.e. list of instructions)  | 
   195 // compilation of a block (i.e. list of instructions)  | 
   192 def compile_block(bl: Block, env: Env) : (String, Env) = bl match { | 
   196 def compile_block(bl: Block, env: Env) : (String, Env) = bl match { | 
   264                Assign("minus1",Var("temp")), //  minus1 := temp; | 
   268                Assign("minus1",Var("temp")), //  minus1 := temp; | 
   265                Assign("n",Aop("-",Var("n"),Num(1))))), //  n := n - 1 }; | 
   269                Assign("n",Aop("-",Var("n"),Num(1))))), //  n := n - 1 }; | 
   266        Write("minus1"))                 //  write minus1 | 
   270        Write("minus1"))                 //  write minus1 | 
   267   | 
   271   | 
   268   | 
   272   | 
         | 
   273 // the compiled file as string  | 
         | 
   274 //  | 
         | 
   275 //println(compile(fib_test, "fib"))  | 
         | 
   276   | 
         | 
   277   | 
   269 compile_run(fib_test, "fib")  | 
   278 compile_run(fib_test, "fib")  | 
   270   | 
   279   | 
   271   | 
   280   |