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