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