| 609 |      1 | // A Small Compiler for the WHILE Language
 | 
| 707 |      2 | //
 | 
| 694 |      3 | //  - includes arrays and a small parser for
 | 
| 707 |      4 | //    WHILE programs
 | 
|  |      5 | //
 | 
|  |      6 | //  - transpiles BF programs into WHILE programs
 | 
|  |      7 | //    and compiles and runs them
 | 
|  |      8 | //
 | 
| 713 |      9 | //  - makes array access safe by explicit bound checks
 | 
|  |     10 | //    and perform defaults when bounds are exceeded
 | 
|  |     11 | //
 | 
|  |     12 | //  - uses goto_w for jumps in while-loops
 | 
|  |     13 | //
 | 
| 707 |     14 | // Call with
 | 
|  |     15 | //
 | 
| 713 |     16 | // scala compile_arr3.scala
 | 
| 707 |     17 | 
 | 
| 710 |     18 | // Mandelbrot
 | 
| 713 |     19 | // mand.j size       605196
 | 
|  |     20 | // mand.class size   56812
 | 
|  |     21 | // running time      26 secs
 | 
| 609 |     22 | 
 | 
|  |     23 | // the abstract syntax trees
 | 
|  |     24 | abstract class Stmt
 | 
|  |     25 | abstract class AExp
 | 
|  |     26 | abstract class BExp 
 | 
|  |     27 | type Block = List[Stmt]
 | 
|  |     28 | 
 | 
|  |     29 | // statements
 | 
|  |     30 | case object Skip extends Stmt
 | 
| 707 |     31 | case class ArrayDef(s: String, n: Int) extends Stmt
 | 
| 609 |     32 | case class If(a: BExp, bl1: Block, bl2: Block) extends Stmt
 | 
|  |     33 | case class While(b: BExp, bl: Block) extends Stmt
 | 
| 707 |     34 | case class Assign(s: String, a: AExp) extends Stmt             // var := exp
 | 
|  |     35 | case class AssignA(s: String, a1: AExp, a2: AExp) extends Stmt // arr[exp1] := exp2
 | 
| 694 |     36 | case class Write(s: String) extends Stmt
 | 
|  |     37 | case class Read(s: String) extends Stmt
 | 
| 609 |     38 | 
 | 
|  |     39 | // arithmetic expressions
 | 
|  |     40 | case class Var(s: String) extends AExp
 | 
|  |     41 | case class Num(i: Int) extends AExp
 | 
|  |     42 | case class Aop(o: String, a1: AExp, a2: AExp) extends AExp
 | 
| 694 |     43 | case class Ref(s: String, a: AExp) extends AExp
 | 
| 609 |     44 | 
 | 
|  |     45 | // boolean expressions
 | 
|  |     46 | case object True extends BExp
 | 
|  |     47 | case object False extends BExp
 | 
|  |     48 | case class Bop(o: String, a1: AExp, a2: AExp) extends BExp
 | 
|  |     49 | 
 | 
|  |     50 | 
 | 
|  |     51 | // compiler headers needed for the JVM
 | 
|  |     52 | // (contains an init method, as well as methods for read and write)
 | 
|  |     53 | val beginning = """
 | 
|  |     54 | .class public XXX.XXX
 | 
|  |     55 | .super java/lang/Object
 | 
|  |     56 | 
 | 
|  |     57 | .method public static write(I)V 
 | 
|  |     58 |     .limit locals 1 
 | 
|  |     59 |     .limit stack 2 
 | 
|  |     60 |     getstatic java/lang/System/out Ljava/io/PrintStream; 
 | 
|  |     61 |     iload 0
 | 
| 694 |     62 |     i2c       ; Int => Char
 | 
|  |     63 |     invokevirtual java/io/PrintStream/print(C)V   ; println(I)V => print(C)V    
 | 
| 609 |     64 |     return 
 | 
|  |     65 | .end method
 | 
|  |     66 | 
 | 
|  |     67 | .method public static main([Ljava/lang/String;)V
 | 
|  |     68 |    .limit locals 200
 | 
|  |     69 |    .limit stack 200
 | 
|  |     70 | 
 | 
| 708 |     71 | ; COMPILED CODE STARTS   
 | 
|  |     72 | 
 | 
| 609 |     73 | """
 | 
|  |     74 | 
 | 
|  |     75 | val ending = """
 | 
| 708 |     76 | ; COMPILED CODE ENDS
 | 
| 609 |     77 |    return
 | 
|  |     78 | 
 | 
|  |     79 | .end method
 | 
|  |     80 | """
 | 
|  |     81 | 
 | 
| 694 |     82 | 
 | 
| 609 |     83 | 
 | 
|  |     84 | 
 | 
|  |     85 | // for generating new labels
 | 
|  |     86 | var counter = -1
 | 
|  |     87 | 
 | 
|  |     88 | def Fresh(x: String) = {
 | 
|  |     89 |   counter += 1
 | 
|  |     90 |   x ++ "_" ++ counter.toString()
 | 
|  |     91 | }
 | 
|  |     92 | 
 | 
|  |     93 | // environments and instructions
 | 
| 694 |     94 | type Env = Map[String, Int]
 | 
|  |     95 | 
 | 
|  |     96 | // convenient string interpolations 
 | 
|  |     97 | // for instructions and labels
 | 
|  |     98 | import scala.language.implicitConversions
 | 
