-
Notifications
You must be signed in to change notification settings - Fork 259
Expand file tree
/
Copy pathbf.scala
More file actions
89 lines (74 loc) · 2.18 KB
/
bf.scala
File metadata and controls
89 lines (74 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import scala.collection.mutable.ArrayBuffer
sealed abstract class Op
case class Inc(v: Int) extends Op
case class Move(v: Int) extends Op
case class Loop(loop: Array[Op]) extends Op
case object Print extends Op
class Tape() {
private var tape: Array[Int] = Array(0)
private var pos: Int = 0
def get = tape(pos)
def inc(x: Int) = tape(pos) += x
def move(x: Int) = {
pos += x
while (pos >= tape.length) {
tape = Array.copyOf(tape, tape.length * 2)
}
}
}
class Program(text: String) {
val ops: Array[Op] = parse(text.iterator)
def parse(iterator: Iterator[Char]) : Array[Op] = {
val res = ArrayBuffer[Op]()
while (iterator.hasNext) {
iterator.next() match {
case '+' => res += Inc(1)
case '-' => res += Inc(-1)
case '>' => res += Move(1)
case '<' => res += Move(-1)
case '.' => res += Print
case '[' => res += Loop(parse(iterator))
case ']' => return res.toArray
case _ =>
}
}
res.toArray
}
def run = _run(ops, new Tape())
def _run(program: Array[Op], tape: Tape): Unit = {
for (op <- program) op match {
case Inc(x) => tape.inc(x)
case Move(x) => tape.move(x)
case Loop(loop) => while (tape.get > 0) _run(loop, tape)
case Print => print(tape.get.toChar)
}
}
}
object BrainFuck {
def time(f: => Any) = {
val s = System.nanoTime
val ret = f
System.err.println("time: "+(System.nanoTime-s)/1e9+"s")
ret
}
def notify(msg: String): Unit = {
scala.util.Using((new java.net.Socket("localhost", 9001)).getOutputStream()) {
_.write(msg.getBytes())
}
}
def main(args: Array[String]): Unit = {
val text = scala.util.Using(scala.io.Source.fromFile(args(0))) { _.mkString }.get
// JIT warming up
System.err.print("JIT warming up\n")
time {
new Program(">++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++[>++++++++<-]>[-]<<>++++++++++[>++++++++++[>++++++++++[>++++++++++[>++++++++++[>++++++++++[>++++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++").run
}
//
System.err.print("run\n")
notify(s"Scala\t${ProcessHandle.current().pid()}")
time {
new Program(text).run
}
notify("stop")
}
}