|     10 // statements |     10 // statements | 
|     11 case object Skip extends Stmt |     11 case object Skip extends Stmt | 
|     12 case class If(a: BExp, bl1: Block, bl2: Block) extends Stmt |     12 case class If(a: BExp, bl1: Block, bl2: Block) extends Stmt | 
|     13 case class While(b: BExp, bl: Block) extends Stmt |     13 case class While(b: BExp, bl: Block) extends Stmt | 
|     14 case class Assign(s: String, a: AExp) extends Stmt |     14 case class Assign(s: String, a: AExp) extends Stmt | 
|         |     15 case class AssignA(s: String, a1: AExp, a2: AExp) extends Stmt | 
|     15 case class Write(s: String) extends Stmt  // writes out a variable |     16 case class Write(s: String) extends Stmt  // writes out a variable | 
|         |     17 case class Array(s: String, n: Int) extends Stmt  | 
|     16  |     18  | 
|     17 // arithmetic expressions |     19 // arithmetic expressions | 
|     18 case class Var(s: String) extends AExp |     20 case class Var(s: String) extends AExp | 
|     19 case class Num(i: Int) extends AExp |     21 case class Num(i: Int) extends AExp | 
|     20 case class Aop(o: String, a1: AExp, a2: AExp) extends AExp |     22 case class Aop(o: String, a1: AExp, a2: AExp) extends AExp | 
|         |     23 case class Ref(s: String, a1: AExp) extends AExp | 
|     21  |     24  | 
|     22 // boolean expressions |     25 // boolean expressions | 
|     23 case object True extends BExp |     26 case object True extends BExp | 
|     24 case object False extends BExp |     27 case object False extends BExp | 
|     25 case class Bop(o: String, a1: AExp, a2: AExp) extends BExp |     28 case class Bop(o: String, a1: AExp, a2: AExp) extends BExp | 
|    134      List("\n" + loop_end + ":\n\n"), env1) |    137      List("\n" + loop_end + ":\n\n"), env1) | 
|    135   } |    138   } | 
|    136   case Write(x) =>  |    139   case Write(x) =>  | 
|    137     (List("iload " + env(x) + "\n" +  |    140     (List("iload " + env(x) + "\n" +  | 
|    138            "invokestatic XXX/XXX/write(I)V\n"), env) |    141            "invokestatic XXX/XXX/write(I)V\n"), env) | 
|         |    142   case Array(s, n) => { | 
|         |    143     val index = if (env.isDefinedAt(s)) throw new Exception("Array already defined") else  | 
|         |    144                     env.keys.size.toString | 
|         |    145     (List("ldc " ++ n.toString ++ "\n", | 
|         |    146           "newarray int \n", | 
|         |    147           "astore " ++ index ++ "\n"), env + (s -> index)) | 
|         |    148   }  | 
|         |    149   case AssignA(s, a1, a2) => { | 
|         |    150     val index = if (env.isDefinedAt(s)) env(s) else  | 
|         |    151                     throw new Exception("Array not yet defined") | 
|         |    152     (List("aload " + index) ++ | 
|         |    153      compile_aexp(a1, env) ++ | 
|         |    154      compile_aexp(a2, env) ++ | 
|         |    155      List("iastore"), env) | 
|         |    156        | 
|         |    157       compile_aexp(a, env) ++  | 
|         |    158      List("istore " + index + "\n"), env + (x -> index)) | 
|         |    159   }  | 
|    139 } |    160 } | 
|    140  |    161  | 
|    141 // compilation of a block (i.e. list of instructions) |    162 // compilation of a block (i.e. list of instructions) | 
|    142 def compile_block(bl: Block, env: Env) : (Instrs, Env) = bl match { |    163 def compile_block(bl: Block, env: Env) : (Instrs, Env) = bl match { | 
|    143   case Nil => (Nil, env) |    164   case Nil => (Nil, env) |