|  |     99 | import scala.language.reflectiveCalls
 | 
|  |    100 | 
 | 
|  |    101 | implicit def sring_inters(sc: StringContext) = new {
 | 
|  |    102 |     def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"
 | 
|  |    103 |     def l(args: Any*): String = sc.s(args:_*) ++ ":\n"
 | 
|  |    104 | }
 | 
|  |    105 | 
 | 
|  |    106 | def compile_op(op: String) = op match {
 | 
|  |    107 |   case "+" => i"iadd"
 | 
|  |    108 |   case "-" => i"isub"
 | 
|  |    109 |   case "*" => i"imul"
 | 
|  |    110 | }
 | 
| 609 |    111 | 
 | 
| 710 |    112 | 
 | 
|  |    113 | def compile_num(i: Int) = 
 | 
|  |    114 |   if (0 <= i && i <= 5) i"iconst_$i" else 
 | 
|  |    115 |   if (-128 <= i && i <= 127) i"bipush $i" else i"ldc $i"
 | 
|  |    116 | 
 | 
|  |    117 | def compile_aload(i: Int) = 
 | 
|  |    118 |   if (0 <= i && i <= 3) i"aload_$i" else i"aload $i"
 | 
|  |    119 | 
 | 
|  |    120 | def compile_iload(i: Int) = 
 | 
|  |    121 |   if (0 <= i && i <= 3) i"iload_$i" else i"iload $i"
 | 
|  |    122 | 
 | 
|  |    123 | def compile_istore(i: Int) = 
 | 
|  |    124 |   if (0 <= i && i <= 3) i"istore_$i" else i"istore $i"
 | 
|  |    125 | 
 | 
| 609 |    126 | // arithmetic expression compilation
 | 
| 694 |    127 | def compile_aexp(a: AExp, env : Env) : String = a match {
 | 
| 710 |    128 |   case Num(i) => compile_num(i)
 | 
|  |    129 |   case Var(s) => compile_iload(env(s))
 | 
| 694 |    130 |   case Aop(op, a1, a2) => 
 | 
|  |    131 |     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op)
 | 
| 712 |    132 |   case Ref(s, a) => {
 | 
|  |    133 |     val arr_safe = Fresh("Arr_safe")
 | 
|  |    134 |     val arr_end = Fresh("Arr_end_")
 | 
|  |    135 |     compile_aexp(a, env) ++
 | 
|  |    136 |     compile_aload(env(s)) ++
 | 
|  |    137 |     i"dup2" ++
 | 
|  |    138 |     i"arraylength" ++
 | 
|  |    139 |     i"if_icmple $arr_safe" ++
 | 
|  |    140 |     i"pop2" ++
 | 
|  |    141 |     i"iconst_0" ++
 | 
|  |    142 |     i"goto $arr_end" ++
 | 
|  |    143 |     l"$arr_safe" ++
 | 
|  |    144 |     i"swap" ++
 | 
|  |    145 |     i"iaload" ++
 | 
|  |    146 |     l"$arr_end"
 | 
|  |    147 |   }
 | 
| 609 |    148 | }
 | 
|  |    149 | 
 | 
| 708 |    150 | def compile_bop(op: String, jmp: String) = op match {
 | 
|  |    151 |   case "==" => i"if_icmpne $jmp"
 | 
|  |    152 |   case "!=" => i"if_icmpeq $jmp"
 | 
|  |    153 |   case "<"  => i"if_icmpge $jmp"
 | 
|  |    154 | }
 | 
|  |    155 | 
 | 
| 710 |    156 | 
 | 
| 609 |    157 | // boolean expression compilation
 | 
| 694 |    158 | def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match {
 | 
| 707 |    159 |   case True => ""
 | 
| 694 |    160 |   case False => i"goto $jmp"
 | 
| 708 |    161 |   case Bop(op, a1, a2) => 
 | 
|  |    162 |     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_bop(op, jmp)
 | 
| 609 |    163 | }
 | 
|  |    164 | 
 | 
|  |    165 | // statement compilation
 | 
