はじめてのGo言語プログラミング
GDDで鵜飼さんのセッションを聞いてムラムラしたのでGo言語入門してみました。意外と公式サイトのドキュメントが充実していて素晴らしい。
HelloWorldの次に何試そうかなと考えて、そういえばBrainf*ckを今まで作ったことがなかったことを思い出したので、とりあえずGo言語の練習がてら作ってみます。正確にはBrainf*ckではなくてBrainCrashだけど。
getcharをどうやったらいいか分からなかったので「,」の実装が多分変ですが、(゚ε゚)キニシナイ!!
package main import ( "flag" "fmt" "bufio" "os" ) const ( PROMPT = "\n%% " ) var is_brainf_ck = false func read_line(file *os.File) string { line, _ := bufio.NewReader(file).ReadString('\n') return line } func braincrash(str string) { program := []byte(str) var memory [30000]byte p := 0 var curr byte if !is_brainf_ck { ini := "Hello, world!" for i := 0; i < len(ini); i++ { memory[i] = ini[i] } } for pc := 0; pc < len(program); pc++ { switch program[pc] { case '>': p++ case '<': p-- case '+': memory[p]++ case '-': memory[p]-- case '.': fmt.Printf("%c", memory[p]) case ',': memory[p] = read_line(os.Stdin)[0] case '[': if memory[p] == 0 { depth := 0 for { pc++ if program[pc] == '[' {depth += 1} if program[pc] == ']' { if depth == 0 { break } else { depth -= 1} } } } case ']': if memory[p] != 0 { depth := 0 for { pc-- if program[pc] == ']' {depth += 1} if program[pc] == '[' { if depth == 0 { break } else { depth -= 1} } } } } if !is_brainf_ck { switch program[pc] { case '|': curr = memory[p]; p++; memory[p] |= curr case '&': curr = memory[p]; p++; memory[p] &= curr case '~': memory[p] = ^memory[p] case '^': curr = memory[p]; p++; memory[p] ^= curr } } } if !is_brainf_ck { for i := p; memory[i] != 0; i++ { fmt.Printf("%c", memory[i]) } } } func read_and_braincrash(file *os.File) bool { program := read_line(file) if program == "exit\n" { return false } braincrash(program) return true } func main() { flag.BoolVar(&is_brainf_ck, "f", false, "brainf*ck mode") flag.Parse() if flag.NArg() == 0 { if is_brainf_ck { fmt.Printf("[BRAINF*CK MODE]\n") } fmt.Printf("Type 'exit' to exit") for { fmt.Printf(PROMPT) if !read_and_braincrash(os.Stdin) { break } } } else { filename := flag.Arg(0) file, err := os.Open(filename, os.O_RDONLY, 0666) if err == nil { read_and_braincrash(file) } } }
コンパイル&リンクはうちのマシンだと
$ 6g braincrash.go $ 6l -o braincrash braincrash.6
実行は
$ ./braincrash Type 'exit' to exit % |< Hmllo, world! % exit $
ちなみに「-f」をつけるとBrainf*ckモードになります。
$ ./braincrash -f [BRAINF*CK MODE] Type 'exit' to exit % +++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+. Hello, world! % exit $
このレベルなら特にクセもなくて使いやすそうな言語ですね。いや、もちろんBrainf*ckがではなくて、Go言語が。
次はやっぱりWhitespaceを作るべきなのかな。