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