| 694 |    166 | def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match {
 | 
|  |    167 |   case Skip => ("", env)
 | 
| 609 |    168 |   case Assign(x, a) => {
 | 
| 710 |    169 |      val index = env.getOrElse(x, env.keys.size) //
 | 
|  |    170 |     (compile_aexp(a, env) ++ compile_istore(index), env + (x -> index)) 
 | 
| 609 |    171 |   } 
 | 
|  |    172 |   case If(b, bl1, bl2) => {
 | 
|  |    173 |     val if_else = Fresh("If_else")
 | 
|  |    174 |     val if_end = Fresh("If_end")
 | 
|  |    175 |     val (instrs1, env1) = compile_block(bl1, env)
 | 
|  |    176 |     val (instrs2, env2) = compile_block(bl2, env1)
 | 
|  |    177 |     (compile_bexp(b, env, if_else) ++
 | 
|  |    178 |      instrs1 ++
 | 
| 694 |    179 |      i"goto $if_end" ++
 | 
|  |    180 |      l"$if_else" ++
 | 
| 609 |    181 |      instrs2 ++
 | 
| 694 |    182 |      l"$if_end", env2)
 | 
| 609 |    183 |   }
 | 
|  |    184 |   case While(b, bl) => {
 | 
|  |    185 |     val loop_begin = Fresh("Loop_begin")
 | 
|  |    186 |     val loop_end = Fresh("Loop_end")
 | 
| 713 |    187 |     val loop_false = Fresh("Loop_false")
 | 
|  |    188 |     val loop_true = Fresh("Loop_true")
 | 
| 609 |    189 |     val (instrs1, env1) = compile_block(bl, env)
 | 
| 694 |    190 |     (l"$loop_begin" ++
 | 
| 713 |    191 |      compile_bexp(b, env, loop_false) ++
 | 
|  |    192 |      i"goto $loop_true" ++
 | 
|  |    193 |      l"$loop_false" ++
 | 
|  |    194 |      i"goto_w $loop_end" ++ 
 | 
|  |    195 |      l"$loop_true" ++
 | 
| 609 |    196 |      instrs1 ++
 | 
| 713 |    197 |      i"goto_w $loop_begin" ++
 | 
| 694 |    198 |      l"$loop_end", env1)
 | 
| 609 |    199 |   }
 | 
|  |    200 |   case Write(x) => 
 | 
| 710 |    201 |     (compile_iload(env(x)) ++
 | 
| 694 |    202 |      i"invokestatic XXX/XXX/write(I)V", env)
 | 
|  |    203 |   case Read(x) => {
 | 
|  |    204 |     val index = env.getOrElse(x, env.keys.size) 
 | 
| 710 |    205 |     (i"invokestatic XXX/XXX/read()I" ++     
 | 
|  |    206 |      compile_istore(index), env + (x -> index))
 | 
| 694 |    207 |   }
 | 
| 707 |    208 |   case ArrayDef(s: String, n: Int) => {
 | 
| 694 |    209 |     val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else 
 | 
|  |    210 |                     env.keys.size
 | 
|  |    211 |     (i"ldc $n" ++
 | 
|  |    212 |      i"newarray int" ++
 | 
|  |    213 |      i"astore $index", env + (s -> index))
 | 
|  |    214 |   }
 | 
| 612 |    215 |   case AssignA(s, a1, a2) => {
 | 
| 712 |    216 |     val arr_safe = Fresh("Arr_safe")
 | 
|  |    217 |     val arr_end = Fresh("Arr_end_")
 | 
| 612 |    218 |     val index = if (env.isDefinedAt(s)) env(s) else 
 | 
| 694 |    219 |                     throw new Exception("array not defined")
 | 
| 712 |    220 |     (compile_aexp(a1, env) ++
 | 
|  |    221 |      compile_aload(env(s)) ++
 | 
|  |    222 |      i"dup2" ++
 | 
|  |    223 |      i"arraylength" ++
 | 
|  |    224 |      i"if_icmple $arr_safe" ++
 | 
|  |    225 |      i"pop2" ++
 | 
| 713 |    226 |      i"goto_w $arr_end" ++
 | 
| 712 |    227 |      l"$arr_safe" ++
 | 
|  |    228 |      i"swap" ++
 | 
| 612 |    229 |      compile_aexp(a2, env) ++
 | 
| 712 |    230 |      i"iastore" ++
 | 
|  |    231 |      l"$arr_end", env)
 | 
| 612 |    232 |   } 
 | 
| 609 |    233 | }
 | 
|  |    234 | 
 | 
| 707 |    235 | // compilation of a block (i.e. list of statements)
 | 
| 694 |    236 | def compile_block(bl: Block, env: Env) : (String, Env) = bl match {
 | 
|  |    237 |   case Nil => ("", env)
 | 
| 609 |    238 |   case s::bl => {
 | 
|  |    239 |     val (instrs1, env1) = compile_stmt(s, env)
 | 
|  |    240 |     val (instrs2, env2) = compile_block(bl, env1)
 | 
|  |    241 |     (instrs1 ++ instrs2, env2)
 | 
|  |    242 |   }
 | 
|  |    243 | }
 | 
|  |    244 | 
 | 
| 694 |    245 | 
 | 
| 609 |    246 | // main compilation function for blocks
 | 
|  |    247 | def compile(bl: Block, class_name: String) : String = {
 | 
| 707 |    248 |   val instructions = compile_block(bl, Map())._1
 | 
|  |    249 |   (beginning ++ instructions ++ ending).replaceAllLiterally("XXX", class_name)
 | 
| 609 |    250 | }
 | 
|  |    251 | 
 | 
|  |    252 | 
 | 
| 710 |    253 | // Fibonacci numbers as a test-case
 | 
|  |    254 | val fib_test = 
 | 
|  |    255 |   List(Read("n"),                       //  read n;                     
 | 
|  |    256 |        Assign("minus1",Num(0)),         //  minus1 := 0;
 | 
|  |    257 |        Assign("minus2",Num(1)),         //  minus2 := 1;
 | 
|  |    258 |        Assign("temp",Num(0)),           //  temp := 0;
 | 
|  |    259 |        While(Bop("<",Num(0),Var("n")),  //  while n > 0 do  {
 | 
|  |    260 |           List(Assign("temp",Var("minus2")),    //  temp := minus2;
 | 
|  |    261 |                Assign("minus2",Aop("+",Var("minus1"),Var("minus2"))), 
 | 
|  |    262 |                                         //  minus2 := minus1 + minus2;
 | 
|  |    263 |                Assign("minus1",Var("temp")), //  minus1 := temp;
 | 
|  |    264 |                Assign("n",Aop("-",Var("n"),Num(1))))), //  n := n - 1 };
 | 
|  |    265 |        Write("minus1"))                 //  write minus1
 | 
