progs/compile_arr.scala
changeset 710 183663740fb7
parent 709 c112a6cb5e52
child 712 e71eb9ce2373
equal deleted inserted replaced
709:c112a6cb5e52 710:183663740fb7
     6 //  - transpiles BF programs into WHILE programs
     6 //  - transpiles BF programs into WHILE programs
     7 //    and compiles and runs them
     7 //    and compiles and runs them
     8 //
     8 //
     9 // Call with
     9 // Call with
    10 //
    10 //
    11 // scala compiler_arr.scala
    11 // scala compile_arr.scala
    12 
    12 
    13 
    13 
       
    14 // Mandelbrot
       
    15 // mand.j size       236241
       
    16 // mand.class size   33296
       
    17 // running time      21 secs
    14 
    18 
    15 // the abstract syntax trees
    19 // the abstract syntax trees
    16 abstract class Stmt
    20 abstract class Stmt
    17 abstract class AExp
    21 abstract class AExp
    18 abstract class BExp 
    22 abstract class BExp 
    99   case "+" => i"iadd"
   103   case "+" => i"iadd"
   100   case "-" => i"isub"
   104   case "-" => i"isub"
   101   case "*" => i"imul"
   105   case "*" => i"imul"
   102 }
   106 }
   103 
   107 
   104 def compile_num(i: Int) = 
       
   105   if (0 <= i && i <= 5) i"iconst_$i" else i"ldc $i"
       
   106 
       
   107 def compile_aload(i: Int) = 
       
   108   if (0 <= i && i <= 3) i"aload_$i" else i"aload $i"
       
   109 
       
   110 def compile_iload(i: Int) = 
       
   111   if (0 <= i && i <= 3) i"iload_$i" else i"iload $i"
       
   112 
       
   113 def compile_istore(i: Int) = 
       
   114   if (0 <= i && i <= 3) i"istore_$i" else i"istore $i"
       
   115 
       
   116 // arithmetic expression compilation
   108 // arithmetic expression compilation
   117 def compile_aexp(a: AExp, env : Env) : String = a match {
   109 def compile_aexp(a: AExp, env : Env) : String = a match {
   118   case Num(i) => compile_num(i)
   110   case Num(i) => i"ldc $i"
   119   case Var(s) => compile_iload(env(s))
   111   case Var(s) => i"iload ${env(s)}"
   120   case Aop(op, a1, a2) => 
   112   case Aop(op, a1, a2) => 
   121     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op)
   113     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_op(op)
   122   case Ref(s, a) => 
   114   case Ref(s, a) =>
   123     compile_aload(env(s)) ++ compile_aexp(a, env) ++  i"iaload"
   115     i"aload ${env(s)}" ++ compile_aexp(a, env) ++  i"iaload"
   124 }
   116 }
   125 
       
   126 def compile_bop(op: String, jmp: String) = op match {
       
   127   case "==" => i"if_icmpne $jmp"
       
   128   case "!=" => i"if_icmpeq $jmp"
       
   129   case "<"  => i"if_icmpge $jmp"
       
   130 }
       
   131 
       
   132 
   117 
   133 // boolean expression compilation
   118 // boolean expression compilation
   134 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match {
   119 def compile_bexp(b: BExp, env : Env, jmp: String) : String = b match {
   135   case True => ""
   120   case True => ""
   136   case False => i"goto $jmp"
   121   case False => i"goto $jmp"
   137   case Bop(op, a1, a2) => 
   122   case Bop("==", a1, a2) => 
   138     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ compile_bop(op, jmp)
   123     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpne $jmp"
       
   124   case Bop("!=", a1, a2) => 
       
   125     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpeq $jmp"
       
   126   case Bop("<", a1, a2) => 
       
   127     compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ i"if_icmpge $jmp"
   139 }
   128 }
   140 
   129 
   141 // statement compilation
   130 // statement compilation
   142 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match {
   131 def compile_stmt(s: Stmt, env: Env) : (String, Env) = s match {
   143   case Skip => ("", env)
   132   case Skip => ("", env)
   144   case Assign(x, a) => {
   133   case Assign(x, a) => {
   145      val index = env.getOrElse(x, env.keys.size) //
   134      val index = env.getOrElse(x, env.keys.size)
   146     (compile_aexp(a, env) ++ compile_istore(index), env + (x -> index)) 
   135     (compile_aexp(a, env) ++ i"istore $index \t\t; $x", env + (x -> index)) 
   147   } 
   136   } 
   148   case If(b, bl1, bl2) => {
   137   case If(b, bl1, bl2) => {
   149     val if_else = Fresh("If_else")
   138     val if_else = Fresh("If_else")
   150     val if_end = Fresh("If_end")
   139     val if_end = Fresh("If_end")
   151     val (instrs1, env1) = compile_block(bl1, env)
   140     val (instrs1, env1) = compile_block(bl1, env)
   166      instrs1 ++
   155      instrs1 ++
   167      i"goto $loop_begin" ++
   156      i"goto $loop_begin" ++
   168      l"$loop_end", env1)
   157      l"$loop_end", env1)
   169   }
   158   }
   170   case Write(x) => 
   159   case Write(x) => 
   171     (compile_iload(env(x)) ++
   160     (i"iload ${env(x)} \t\t; $x" ++ 
   172      i"invokestatic XXX/XXX/write(I)V", env)
   161      i"invokestatic XXX/XXX/write(I)V", env)
   173   case Read(x) => {
   162   case Read(x) => {
   174     val index = env.getOrElse(x, env.keys.size) 
   163     val index = env.getOrElse(x, env.keys.size) 
   175     (i"invokestatic XXX/XXX/read()I" ++     
   164     (i"invokestatic XXX/XXX/read()I" ++ 
   176      compile_istore(index), env + (x -> index))
   165      i"istore $index \t\t; $x", env + (x -> index))
   177   }
   166   }
   178   case ArrayDef(s: String, n: Int) => {
   167   case ArrayDef(s: String, n: Int) => {
   179     val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else 
   168     val index = if (env.isDefinedAt(s)) throw new Exception("array def error") else 
   180                     env.keys.size
   169                     env.keys.size
   181     (i"ldc $n" ++
   170     (i"ldc $n" ++
   183      i"astore $index", env + (s -> index))
   172      i"astore $index", env + (s -> index))
   184   }
   173   }
   185   case AssignA(s, a1, a2) => {
   174   case AssignA(s, a1, a2) => {
   186     val index = if (env.isDefinedAt(s)) env(s) else 
   175     val index = if (env.isDefinedAt(s)) env(s) else 
   187                     throw new Exception("array not defined")
   176                     throw new Exception("array not defined")
   188     (compile_aload(env(s)) ++
   177     (i"aload ${env(s)}" ++
   189      compile_aexp(a1, env) ++
   178      compile_aexp(a1, env) ++
   190      compile_aexp(a2, env) ++
   179      compile_aexp(a2, env) ++
   191      i"iastore", env)
   180      i"iastore", env)
   192   } 
   181   } 
   193 }
   182 }
   376    ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==>
   365    ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==>
   377     { case _ ~ y ~ _ ~ u ~ _ ~w => If(y, u, w): Stmt } |
   366     { case _ ~ y ~ _ ~ u ~ _ ~w => If(y, u, w): Stmt } |
   378    ("while" ~ BExp ~ "do" ~ Block) ==> { case _ ~ y ~ _ ~ w => While(y, w) } |
   367    ("while" ~ BExp ~ "do" ~ Block) ==> { case _ ~ y ~ _ ~ w => While(y, w) } |
   379    ("new(" ~ IdParser ~ "[" ~ NumParser ~ "])") ==> { 
   368    ("new(" ~ IdParser ~ "[" ~ NumParser ~ "])") ==> { 
   380     case _ ~ y ~ _ ~ u ~ _ => ArrayDef(y, u) } |
   369     case _ ~ y ~ _ ~ u ~ _ => ArrayDef(y, u) } |
   381    ("write" ~ IdParser) ==> { case _ ~ y => Write(y) } 
   370    ("write(" ~ IdParser ~ ")") ==> { case _ ~ y ~ _ => Write(y) } 
   382  
   371  
   383 lazy val Stmts: Parser[String, Block] =
   372 lazy val Stmts: Parser[String, Block] =
   384   (Stmt ~ ";" ~ Stmts) ==> { case x ~ _ ~ z => x :: z : Block } |
   373   (Stmt ~ ";" ~ Stmts) ==> { case x ~ _ ~ z => x :: z : Block } |
   385   (Stmt ==> ((s) => List(s) : Block)) 
   374   (Stmt ==> ((s) => List(s) : Block)) 
   386 
   375 
   406      temp := minus2; 
   395      temp := minus2; 
   407      minus2 := minus1 + minus2;
   396      minus2 := minus1 + minus2;
   408      minus1 := temp;
   397      minus1 := temp;
   409      n := n - 1};
   398      n := n - 1};
   410    result := minus2;
   399    result := minus2;
   411    write result
   400    write(result)
   412    """.replaceAll("\\s+", "")
   401    """.replaceAll("\\s+", "")
   413 
   402 
   414 val fib_prog = Stmts.parse_all(fib).toList
   403 val fib_prog = Stmts.parse_all(fib).toList
   415 //compile_and_run(fib_prog.head, "fib")
   404 //compile_and_run(fib_prog.head, "fib")
   416 
   405 
   523 bf_run(bf2, "fibs")
   512 bf_run(bf2, "fibs")
   524 
   513 
   525 // Mandelbrot Set
   514 // Mandelbrot Set
   526 //----------------
   515 //----------------
   527 //
   516 //
   528 // Note: Parsing of the generated WHILE program (around 56K in size)
   517 // Note: Parsing of the generated WHILE program (around 60K in size)
   529 // takes approximately 10 minutes. The final class file runs
   518 // takes approximately 10 minutes
   530 // for around 23 seconds.
   519 
       
   520 
   531 
   521 
   532 bf_run("""A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
   522 bf_run("""A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
   533 +++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
   523 +++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
   534 >>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
   524 >>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
   535 <<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
   525 <<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
   674 >>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
   664 >>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
   675 +[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
   665 +[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
   676 <<<<<]]>>>]""", "mand")
   666 <<<<<]]>>>]""", "mand")
   677 
   667 
   678 
   668 
       
   669 
       
   670 
       
   671 //===============
       
   672 // For peephole profiling
       
   673 // 
       
   674 /*
       
   675 val loops = """
       
   676   start := 180000; 
       
   677   x1 := start;
       
   678   x2 := start;
       
   679   x3 := start;
       
   680   while (0 < x1) do {
       
   681     while (0 < x2) do {
       
   682       while (0 < x3) do { x3 := x3 - 1 };
       
   683       x3 := start;
       
   684       x2 := x2 - 1
       
   685     };     
       
   686   x2 := start;
       
   687   x1 := x1 - 1
       
   688   }""".replaceAll("\\s+", "")
       
   689 
       
   690 val loops_prog = Stmts.parse_all(loops).toList
       
   691 compile_to_file(loops_prog.head, "loops")
       
   692 compile_and_run(loops_prog.head, "loops")
       
   693 */