======
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 見ると、
expr : IDENT
|
(中略)
| expr '.' IDENT
{
$$ = &ast.MemberExpr{Expr: $1, Name: $3.Lit}
$$.SetPosition($1.Position())
}
ということで、モジュールのメンバ関数呼び出しは特別あつかいされず処理されているようだ。てっきりeval()みたいなのに丸投げかと、、、そりゃRubyが動的すぎるのか...
ということは、、、主要なモジュールを自分で定義できる関数と同じ名前空間(?)で実装してる?/builtins ってそれ?
うわすご。。。。。Define
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/
いやいやいや、上の記事も自分には全然到達できないレベルなんですけど。。。。