|  |    266 | 
 | 
|  |    267 | // prints out the JVM-assembly instructions for fib
 | 
|  |    268 | //
 | 
|  |    269 | // println(compile(fib_test, "fib"))
 | 
|  |    270 | //
 | 
|  |    271 | // can be assembled by hand with 
 | 
|  |    272 | //
 | 
|  |    273 | //    java -jar jvm/jasmin-2.4/jasmin.jar fib.j
 | 
|  |    274 | //
 | 
|  |    275 | // and started with
 | 
|  |    276 | //
 | 
|  |    277 | //    java fib/fib
 | 
|  |    278 | 
 | 
| 609 |    279 | import scala.util._
 | 
|  |    280 | import scala.sys.process._
 | 
|  |    281 | 
 | 
|  |    282 | def time_needed[T](i: Int, code: => T) = {
 | 
|  |    283 |   val start = System.nanoTime()
 | 
| 707 |    284 |   for (j <- 2 to i) code
 | 
|  |    285 |   val result = code
 | 
| 609 |    286 |   val end = System.nanoTime()
 | 
| 707 |    287 |   ((end - start) / (i * 1.0e9), result)
 | 
|  |    288 | }
 | 
|  |    289 | 
 | 
|  |    290 | def compile_to_file(bl: Block, class_name: String) : Unit = 
 | 
|  |    291 |   Using(new java.io.FileWriter(class_name + ".j")) {
 | 
|  |    292 |     _.write(compile(bl, class_name))
 | 
|  |    293 |   }
 | 
|  |    294 | 
 | 
|  |    295 | def compile_and_run(bl: Block, class_name: String) : Unit = {
 | 
|  |    296 |   println(s"Start compilation of $class_name")
 | 
|  |    297 |   compile_to_file(bl, class_name)
 | 
|  |    298 |   println("generated .j file")
 | 
|  |    299 |   (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!!
 | 
|  |    300 |   println("generated .class file ")
 | 
| 710 |    301 |   println("Time: " + time_needed(3, (s"java ${class_name}/${class_name}").!)._1)
 | 
| 609 |    302 | }
 | 
|  |    303 | 
 | 
|  |    304 | 
 | 
| 694 |    305 | val arr_test = 
 | 
| 710 |    306 |   List(ArrayDef("a", 10),
 | 
|  |    307 |        ArrayDef("b", 2),
 | 
|  |    308 |        AssignA("a", Num(0), Num(10)),
 | 
|  |    309 |        Assign("x", Ref("a", Num(0))),
 | 
|  |    310 |        Write("x"),
 | 
|  |    311 |        AssignA("b", Num(1), Num(5)),
 | 
|  |    312 |        Assign("x", Ref("b", Num(1))),
 | 
|  |    313 |        Write("x"))       
 | 
|  |    314 | 
 | 
|  |    315 | 
 | 
|  |    316 | //compile_and_run(arr_test, "a")
 | 
|  |    317 | 
 | 
|  |    318 | //====================
 | 
|  |    319 | // Parser Combinators
 | 
|  |    320 | //====================
 | 
|  |    321 | 
 | 
|  |    322 | import scala.language.implicitConversions
 | 
|  |    323 | import scala.language.reflectiveCalls
 | 
|  |    324 | 
 | 
|  |    325 | // more convenience for the semantic actions later on
 | 
|  |    326 | case class ~[+A, +B](_1: A, _2: B)
 | 
|  |    327 | 
 | 
|  |    328 | type IsSeq[A] = A => Seq[_]
 | 
|  |    329 | 
 | 
|  |    330 | abstract class Parser[I : IsSeq, T] {
 | 
|  |    331 |   def parse(ts: I): Set[(T, I)]
 | 
|  |    332 | 
 | 
|  |    333 |   def parse_all(ts: I) : Set[T] =
 | 
|  |    334 |     for ((head, tail) <- parse(ts); if (tail.isEmpty)) yield head
 | 
|  |    335 | }
 | 
|  |    336 | 
 | 
|  |    337 | class SeqParser[I : IsSeq, T, S](p: => Parser[I, T], q: => Parser[I, S]) extends Parser[I, ~[T, S]] {
 | 
|  |    338 |   def parse(sb: I) = 
 | 
|  |    339 |     for ((head1, tail1) <- p.parse(sb); 
 | 
|  |    340 |          (head2, tail2) <- q.parse(tail1)) yield (new ~(head1, head2), tail2)
 | 
|  |    341 | }
 | 
|  |    342 | 
 | 
|  |    343 | class AltParser[I : IsSeq, T](p: => Parser[I, T], q: => Parser[I, T]) extends Parser[I, T] {
 | 
|  |    344 |   def parse(sb: I) = p.parse(sb) ++ q.parse(sb)   
 | 
|  |    345 | }
 | 
|  |    346 | 
 | 
|  |    347 | class FunParser[I : IsSeq, T, S](p: => Parser[I, T], f: T => S) extends Parser[I, S] {
 | 
|  |    348 |   def parse(sb: I) = 
 | 
|  |    349 |     for ((head, tail) <- p.parse(sb)) yield (f(head), tail)
 | 
|  |    350 | }
 | 
|  |    351 | 
 | 
|  |    352 | 
 | 
|  |    353 | import scala.util.matching.Regex
 | 
|  |    354 | case class RegexParser(reg: Regex) extends Parser[String, String] {
 | 
|  |    355 |   def parse(sb: String) = reg.findPrefixMatchOf(sb) match {
 | 
|  |    356 |     case None => Set()
 | 
|  |    357 |     case Some(m) => Set((m.matched, m.after.toString))  
 | 
|  |    358 |   }
 | 
|  |    359 | }
 | 
|  |    360 | 
 | 
|  |    361 | def StringParser(s: String) = RegexParser(Regex.quote(s).r)
 | 
|  |    362 | 
 | 
|  |    363 | 
 | 
|  |    364 | implicit def string2parser(s : String) = StringParser(s)
 | 
|  |    365 | 
 | 
|  |    366 | implicit def ParserOps[I : IsSeq, T](p: Parser[I, T]) = new {
 | 
|  |    367 |   def | (q : => Parser[I, T]) = new AltParser[I, T](p, q)
 | 
|  |    368 |   def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f)
 | 
|  |    369 |   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
 | 
|  |    370 | }
 | 
