progs/while-arrays/compile_bfc.sc
changeset 949 61797848eede
parent 943 5365ef60707e
child 956 ae9782e62bdd
equal deleted inserted replaced
948:6bb67c2dcfd3 949:61797848eede
    11 //       * 65k for the transpiled WHILE program 
    11 //       * 65k for the transpiled WHILE program 
    12 //       * parsing uses around 30 secs using fastparse
    12 //       * parsing uses around 30 secs using fastparse
    13 //       * the jasmin assembly file is 236k
    13 //       * the jasmin assembly file is 236k
    14 //       * the resulting Java program takes about 20 secs 
    14 //       * the resulting Java program takes about 20 secs 
    15 //
    15 //
    16 // Call with (X being 0,1,..,4)
    16 //
    17 //
    17 // Call with scala-cli:
    18 //  amm compile_bfc.sc all
    18 //
    19 //  amm compile_bfc.sc bfcX
    19 //  scala-cli --dep com.lihaoyi::fastparse:3.0.2  compile_bfc.sc 
    20 
    20 //
    21 
    21 // Scala-cli is another REPL for scala. Unfortunately
    22 // load the compiler
    22 // fastparse used in this file is not yet supported
    23 import $file.compile_arrays2
    23 // under ammonite.
    24 import compile_arrays2._ 
    24 
       
    25 
       
    26 //> using toolkit latest
       
    27 //> using file compile_arrays2.sc
       
    28 import compile_arrays2._
    25 
    29 
    26 def time_needed[T](i: Int, code: => T) = {
    30 def time_needed[T](i: Int, code: => T) = {
    27   val start = System.nanoTime()
    31   val start = System.nanoTime()
    28   for (j <- 2 to i) code
    32   for (j <- 2 to i) code
    29   val result = code
    33   val result = code
    70 // post 2.5.0 ammonite
    74 // post 2.5.0 ammonite
    71 import os._
    75 import os._
    72 
    76 
    73 
    77 
    74 def compile_to_file(bl: Block, class_name: String) : Unit = 
    78 def compile_to_file(bl: Block, class_name: String) : Unit = 
    75   write.over(pwd / s"$class_name.j", compile(bl, class_name))  
    79   os.write.over(os.pwd / s"$class_name.j", compile(bl, class_name))  
    76 
    80 
    77 def compile_and_run(bl: Block, class_name: String) : Unit = {
    81 def compile_and_run(bl: Block, class_name: String) : Unit = {
    78   println(s"Start of compilation")
    82   println(s"Start of compilation")
    79   compile_to_file(bl, class_name)
    83   compile_to_file(bl, class_name)
    80   println(s"generated $class_name.j file")
    84   println(s"generated $class_name.j file")
    90 
    94 
    91 //=====================================
    95 //=====================================
    92 // Grammar Rules for WHILE with arrays
    96 // Grammar Rules for WHILE with arrays
    93 //=====================================
    97 //=====================================
    94 
    98 
    95 import $ivy.`com.lihaoyi::fastparse:3.0.2`
    99 //> using dep com.lihaoyi::fastparse:3.0.2
       
   100 
    96 import fastparse._
   101 import fastparse._
    97 import MultiLineWhitespace._
   102 import MultiLineWhitespace._
    98 
   103 
    99 def string[A: P]: P[String]   = P(CharIn("a-zA-Z0-9").rep(1).!)
       
   100 
       
   101 /*
       
   102 def lowercase [$ : P] = P( CharIn("a-z") )
   104 def lowercase [$ : P] = P( CharIn("a-z") )
   103 def uppercase[$ : P]  = P( CharIn("A-Z") )
   105 def uppercase[$ : P]  = P( CharIn("A-Z") )
   104 def letter[$ : P]     = P( lowercase | uppercase )
   106 def letter[$ : P]     = P( lowercase | uppercase )
   105 def digit [$ : P]     = P( CharIn("0-9") )
   107 def digit [$ : P]     = P( CharIn("0-9") )
   106 
   108 
   115 def Te[$ : P]: P[AExp] = 
   117 def Te[$ : P]: P[AExp] = 
   116   P(  P(Fa ~ "*" ~ Te).map{ case (l, r) => Aop("*", l, r)} 
   118   P(  P(Fa ~ "*" ~ Te).map{ case (l, r) => Aop("*", l, r)} 
   117     | Fa )   
   119     | Fa )   
   118 def Fa[$ : P]: P[AExp] = 
   120 def Fa[$ : P]: P[AExp] = 
   119   P( "(" ~ AExp ~ ")" 
   121   P( "(" ~ AExp ~ ")" 
   120      | P (Ident ~ "[" ~ AExp ~ "]").map{Ref.tupled}
   122      | P (Ident ~ "[" ~ AExp ~ "]").map{Ref(_, _)}
   121      | P(Number).map{Num} 
   123      | P(Number).map{Num} 
   122      | P(Ident).map{Var} )
   124      | P(Ident).map{Var} )
   123 
   125 
   124 // boolean expressions
   126 // boolean expressions
   125 def BExp[$ : P]: P[BExp] = 
   127 def BExp[$ : P]: P[BExp] = 
   132     | "(" ~ BExp ~ ")" )
   134     | "(" ~ BExp ~ ")" )
   133 
   135 
   134 // statements and blocks
   136 // statements and blocks
   135 def Stmt[$ : P]: P[Stmt] =
   137 def Stmt[$ : P]: P[Stmt] =
   136   P(  P("skip").map( _ => Skip) 
   138   P(  P("skip").map( _ => Skip) 
   137     | P(Ident ~ ":=" ~ AExp).map{Assign.tupled} 
   139     | P(Ident ~ ":=" ~ AExp).map{Assign(_, _)} 
   138     | P(Ident ~ "[" ~ AExp ~ "]" ~ ":=" ~ AExp).map{AssignA.tupled} 
   140     | P(Ident ~ "[" ~ AExp ~ "]" ~ ":=" ~ AExp).map{AssignA(_, _, _)} 
   139     | P("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block).map{If.tupled} 
   141     | P("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block).map{If(_, _, _)} 
   140     | P("while" ~ BExp ~ "do" ~ Block).map{While.tupled} 
   142     | P("while" ~ BExp ~ "do" ~ Block).map{While(_, _)} 
   141     | P("new(" ~ Ident ~ "[" ~ Number ~ "])").map{ArrayDef.tupled} 
   143     | P("new(" ~ Ident ~ "[" ~ Number ~ "])").map{ArrayDef(_, _)} 
   142     | P("write(" ~ Ident ~ ")").map{Write} ) 
   144     | P("write(" ~ Ident ~ ")").map{Write} ) 
   143 
   145 
   144 def Stmts[$ : P]: P[Block] =
   146 def Stmts[$ : P]: P[Block] =
   145   P(  P(Stmt ~ ";" ~ Stmts).map{ case (x, z) => x :: z } 
   147   P(  P(Stmt ~ ";" ~ Stmts).map{ case (x, z) => x :: z } 
   146     | P(Stmt).map{s => List(s)} ) 
   148     | P(Stmt).map{s => List(s)} ) 
   257   compile_and_run(bf_prog, name)
   259   compile_and_run(bf_prog, name)
   258 }
   260 }
   259 
   261 
   260 // a benchmark program (counts down from 'Z' to 'A')
   262 // a benchmark program (counts down from 'Z' to 'A')
   261 //@doc(" Benchmark 'Z' to 'A'.")
   263 //@doc(" Benchmark 'Z' to 'A'.")
   262 @main
   264 //@main
   263 def bfc0() = bf_run(read(pwd / "benchmark.bf"), "bench")
   265 def bfc0() = bf_run(read(pwd / "benchmark.bf"), "bench")
   264 
   266 
   265 
   267 
   266 //@doc(" Sierpinski triangle.")
   268 //@doc(" Sierpinski triangle.")
   267 @main
   269 //@main
   268 def bfc1() = bf_run(read(pwd / "sierpinski.bf"), "sier")
   270 def bfc1() = bf_run(read(pwd / "sierpinski.bf"), "sier")
   269 
   271 
   270 // Hello World
   272 // Hello World
   271 val bf2 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]
   273 val bf2 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]
   272       >>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."""
   274       >>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."""
   273 
   275 
   274 //@doc(" Hello world.")
   276 //@doc(" Hello world.")
   275 @main
   277 //@main
   276 def bfc2() = bf_run(bf2, "hello")
   278 def bfc2() = bf_run(bf2, "hello")
   277 
   279 
   278 // Fibonacci 
   280 // Fibonacci 
   279 val bf3 = """+++++++++++
   281 val bf3 = """+++++++++++
   280       >+>>>>++++++++++++++++++++++++++++++++++++++++++++
   282       >+>>>>++++++++++++++++++++++++++++++++++++++++++++
   288       <<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<
   290       <<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<
   289       [-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]
   291       [-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]
   290       [-]++++++++++."""
   292       [-]++++++++++."""
   291 
   293 
   292 //@doc(" Fibonacci numbers.")
   294 //@doc(" Fibonacci numbers.")
   293 @main
   295 //@main
   294 def bfc3() = bf_run(bf3, "fibs")
   296 def bfc3() = bf_run(bf3, "fibs")
   295 
   297 
   296 // Mandelbrot Set
   298 // Mandelbrot Set
   297 //----------------
   299 //----------------
   298 //
   300 //
   299 // Note: Parsing of the generated WHILE program (around 60K in size)
   301 // Note: Parsing of the generated WHILE program (around 60K in size)
   300 // takes approximately 10 minutes to parse with our parser combinators,
   302 // takes approximately 10 minutes to parse with our parser combinators,
   301 // and approximately 30 seconds with Ammonite's fastparse.
   303 // and approximately 30 seconds with Ammonite's fastparse.
   302 
   304 
   303 //@doc(" Mandelbrot set.")
   305 //@doc(" Mandelbrot set.")
   304 @main
   306 //@main
   305 def bfc4() = bf_run(read(pwd / "mandelbrot.bf"), "mandelbrot")
   307 def bfc4() = bf_run(read(pwd / "mandelbrot.bf"), "mandelbrot")
   306 
   308 
   307 
   309 
   308 // this unfortunately hits the capacity of the JVM, even with optimisations
   310 // this unfortunately hits the capacity of the JVM, even with optimisations
   309 //@doc(" Coolatz serries up to 30.")
   311 //@doc(" Collatz series up to 30.")
   310 //@main
   312 //@main
   311 //def bfc5() = bf_run(read(pwd / "collatz.bf"), "coll")
   313 //def bfc5() = bf_run(read(pwd / "collatz.bf"), "coll")
   312 
   314 
   313 // this unfortunately hits the capacity of the JVM, even with optimisations
   315 // this unfortunately hits the capacity of the JVM, even with optimisations
   314 //@doc(" Towers of Hanoi.")
   316 //@doc(" Towers of Hanoi.")
   315 //@main
   317 //@main
   316 //def bfc6() = bf_run(read(pwd / "hanoi.bf"), "hanoi")
   318 //def bfc6() = bf_run(read(pwd / "hanoi.bf"), "hanoi")
   317 
   319 
   318 //
   320 //
   319 //@doc(" All benchmarks.")
   321 //@doc(" All benchmarks.")
   320 @main
   322 //@main
   321 def all() = { bfc0(); bfc1(); bfc2(); bfc3(); bfc4() } 
   323 def all() = { bfc0(); bfc1(); bfc2(); bfc3(); bfc4() } 
   322 
   324 
   323 
   325 all()
   324 
   326 
   325 
   327 
   326 
   328 
   327 */
   329 
       
   330 
       
   331 // old way to run it with Ammonite
       
   332 //
       
   333 // Call with (X being 0,1,..,4)
       
   334 //
       
   335 //  amm compile_bfc.sc all
       
   336 //  amm compile_bfc.sc bfcX
       
   337 //
       
   338 //
       
   339 // load the compiler
       
   340 //import $file.compile_arrays2
       
   341 //import compile_arrays2._ 
       
   342 //
       
   343 // load fastparse
       
   344 //import $ivy.`com.lihaoyi::fastparse:3.0.2`