ankoって素のgolang通すんですね、という誤解(多分)の旅

======

ankoとはGolangをベースとしたmattnさん謹製のスクリプト言語。 https://github.com/mattn/anko
スクリプト言語、というか、ストレスフリー言語な感じが素晴らしいです。
golangは全くの素人の自分でもアイデアをメモるぐらいは問題無いです。
しかも、結構速いらしい。https://twitter.com/mattn_jp/status/519461004145467393
ということで、サンプルいじってみました。それだけですので、以下、期待しないで下さい。
__失礼な内容等があったら訂正・削除しますのでご一報下さい。__

## githubにあったサンプル
https://github.com/mattn/anko/blob/master/_example/server.ank
これ、golangまんまなんですね。インラインで書けるのかー。（違うかも、、というか誤解であった模様

```
net.http.HandleFunc("/", net.http.toHandleFunc(func(w, r) {
w.Write(toBytes("hello world"))
}))
net.http.ListenAndServe(":8080", nil)

```
これを```svr.ank```として保存して、実行してみます

```
$ anko svr.ank
```

pid調べます

```
$ ps a | grep ank[o]
12375 s001  S+     0:00.02 anko svr.ank
```

curlで接続してみます

```
$ curl http://localhost:8080/
hello world
```

telnetでHTTP手打ちしてみます。
入力したリクエストヘッダは```GET / HTTP/1.0```のみです。

```
$ telnet localhost 8080
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.0

HTTP/1.0 200 OK
Date: Tue, 07 Oct 2014 16:14:12 GMT
Content-Length: 11
Content-Type: text/plain; charset=utf-8

hello worldConnection closed by foreign host.

```

プログラムのfootprintとかfdとかどういう風に接続されているのかlsofで見てみます(OSX10.9)

```
$ lsof -p 12375
COMMAND   PID     USER   FD     TYPE             DEVICE  SIZE/OFF      NODE NAME
anko    12375 watashi  cwd      DIR                1,1       102 136749708 /Users/watashi/currentworkingdirectory
anko    12375 watashi  txt      REG                1,1   9584716 136749447 /Users/watashi/gocode/bin/anko
anko    12375 watashi  txt      REG                1,1    271440 126755563 /System/Library/CoreServices/Encodings/libJapaneseConverter.dylib
anko    12375 watashi  txt      REG                1,1    600832 136460459 /usr/lib/dyld
anko    12375 watashi  txt      REG                1,1 344521854 136470017 /private/var/db/dyld/dyld_shared_cache_x86_64
anko    12375 watashi    0u     CHR               16,1   0t11590      3215 /dev/ttys001
anko    12375 watashi    1u     CHR               16,1   0t11590      3215 /dev/ttys001
anko    12375 watashi    2u     CHR               16,1   0t11590      3215 /dev/ttys001
anko    12375 watashi    3u    IPv6 0x8abaa65222cb7a41       0t0       TCP *:http-alt (LISTEN)
anko    12375 watashi    4u  KQUEUE                                        count=0, state=0x2
```

うーん、ankoのREPL(read–eval–print loop)インタープリタ？が動いてるだけの状態（下）と比べてTCPのポートとKQUEUEが増えているくらい。Listenしてるからですかね。

```
COMMAND   PID     USER   FD   TYPE DEVICE  SIZE/OFF      NODE NAME
anko    12451 watashi  cwd    DIR    1,1       102 136749708 /Users/watashi/currentworkingdirectory
anko    12451 watashi  txt    REG    1,1   9584716 136749447 /Users/watashi/gocode/bin/anko
anko    12451 watashi  txt    REG    1,1    271440 126755563 /System/Library/CoreServices/Encodings/libJapaneseConverter.dylib
anko    12451 watashi  txt    REG    1,1    600832 136460459 /usr/lib/dyld
anko    12451 watashi  txt    REG    1,1 344521854 136470017 /private/var/db/dyld/dyld_shared_cache_x86_64
anko    12451 watashi    0u   CHR   16,1   0t11625      3215 /dev/ttys001
anko    12451 watashi    1u   CHR   16,1   0t11625      3215 /dev/ttys001
anko    12451 watashi    2u   CHR   16,1   0t11625      3215 /dev/ttys001
```

## とりあえずコード見てみる、が、自前構文以外をどっかに丸投げする部分は無いように見える
見てたのは https://github.com/mattn/anko/commit/dda57c05b9542965c018a357acb7490ddc1b2131 の頃です。

インタプリターがコードを解釈する部分は https://github.com/mattn/anko/blob/master/anko.go#L134 のあたり。
最終的にはparser/parser.goの
https://github.com/mattn/anko/blob/master/parser/parser.go#L596 のあたりからかなぁ。
それそのまま読むのは苦痛なのでyaccのファイル(parser.go.y)の方を見ると。あれー、ライブラリ呼び出し```net.http.HandleFunc()```のようなものを特別扱いして素通しするようなところは無いような、、、

というか、https://github.com/mattn/anko/blob/master/parser/parser.go.y#L369　見ると、

```{/parser/parser.go.y}
expr : IDENT
 |
(中略)
 | expr '.' IDENT
{
$$ = &ast.MemberExpr{Expr: $1, Name: $3.Lit}
$$.SetPosition($1.Position())
}
```

ということで、モジュールのメンバ関数呼び出しは特別あつかいされず処理されているようだ。てっきりeval()みたいなのに丸投げかと、、、そりゃRubyが動的すぎるのか...

## ということは、、、主要なモジュールを自分で定義できる関数と同じ名前空間(?)で実装してる？/builtins ってそれ？

うわすご。。。。。Define

https://github.com/mattn/anko/blob/master/builtins/os/os.go

```{builtins/os/os.go}
package os

import (
	pkg_exec "github.com/mattn/anko/builtins/os/exec"
	"github.com/mattn/anko/vm"
	pkg "os"
	"reflect"
)

func Import(env *vm.Env) {
	m := env.NewModule("os")
	m.Define("Args", reflect.ValueOf(pkg.Args))

 (以下延々と、略）
	m.Define("TempDir", reflect.ValueOf(pkg.TempDir))
	m.Define("Truncate", reflect.ValueOf(pkg.Truncate))
	pkg_exec.Import(m)
}
```

## いやいやいやVMもすげぇ

vm.go https://github.com/mattn/anko/blob/master/vm/vm.go も手抜きなくASTを解釈しつつ、副作用があればgolangのランタイム（なのかどうかは自分は判断できないのですが）に反映してるようだ。。。

自分はこんなの（↓）を想像してた。本当にすみません。
http://lawlessguy.wordpress.com/2013/07/20/an-rpn-interpreter-in-go-golang/
いやいやいや、上の記事も自分には全然到達できないレベルなんですけど。。。。