|  |    371 | 
 | 
|  |    372 | implicit def StringOps(s: String) = new {
 | 
|  |    373 |   def | (q : => Parser[String, String]) = new AltParser[String, String](s, q)
 | 
|  |    374 |   def | (r: String) = new AltParser[String, String](s, r)
 | 
|  |    375 |   def ==>[S] (f: => String => S) = new FunParser[String, String, S](s, f)
 | 
|  |    376 |   def ~[S](q : => Parser[String, S]) = 
 | 
|  |    377 |     new SeqParser[String, String, S](s, q)
 | 
|  |    378 |   def ~ (r: String) = 
 | 
|  |    379 |     new SeqParser[String, String, String](s, r)
 | 
|  |    380 | }
 | 
|  |    381 | 
 | 
|  |    382 | 
 | 
|  |    383 | val NumParser = RegexParser("[0-9]+".r) ==> (s => s.toInt : Int)
 | 
|  |    384 | val IdParser = RegexParser("[a-z][a-z,0-9]*".r)
 | 
|  |    385 | 
 | 
|  |    386 | 
 | 
|  |    387 | 
 | 
|  |    388 | // Grammar Rules for WHILE with arrays
 | 
|  |    389 | 
 | 
|  |    390 | lazy val AExp: Parser[String, AExp] = 
 | 
|  |    391 |   (Te ~ "+" ~ AExp) ==> { case x ~ _ ~ z => Aop("+", x, z):AExp } |
 | 
|  |    392 |   (Te ~ "-" ~ AExp) ==> { case x ~ _ ~ z => Aop("-", x, z):AExp } | Te
 | 
|  |    393 | lazy val Te: Parser[String, AExp] = 
 | 
|  |    394 |   (Fa ~ "*" ~ Te) ==> { case x ~ _ ~ z => Aop("*", x, z):AExp } | Fa
 | 
|  |    395 | lazy val Fa: Parser[String, AExp] = 
 | 
|  |    396 |    ("(" ~ AExp ~ ")") ==> { case _ ~ y ~ _ => y } | 
 | 
|  |    397 |    (IdParser ~ "[" ~ AExp ~ "]") ==> { case x ~ _ ~ y ~ _ => Ref(x, y) } |
 | 
|  |    398 |    IdParser ==> Var | 
 | 
|  |    399 |    NumParser ==> Num
 | 
|  |    400 | 
 | 
|  |    401 | // boolean expressions
 | 
|  |    402 | lazy val BExp: Parser[String, BExp] = 
 | 
|  |    403 |    (AExp ~ "=" ~ AExp) ==> { case x ~ y ~ z => Bop("=", x, z):BExp } | 
 | 
|  |    404 |    (AExp ~ "!=" ~ AExp) ==> { case x ~ y ~ z => Bop("!=", x, z):BExp } | 
 | 
|  |    405 |    (AExp ~ "<" ~ AExp) ==> { case x ~ y ~ z => Bop("<", x, z):BExp } | 
 | 
|  |    406 |    (AExp ~ ">" ~ AExp) ==> { case x ~ y ~ z => Bop("<", z, x):BExp } | 
 | 
|  |    407 |    ("true" ==> ((_) => True:BExp )) | 
 | 
|  |    408 |    ("false" ==> ((_) => False:BExp )) |
 | 
|  |    409 |    ("(" ~ BExp ~ ")") ==> { case x ~ y ~ z => y}
 | 
|  |    410 | 
 | 
|  |    411 | lazy val Stmt: Parser[String, Stmt] =
 | 
|  |    412 |    ("skip" ==> (_ => Skip: Stmt)) |
 | 
|  |    413 |    (IdParser ~ ":=" ~ AExp) ==> { case x ~ y ~z => Assign(x, z): Stmt } |
 | 
|  |    414 |    (IdParser ~ "[" ~ AExp ~ "]" ~ ":=" ~ AExp) ==> { 
 | 
|  |    415 |      case x ~ _ ~ z ~ _ ~ _ ~ u => AssignA(x, z, u): Stmt } |
 | 
|  |    416 |    ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==>
 | 
|  |    417 |     { case _ ~ y ~ _ ~ u ~ _ ~w => If(y, u, w): Stmt } |
 | 
|  |    418 |    ("while" ~ BExp ~ "do" ~ Block) ==> { case _ ~ y ~ _ ~ w => While(y, w) } |
 | 
|  |    419 |    ("new(" ~ IdParser ~ "[" ~ NumParser ~ "])") ==> { 
 | 
|  |    420 |     case _ ~ y ~ _ ~ u ~ _ => ArrayDef(y, u) } |
 | 
|  |    421 |    ("write" ~ IdParser) ==> { case _ ~ y => Write(y) } 
 | 
|  |    422 |  
 | 
|  |    423 | lazy val Stmts: Parser[String, Block] =
 | 
|  |    424 |   (Stmt ~ ";" ~ Stmts) ==> { case x ~ _ ~ z => x :: z : Block } |
 | 
|  |    425 |   (Stmt ==> ((s) => List(s) : Block)) 
 | 
|  |    426 | 
 | 
|  |    427 | 
 | 
|  |    428 | lazy val Block: Parser[String, Block] =
 | 
|  |    429 |    ("{" ~ Stmts ~ "}") ==> { case _ ~ y ~ _ => y} | 
 | 
|  |    430 |    (Stmt ==> (s => List(s)))
 | 
|  |    431 | 
 | 
|  |    432 | //Stmts.parse_all("x2:=5+a")
 | 
|  |    433 | //Stmts.parse_all("x2:=5+a[3+a]")
 | 
|  |    434 | //Stmts.parse_all("a[x2+3]:=5+a[3+a]")
 | 
|  |    435 | //Block.parse_all("{x:=5;y:=8}")
 | 
|  |    436 | //Block.parse_all("if(false)then{x:=5}else{x:=10}")
 | 
|  |    437 | 
 | 
|  |    438 | 
 | 
|  |    439 | 
 | 
|  |    440 | val fib = """
 | 
|  |    441 |    n := 10;
 | 
|  |    442 |    minus1 := 0;
 | 
|  |    443 |    minus2 := 1;
 | 
|  |    444 |    temp:=0;
 | 
|  |    445 |    while (n > 0) do {
 | 
|  |    446 |      temp := minus2; 
 | 
|  |    447 |      minus2 := minus1 + minus2;
 | 
|  |    448 |      minus1 := temp;
 | 
|  |    449 |      n := n - 1};
 | 
|  |    450 |    result := minus2;
 | 
|  |    451 |    write result
 | 
|  |    452 |    """.replaceAll("\\s+", "")
 | 
|  |    453 | 
 | 
|  |    454 | val fib_prog = Stmts.parse_all(fib).toList
 | 
|  |    455 | //compile_and_run(fib_prog.head, "fib")
 | 
|  |    456 | 
 | 
|  |    457 | //======================================
 | 
|  |    458 | // BF transpiler into WHILE with arrays
 | 
|  |    459 | //======================================
 | 
|  |    460 | 
 | 
|  |    461 | // simple BF instructions translation
 | 
|  |    462 | def instr(c: Char) : String = c match {
 | 
|  |    463 |   case '>' => "ptr := ptr + 1;"
 | 
|  |    464 |   case '<' => "ptr := ptr - 1;"
 | 
|  |    465 |   case '+' => "mem[ptr] := mem[ptr] + 1;"
 | 
|  |    466 |   case '-' => "mem[ptr] := mem[ptr] - 1;"
 | 
|  |    467 |   case '.' => "x := mem[ptr]; write x;"
 | 
|  |    468 |   //case ',' => "XXX" // "ptr = getchar();\n"
 | 
|  |    469 |   case '['  => "while (mem[ptr] != 0) do {"
 | 
|  |    470 |   case ']'  => "skip};"
 | 
|  |    471 |   case _ => ""
 | 
|  |    472 | }
 | 
|  |    473 | 
 | 
|  |    474 | def instrs(prog: String) : String =
 | 
|  |    475 |   prog.toList.map(instr).mkString
 | 
| 616 |    476 | 
 | 
|  |    477 | 
 | 
| 710 |    478 | // Note: the mandelbrot.bf program is so large that
 | 
|  |    479 | // it does not fit inside the limitations of what the
 | 
|  |    480 | // JVM imposes on methods (only 64K of instructions).
 | 
|  |    481 | // Therefore some optimisations are first applied to 
 | 
|  |    482 | // BF programs before WHILE programs are created. The
 | 
|  |    483 | // optimisations are 
 | 
|  |    484 | //  
 | 
|  |    485 | //  - replacing BF-loops of the form [-] 
 | 
|  |    486 | //  - combining single increment/decrement instructions
 | 
|  |    487 | //
 | 
|  |    488 | // The size of the resulting .j-file is 270K.
 | 
|  |    489 | 
 | 
|  |    490 | def splice(cs: List[Char], acc: List[(Char, Int)]) : List[(Char, Int)] = (cs, acc) match {
 | 
|  |    491 |   case (Nil, acc) => acc
 | 
|  |    492 |   case (c :: cs, Nil) => splice(cs, List((c, 1)))
 | 
|  |    493 |   case (c :: cs, (d, n) :: acc) => 
 | 
|  |    494 |     if (c == d) splice(cs, (c, n + 1) :: acc)
 | 
|  |    495 |     else splice(cs, (c, 1) :: (d, n) :: acc)
 | 
|  |    496 | }
 | 
|  |    497 | 
 | 
|  |    498 | def spl(s: String) = splice(s.toList, Nil).reverse
 | 
|  |    499 | 
 | 
|  |    500 | def instr2(c: Char, n: Int) : String = c match {
 | 
|  |    501 |   case '>' => s"ptr := ptr + $n;"
 | 
|  |    502 |   case '<' => s"ptr := ptr - $n;"
 | 
|  |    503 |   case '0' => s"mem[ptr] := 0;"
 | 
|  |    504 |   case '+' => s"mem[ptr] := mem[ptr] + $n;"
 | 
|  |    505 |   case '-' => s"mem[ptr] := mem[ptr] - $n;"
 | 
|  |    506 |   case '.' => s"x := mem[ptr]; write x;" 
 | 
|  |    507 |   case '['  => "while (mem[ptr] != 0) do {" * n 
 | 
|  |    508 |   case ']'  => "skip};" * n
 | 
|  |    509 |   case _ => ""
 | 
|  |    510 | }
 | 
|  |    511 | 
 | 
|  |    512 | def instrs2(prog: String) : String =
 | 
|  |    513 |   spl(prog.replaceAll("""\[-\]""", "0")).map{ case (c, n) => instr2(c, n) }.mkString
 | 
|  |    514 | 
 | 
|  |    515 | def bf_str(prog: String) : String = {
 | 
|  |    516 |   "new(mem[30000]);" ++
 | 
|  |    517 |   "ptr := 15000;" ++
 | 
|  |    518 |   instrs2(prog) ++
 | 
|  |    519 |   "skip"
 | 
|  |    520 | }
 | 
|  |    521 | 
 | 
|  |    522 | def bf_run(prog: String, name: String) = {
 | 
|  |    523 |   println(s"BF pre-processing of $name")
 | 
|  |    524 |   val bf_string = bf_str(prog).replaceAll("\\s", "")
 | 
|  |    525 |   println(s"BF parsing (program length ${bf_string.length} characters)")
 | 
|  |    526 |   val (time, bf_prog) = time_needed(1, Stmts.parse_all(bf_string).toList.head)
 | 
|  |    527 |   println(s"BF generated WHILE program (needed $time for parsing)")
 | 
|  |    528 |   compile_and_run(bf_prog, name)
 | 
|  |    529 | }
 | 
|  |    530 | 
 | 
|  |    531 | // a benchmark program (counts down from 'Z' to 'A')
 | 
|  |    532 | val bf0 = """>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
 | 
|  |    533 |             [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
 | 
|  |    534 |             ++++++++[>++++++++++[>++++++++++[>++++++++++[>+
 | 
|  |    535 |             +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++."""
 | 
|  |    536 | 
 | 
|  |    537 | bf_run(bf0, "bench")
 | 
|  |    538 | 
 | 
|  |    539 | // Sierpinski triangle
 | 
|  |    540 | val bf1 = """++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[
 | 
|  |    541 |       ->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<
 | 
|  |    542 |       ]>.>+[>>]>+]"""
 | 
|  |    543 | 
 | 
|  |    544 | bf_run(bf1, "sier")
 | 
|  |    545 | 
 | 
|  |    546 | // Helo World!
 | 
|  |    547 | bf_run("""++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++
 | 
|  |    548 |        ..+++.>>.<-.<.+++.------.--------.>>+.>++.""", "hello")
 | 
|  |    549 | 
 | 
|  |    550 | // Fibonacci 
 | 
|  |    551 | val bf2 = """+++++++++++
 | 
|  |    552 |       >+>>>>++++++++++++++++++++++++++++++++++++++++++++
 | 
|  |    553 |       >++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>
 | 
|  |    554 |       +<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-
 | 
|  |    555 |       <-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<
 | 
|  |    556 |       -]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]
 | 
|  |    557 |       >[<<+>>[-]]<<<<<<<]>>>>>[+++++++++++++++++++++++++
 | 
|  |    558 |       +++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++
 | 
|  |    559 |       ++++++++++++++++++++++++++++++++++++++++++++.[-]<<
 | 
|  |    560 |       <<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<
 | 
| 712 |    561 |       [-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]
 | 
|  |    562 |       [-]++++++++++."""
 | 
| 710 |    563 | 
 | 
|  |    564 | bf_run(bf2, "fibs")
 | 
|  |    565 | 
 | 
|  |    566 | // Mandelbrot Set
 | 
|  |    567 | //----------------
 | 
|  |    568 | //
 | 
|  |    569 | // Note: Parsing of the generated WHILE program (around 60K in size)
 | 
|  |    570 | // takes approximately 10 minutes
 | 
|  |    571 | 
 | 
|  |    572 | 
 | 
| 694 |    573 | 
 | 
| 710 |    574 | bf_run("""A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
 | 
|  |    575 | +++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
 | 
|  |    576 | >>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
 | 
|  |    577 | <<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
|  |    578 | >+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>>
 | 
|  |    579 | >>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>>
 | 
|  |    580 | >>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>>
 | 
|  |    581 | >>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>
 | 
|  |    582 | [>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<
 | 
|  |    583 | <<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[
 | 
|  |    584 | >>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[
 | 
|  |    585 | >+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[
 | 
|  |    586 | -<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<
 | 
|  |    587 | <<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<
 | 
|  |    588 | [>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>
 | 
|  |    589 | >>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+
 | 
|  |    590 | <<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>
 | 
|  |    591 | >>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<
 | 
|  |    592 | +>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<
 | 
|  |    593 | <]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>
 | 
|  |    594 | >>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
 | 
|  |    595 | >>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<
 | 
|  |    596 | <<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<
 | 
|  |    597 | <<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->
 | 
|  |    598 | >>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<
 | 
|  |    599 | <<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++
 | 
|  |    600 | +++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>-
 | 
|  |    601 | <<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>>
 | 
|  |    602 | [-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<<
 | 
|  |    603 | <+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[-
 | 
|  |    604 | ]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<<
 | 
|  |    605 | <<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]<
 | 
|  |    606 | <[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>>
 | 
|  |    607 | >>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>>
 | 
|  |    608 | [-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<
 | 
|  |    609 | <<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>>
 | 
|  |    610 | ]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+
 | 
|  |    611 | >>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
 | 
|  |    612 | [->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
 | 
|  |    613 | ]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
 | 
|  |    614 | [>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
|  |    615 | ]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>
 | 
|  |    616 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++
 | 
|  |    617 | +++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+
 | 
|  |    618 | >>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[
 | 
|  |    619 | -]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-<
 | 
|  |    620 | <<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<
 | 
|  |    621 | [->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]
 | 
|  |    622 | +>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<<
 | 
|  |    623 | <<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<
 | 
|  |    624 | [<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<
 | 
|  |    625 | <<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<
 | 
|  |    626 | <<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<
 | 
|  |    627 | <<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<<
 | 
|  |    628 | <<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<<
 | 
|  |    629 | <<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<<
 | 
|  |    630 | ]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<<
 | 
|  |    631 | [>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<<
 | 
|  |    632 | +>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<<
 | 
|  |    633 | <<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<
 | 
|  |    634 | <<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[
 | 
|  |    635 | [>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+
 | 
|  |    636 | [>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>
 | 
|  |    637 | [-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<
 | 
|  |    638 | <[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[
 | 
|  |    639 | >[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[
 | 
|  |    640 | >>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>
 | 
|  |    641 | >>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<
 | 
|  |    642 | <<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<
 | 
|  |    643 | <<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-
 | 
|  |    644 | <<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>
 | 
|  |    645 | >>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>>
 | 
|  |    646 | [-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<<
 | 
|  |    647 | +>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]>
 | 
|  |    648 | [-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>
 | 
|  |    649 | >>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>>
 | 
|  |    650 | >>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<<
 | 
|  |    651 | ]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<<
 | 
|  |    652 | <+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>
 | 
|  |    653 | >]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<<
 | 
|  |    654 | <<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<
 | 
|  |    655 | <<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]<
 | 
|  |    656 | <<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<
 | 
|  |    657 | <<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+
 | 
|  |    658 | <]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>-
 | 
|  |    659 | <<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<<
 | 
|  |    660 | ]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+>
 | 
|  |    661 | >>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>-
 | 
|  |    662 | <<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[
 | 
|  |    663 | ->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>
 | 
|  |    664 | >>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>>
 | 
|  |    665 | >>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<
 | 
|  |    666 | <<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<
 | 
|  |    667 | <<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+
 | 
|  |    668 | >>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>>
 | 
|  |    669 | ]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
 | 
|  |    670 | >>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>
 | 
|  |    671 | >>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+
 | 
|  |    672 | >>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
 | 
|  |    673 | [->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
 | 
|  |    674 | ]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
 | 
|  |    675 | [>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<
 | 
|  |    676 | <<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>
 | 
|  |    677 | >>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>>
 | 
|  |    678 | >>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+
 | 
|  |    679 | <<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
 | 
|  |    680 | >>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>
 | 
|  |    681 | >]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<]
 | 
|  |    682 | >>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<
 | 
|  |    683 | ]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+<
 | 
|  |    684 | <<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>
 | 
|  |    685 | >>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<<
 | 
|  |    686 | ->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[
 | 
|  |    687 | >[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<<
 | 
|  |    688 | [<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<<
 | 
|  |    689 | <<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<<
 | 
|  |    690 | <<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<<
 | 
|  |    691 | <<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>>
 | 
|  |    692 | >+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<
 | 
|  |    693 | <<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]<
 | 
|  |    694 | +<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>>
 | 
|  |    695 | >>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<
 | 
|  |    696 | <<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<<
 | 
|  |    697 | <<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<<
 | 
|  |    698 | <<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-<
 | 
|  |    699 | <<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<
 | 
|  |    700 | <<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<
 | 
|  |    701 | <<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<<
 | 
|  |    702 | <<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>>
 | 
|  |    703 | >+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<
 | 
|  |    704 | <<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>>
 | 
|  |    705 | >]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<
 | 
|  |    706 | <<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>>
 | 
|  |    707 | >>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<-
 | 
|  |    708 | >>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<
 | 
|  |    709 | <<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>>
 | 
|  |    710 | >>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<
 | 
|  |    711 | <<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>
 | 
|  |    712 | +>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+<
 | 
|  |    713 | <<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<
 | 
|  |    714 | <<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>
 | 
|  |    715 | -<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>
 | 
|  |    716 | >>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
 | 
|  |    717 | +[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
 | 
|  |    718 | <<<<<]]>>>]""", "mand")
 | 
|  |    719 | 
 | 
|  |    720 | 
 |